踐踏堆棧-緩沖區(qū)溢出漏洞

打算寫這篇文章是因?yàn)樵诰W(wǎng)上看過一篇論文软能,講了緩沖區(qū)溢出破壞堆棧來(lái)執(zhí)行惡意程序的漏洞。該論文請(qǐng)見參考資料1慌闭。這篇文章會(huì)涉及一些匯編的基礎(chǔ)知識(shí)别威,以及虛擬內(nèi)存的一些基本概念等。當(dāng)然用來(lái)調(diào)試程序的系統(tǒng)是linux驴剔,工具是gcc省古。很久沒有看過匯編和C語(yǔ)言了,錯(cuò)漏之處丧失,還請(qǐng)指正豺妓。這篇文章最早也是發(fā)在CSDN,有一些參考文章鏈接可能漏掉了,如果原作者看到科侈,麻煩指出载佳。

1 概要

文章標(biāo)題有提到堆棧和緩沖區(qū),那么就先來(lái)探討下這幾個(gè)名詞的定義臀栈。這里的緩沖區(qū),指的就是計(jì)算機(jī)內(nèi)一塊連續(xù)的內(nèi)存區(qū)域挠乳,可以保存相同數(shù)據(jù)類型的多個(gè)實(shí)例权薯。C程序員最常見的緩沖區(qū)就是字符數(shù)組了。與C語(yǔ)言中其他變量一樣睡扬,數(shù)組也可以聲明為靜態(tài)或動(dòng)態(tài)的盟蚣,靜態(tài)變量在程序加載時(shí)位于數(shù)據(jù)段,動(dòng)態(tài)變量位于堆棧之中(這一點(diǎn)我們可以很容易的寫個(gè)程序來(lái)驗(yàn)證卖怜,見exmple.c,使用命令gcc -m32 -S example.c將其編譯成32位匯編代碼,查看example.s即可看到數(shù)組a的數(shù)據(jù)分布在數(shù)據(jù)段中屎开,而數(shù)組b的數(shù)據(jù)則分布在堆棧中)。本文只探討動(dòng)態(tài)緩沖區(qū)的溢出問題马靠,即基于堆棧的緩沖區(qū)溢出奄抽。

/*exapmle.c*/
int main() {
    static int a[4] = {1, 2, 3, 4};
    int b[4] = {5, 6, 7, 8};
}

2 基礎(chǔ)知識(shí)

2.1 進(jìn)程內(nèi)存組織形式

既然本文要討論基于堆棧的緩沖區(qū)溢出,首先就來(lái)看看進(jìn)程的內(nèi)存組織結(jié)構(gòu)甩鳄。我們基本都知道逞度,進(jìn)程在內(nèi)存中的結(jié)構(gòu)可以簡(jiǎn)單的分為代碼段,數(shù)據(jù)段和堆棧段妙啃。代碼段位于內(nèi)存低地址档泽,而堆棧位于內(nèi)存高地址。當(dāng)然我們這里說(shuō)的內(nèi)存地址是指虛擬地址揖赴,具體物理地址是需要經(jīng)過MMU(內(nèi)存管理單元)進(jìn)行轉(zhuǎn)換得到馆匿。下面是一個(gè)進(jìn)程的內(nèi)存組織結(jié)構(gòu)圖:


圖2.1 進(jìn)程的內(nèi)存組織結(jié)構(gòu)圖
從圖2.1中可以看到,除了基本的代碼段燥滑,數(shù)據(jù)段渐北,還有未初始化數(shù)據(jù)段bss,堆heap突倍,內(nèi)存映射區(qū)域等腔稀。當(dāng)然我們這里的段的概念跟程序加載時(shí)的段是不一樣的,具體區(qū)別可以參見《Linux C一站式編程》18.5 ELF文件格式那一節(jié)的說(shuō)明羽历。

2.2 堆棧

堆棧是一種計(jì)算機(jī)中常用的抽象數(shù)據(jù)模型焊虏,其特征就是先進(jìn)先出,支持的操作主要就是PUSH和POP秕磷。PUSH操作是在堆棧頂部壓入一個(gè)元素诵闭,而POP操作則是彈出堆棧的頂部元素。

為什么會(huì)使用堆棧則是跟現(xiàn)代計(jì)算機(jī)設(shè)計(jì)相關(guān)。在高級(jí)編程語(yǔ)言如C語(yǔ)言疏尿,JAVA語(yǔ)言瘟芝,Python語(yǔ)言等編寫程序時(shí),經(jīng)常會(huì)用到函數(shù)(function)或者過程(procedure)褥琐。通常锌俱,一個(gè)函數(shù)調(diào)用可以像跳轉(zhuǎn)命令那樣改變程序的執(zhí)行流程,而函數(shù)執(zhí)行完畢后敌呈,又需要把控制權(quán)返回給函數(shù)之后的代碼指令贸宏,這種實(shí)現(xiàn)需要依靠堆棧來(lái)實(shí)現(xiàn)。當(dāng)然在函數(shù)的局部變量中磕洪,以及函數(shù)傳遞參數(shù)和返回值中都要用到堆棧吭练。

堆棧是一塊連續(xù)的內(nèi)存區(qū)域,堆棧既可以向上也可以向下增長(zhǎng)析显,這個(gè)依賴于具體實(shí)現(xiàn)鲫咽。在大部分的處理器如Intel,Motorola谷异,SPARC和MIPS中分尸,堆棧都是向下增長(zhǎng)的,即堆棧指針SP指向堆棧的頂部晰绎,堆棧底部是一個(gè)固定的地址寓落,堆棧大小在運(yùn)行時(shí)由內(nèi)核動(dòng)態(tài)調(diào)整。CPU實(shí)現(xiàn)指令PUSH和POP荞下,向堆棧中添加和移除元素伶选。

除了堆棧指針SP,為了方便還有一個(gè)指向幀內(nèi)固定地址的指針BP尖昏。從理論上來(lái)說(shuō)仰税,局部變量可以通過SP加偏移量來(lái)引用,然而抽诉,當(dāng)有字被壓入棧和出棧后陨簇,這些偏移就變化了。盡管有些情況下編譯器能夠跟蹤棧內(nèi)的操作變化迹淌,修正偏移量河绽,但是還有很多情況不能跟蹤,而且為了跟蹤偏移量的變化需要引入額外的管理開銷唉窃。因此很多編譯器會(huì)使用第二個(gè)寄存器BP耙饰,局部變量和函數(shù)參數(shù)都可以引用它,因?yàn)榫植孔兞亢秃瘮?shù)參數(shù)到BP的距離不受PUSH和POP操作的影響纹份。

2.3 函數(shù)調(diào)用中棧幀分析

為了利用緩沖區(qū)溢出苟跪,需要知道函數(shù)調(diào)用中棧幀變化和布局情況廷痘,這里就不分析了,已經(jīng)有很好的文章詳細(xì)說(shuō)過這個(gè)問題件已,參見宋勁松老師的《linux C一站式編程》19.1節(jié)函數(shù)調(diào)用笋额。

3 緩沖區(qū)溢出

好了,做了一些準(zhǔn)備工作后篷扩,可以來(lái)看看這個(gè)緩沖區(qū)溢出的問題了兄猩。 首先看下面的代碼example1.c,我們分析下函數(shù)棧幀的分布鉴未。

/*example2.c*/
void function(int a, int b, int c) {
   char buffer1[5];
   char buffer2[10];
}

void main() {
  function(1,2,3);
}

運(yùn)行命令:gcc -S -fno-stack-protector example1.c,通過分析example1.s文件得出 函數(shù)棧幀分布如下所示(我的運(yùn)行環(huán)境是32位的ubuntu11.04):

c (高地址)
b
a
ret
ebp
buffer1
buffer2 (低地址)

接下來(lái)看一個(gè)通過覆蓋返回地址造成段錯(cuò)誤的情況厦滤。見example2.c。

/*example2.c*/
void function(char *str) {
   char buffer[16];
   strcpy(buffer,str);
}

void main() {
  char large_string[256];
  int i;
  for( i = 0; i < 255; i++)
    large_string[i] = 'A';
  function(large_string);
}

example2.c是一個(gè)典型的緩沖區(qū)溢出的例子歼狼,strcpy拷貝的數(shù)據(jù)超過了16個(gè)字節(jié),導(dǎo)致溢出代碼覆蓋了棧中保存的ebp值以及返回地址ret享怀,而函數(shù)返回時(shí)會(huì)從棧中取返回地址ret接著執(zhí)行下一條指令羽峰,該地址不合法,從而導(dǎo)致段錯(cuò)誤添瓷。而如果用一個(gè)合法地址來(lái)覆蓋返回地址ret梅屉,這樣就可以修改程序執(zhí)行流程了。

接下來(lái)鳞贷,修改example2.c坯汤,通過緩沖區(qū)溢出修改返回地址ret來(lái)修改程序執(zhí)行流程。如example3.c所示搀愧。

/*example3.c*/
void function(int a, int b, int c)
{
    int *ret;
    char buffer1[5];
    char buffer2[10];
    ret = buffer1 + 13;
    (*ret) += 8;
}

void main()
{
    int x = 0;
    function(1,2,3);
    x = 1;
    printf("%d\n", x);
}

使用命令gcc -o example3 -fno-stack-protector example3.c編譯惰聂,可以看到棧幀分布如下所示:

c (高地址)| b  | a | ret(返回地址) |  ebp |  ret (局部變量ret) | buffer1  | buffer2 (低地址)|

因此,通過ret=buffer1+13咱筛,可以獲得返回地址ret的地址搓幌。這里之所以加13,是buffer1的5字節(jié)+局部變量ret的4字節(jié)+ebp的4字節(jié)迅箩。調(diào)用function函數(shù)后溉愁,返回地址本應(yīng)該是x=1指令地址,(*ret) += 8將返回地址ret加8饲趋,這樣就跳過了x=1這條指令拐揭,example3.c編譯后執(zhí)行的結(jié)果是0。注意必須加上-fno-stack-protector奕塑,因?yàn)間cc默認(rèn)存在堆棧保護(hù)技術(shù)堂污,那樣會(huì)防止返回地址被改寫,如果返回地址被惡意修改爵川,會(huì)報(bào)段錯(cuò)誤敷鸦。GCC編譯器堆棧保護(hù)技術(shù)詳見該文鏈接

接下來(lái)可以通過緩沖區(qū)溢出來(lái)執(zhí)行shell代碼,這個(gè)留待下一篇文章再說(shuō)了扒披,內(nèi)容太長(zhǎng)值依,現(xiàn)在還沒有看完。

參考資料

stack smashing
GCC編譯器堆棧保護(hù)技術(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碟案,一起剝皮案震驚了整個(gè)濱河市愿险,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌价说,老刑警劉巖辆亏,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鳖目,居然都是意外死亡扮叨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門领迈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)彻磁,“玉大人,你說(shuō)我怎么就攤上這事狸捅≈则眩” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵尘喝,是天一觀的道長(zhǎng)磁浇。 經(jīng)常有香客問我,道長(zhǎng)朽褪,這世上最難降的妖魔是什么置吓? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮鞍匾,結(jié)果婚禮上交洗,老公的妹妹穿的比我還像新娘。我一直安慰自己橡淑,他們只是感情好构拳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著梁棠,像睡著了一般置森。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上符糊,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天凫海,我揣著相機(jī)與錄音,去河邊找鬼男娄。 笑死行贪,一個(gè)胖子當(dāng)著我的面吹牛漾稀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播建瘫,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼崭捍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了啰脚?” 一聲冷哼從身側(cè)響起殷蛇,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎橄浓,沒想到半個(gè)月后粒梦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荸实,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年匀们,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片准给。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昼蛀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出圆存,到底是詐尸還是另有隱情,我是刑警寧澤仇哆,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布沦辙,位于F島的核電站,受9級(jí)特大地震影響讹剔,放射性物質(zhì)發(fā)生泄漏油讯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一延欠、第九天 我趴在偏房一處隱蔽的房頂上張望陌兑。 院中可真熱鬧,春花似錦由捎、人聲如沸兔综。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)软驰。三九已至,卻和暖如春心肪,著一層夾襖步出監(jiān)牢的瞬間锭亏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工硬鞍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慧瘤,地道東北人戴已。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像锅减,于是被迫代替她去往敵國(guó)和親糖儡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容