日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

从函数调用过程中的堆栈变化理解缓冲区溢出

發(fā)布時(shí)間:2025/5/22 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从函数调用过程中的堆栈变化理解缓冲区溢出 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、說(shuō)明

本來(lái)是想直接寫一個(gè)緩沖區(qū)溢出的例子,但是一是當(dāng)前編譯器和操作系統(tǒng)有溢出的保護(hù)措施沒(méi)有完全弄清怎么取消,二是strcpy等遇到00會(huì)截?cái)嘈枰M(jìn)行編碼這比較難搞,所以最終沒(méi)有實(shí)現(xiàn)。

但已經(jīng)雙看了一陣函數(shù)的調(diào)用過(guò)程,如果全然就此放棄那以后再研究緩沖區(qū)溢出又得從0開(kāi)始研究函數(shù)的調(diào)用,所以就記些東西下來(lái),免得以后雙得從0開(kāi)始。

在緩沖區(qū)溢出中堆棧變化是最為關(guān)鍵的,本文從堆棧入手。

?

二、函數(shù)調(diào)用過(guò)程中的堆棧變化

2.1 使用程序

本文使用程序源代碼如下(編寫時(shí)我創(chuàng)建了一個(gè)StackChange工程,將源代碼保存為StackChange.c),使用vc++ 6.0編譯,使用olldbg逆向。

#include <stdio.h>int get_sum(int a, int b) {int sum;sum = a + b;printf("get_sum: calc sum success, now will return\n");return sum; }int main(int argc, char **argv) {int a = 1;int b = 2;int sum;sum = get_sum(a,b);printf("main: the sum is %d\n", sum);return 1; }

?

2.2 堆棧在內(nèi)存地址空間中的位置

今早等公交的時(shí)候看到一個(gè)問(wèn)題大意是,如果堆棧不可執(zhí)行那么程序?yàn)槭裁催€可以執(zhí)行,從概念上說(shuō)堆棧段和代碼段沒(méi)關(guān)系所以堆棧段不可執(zhí)行代碼段還可以執(zhí)行。

但我想這位小哥根本上是想知道,堆棧段和代碼段分別在內(nèi)存的什么位置,為什么堆棧段不可執(zhí)行代碼段還可執(zhí)行。

將2.1中的程序編譯后,使用olldbg載入exe,然后打開(kāi)內(nèi)存窗口(M),如下圖:

圖中各種信息都很明了了,具體到堆棧段和代碼段的位置,堆棧段為0x0018e000-0x00190000(因?yàn)閟ize為0x2000),代碼段為0x00401000-0x00422000(因?yàn)閟ize為0x2100)。所以堆棧段不可執(zhí)行,不影向代碼段可不可執(zhí)行。

?

2.3 函數(shù)調(diào)用在匯編上的過(guò)程

main函數(shù)匯編解析,說(shuō)明看其中的注釋:

get_sum函數(shù)匯編解析如下,流程和main函數(shù)是類似的(應(yīng)該說(shuō)所有函數(shù)的流程框架都是這樣的)不重復(fù)注釋,需要注意的就是獲取參數(shù)是使用ebp+8的形式回頭獲取的

?

2.4 函數(shù)調(diào)用過(guò)程中的堆棧變化

應(yīng)該很多人和我一樣2.3中的函數(shù)調(diào)用過(guò)程聽(tīng)了一萬(wàn)遍了,只是下次還是記不住;想以此去理解緩沖區(qū)溢出更是浮沙筑臺(tái),一知半解,過(guò)后又忘。

我想了想其癥結(jié)在于我們總嘗試去死記硬背這個(gè)過(guò)程,重點(diǎn)放在代碼段上。

而如果我們從整個(gè)程序內(nèi)存空間在程序執(zhí)行過(guò)程中的變化情況,就會(huì)發(fā)現(xiàn)代碼段區(qū)域和數(shù)據(jù)段區(qū)域內(nèi)容都是不變的,只有堆棧段內(nèi)容才會(huì)變(當(dāng)然寄存器也是變化的但寄存器不在內(nèi)存中)。

或者換言之,整個(gè)0x00000000-0xffffffff內(nèi)存地址空間,從程序運(yùn)行到進(jìn)程結(jié)束,只有堆棧部分的內(nèi)存即0x0018e000-0x00190000是會(huì)變的,其他部分在初始化后都是不變的。

所以也許重點(diǎn)放在堆棧段上,也許我們能更好更解函數(shù)調(diào)用過(guò)程。

(此時(shí)想起兩年前去面試,面試官問(wèn)輸入的用戶名密碼存到哪了,回答存內(nèi)存了,得到基礎(chǔ)薄弱的評(píng)價(jià),當(dāng)時(shí)是有些不忿的;現(xiàn)在想來(lái)內(nèi)存是0x00000000-0xffffffff,而別人想要的是0x0018e000-0x00190000這么一小段,差距確實(shí)是有點(diǎn)大)

?

2.4.1 堆棧在函數(shù)層次的變化

以下是olldbg進(jìn)入get_sum函數(shù)的printf函數(shù)內(nèi)部時(shí)的各函數(shù)堆棧情況(0x0018fe6c-0x0018ff4c):

以下是olldbg進(jìn)入main函數(shù)的printf函數(shù)內(nèi)部時(shí)各函數(shù)的堆棧情況(0x0018fe6c-0x0018ff4c):

從以上兩圖中的變化我們可以部結(jié)出以下幾點(diǎn):

1. 棧從高地址向低地址生長(zhǎng)。我們前邊說(shuō)過(guò)棧地址空間為0x0018e000-0x00190000,這里main并沒(méi)有從0x00190000開(kāi)始是因?yàn)閙ain函數(shù)其實(shí)是被系統(tǒng)函數(shù)調(diào)用啟動(dòng)的,并不能一開(kāi)始就是main函數(shù)。見(jiàn)下圖。

2. 層次為父子關(guān)系的函數(shù)(比如這里的main和get_sum、get_sum和其中的printf),父函數(shù)的堆棧在高地址子函數(shù)的堆棧在緊接父函數(shù)堆棧的低地址。

3. 層次為兄弟關(guān)系的函數(shù)(比如這里的get_sum和main函數(shù)的中的printf),前一函數(shù)調(diào)用完后其堆棧被釋放歸回未使用,后一函數(shù)執(zhí)行時(shí)使用的堆棧和前一函數(shù)一樣(開(kāi)始地址一樣,結(jié)束地址一般不一樣,畢竟各自局部變量需要的空間不一樣)

4.堆棧在使用時(shí)初始化在釋放時(shí)不初始化。比如上邊我們已進(jìn)入到main函數(shù)的printf,但get_sum未被占用的那部份和get_sum中的printf的堆棧共保留的內(nèi)容還和原來(lái)一樣。

?

2.4.2 單個(gè)函數(shù)內(nèi)部的堆棧空間分析

我們使用前邊“olldbg進(jìn)入get_sum函數(shù)的printf函數(shù)內(nèi)部時(shí)的各函數(shù)堆棧情況”時(shí)的圖來(lái)看get_sum函數(shù)堆棧的內(nèi)容

我們將get_sum堆棧空間轉(zhuǎn)化為以下表格:

對(duì)應(yīng)圖中地址內(nèi)容說(shuō)明
0x0018FE84ebp(get_sum函數(shù)的)這其實(shí)是printf函數(shù)中的push ebp
0x0018FE88eip(printf返回get_sum的)這是get_sum函數(shù)中call printf壓入棧的
0x0018FE8C形參(printf的)?
0x0018FE90edi(main函數(shù)的)如果不調(diào)用參數(shù),或調(diào)用參數(shù)返回后,esp指向此處
0x0018FE94esi(main函數(shù)的)?
0x0018FE98ebx(main函數(shù)的)?
0x0018FE9C-0x0018FED8預(yù)留空間編譯器總會(huì)給比參數(shù)需要的空間多一些的空間,malloc的話會(huì)從0x0018FE9C往0x0018FED8方向使用
0x0018FEDC局部變量已使用空間所謂緩沖區(qū)溢出,就是此處的參數(shù)長(zhǎng)度溢出,向后覆蓋0x0018FEE4處的eip
0x0018FEE0ebp(main函數(shù)的)這是get_sum函數(shù)形頭push ebp壓入棧的
0x0018FEE4eip(get_sum返回main的)這是main函數(shù)中的call get_sum壓入棧的,不屬于get_sum的堆棧空間

?

?

?

?

?

?

?

?

?

?

?

?

?

?

三、緩沖區(qū)溢出

3.1 緩沖區(qū)溢出利用的原理

緩沖區(qū)溢出:給本函數(shù)局部變量賦的值其長(zhǎng)度超過(guò)了變量定義的長(zhǎng)度

結(jié)合2.4.2最后的表格中我們可以得到緩沖區(qū)溢出利用的原理就是:給本函數(shù)局部變量賦長(zhǎng)度超過(guò)其定義長(zhǎng)度的值,使本函數(shù)返回上層函數(shù)的eip值被覆蓋成自己想去執(zhí)行的語(yǔ)句的地址。

如果這個(gè)定義還感覺(jué)不是很明了,那我們舉個(gè)例子:main函數(shù)調(diào)用了vuln_fun函數(shù),vuln_fun函數(shù)調(diào)用了strcpy,strcpy沒(méi)注意長(zhǎng)度會(huì)引發(fā)緩沖區(qū)溢出。此時(shí)溢出發(fā)生在vuln_fun函數(shù)的堆棧中,而被覆蓋的eip是vuln_fun執(zhí)行完返回main的eip。

所以可以給緩沖區(qū)溢出漏洞下一個(gè)更簡(jiǎn)單的定義:緩沖區(qū)溢出發(fā)生在調(diào)用strcpy/strcat/sprintf/vsprintf/gets/scanf的函數(shù)中,被覆蓋的eip是該函數(shù)返回上層函數(shù)的eip。

?

3.2 緩沖區(qū)溢出利用的難點(diǎn)

3.2.1 不考慮系統(tǒng)與編譯器無(wú)保護(hù)機(jī)制時(shí)的難點(diǎn)

在給變量賦的超長(zhǎng)字符串中包含以下三部份內(nèi)容:填充數(shù)據(jù)、注入的要執(zhí)行的匯編語(yǔ)句、注入的要執(zhí)行的匯編語(yǔ)句的地址。

填充數(shù)據(jù),隨便點(diǎn)就行了不是難點(diǎn)。

注入的要執(zhí)行的匯編語(yǔ)句,在不考慮編譯器和系統(tǒng)保護(hù)機(jī)制的情況下,大概是把自己要執(zhí)行的語(yǔ)句寫成c程序,然后編譯成exe,然后再把語(yǔ)句對(duì)應(yīng)的十六進(jìn)制dump出來(lái)就行了;不過(guò)strcpy等函數(shù)遇到00會(huì)認(rèn)為字符串結(jié)束,而期望dump出的十六進(jìn)制剛好沒(méi)有00是不太現(xiàn)實(shí)的,需要對(duì)其進(jìn)行編碼處理。

注入的要執(zhí)行的匯編語(yǔ)句的地址,這又有兩個(gè)難點(diǎn):一是要確定變量到eip的距離,以便剛好能在eip的位置寫入想要執(zhí)行的代碼的地址;二是要確定注入的、想要執(zhí)行的代碼的地址是多少。

?

3.2.2 編譯器與操作系統(tǒng)的保護(hù)措施

編譯器有棧不可執(zhí)行、棧保護(hù)兩種措施,編譯器與操作系統(tǒng)聯(lián)動(dòng)則還有內(nèi)存布局隨機(jī)化。更具體內(nèi)容可參考:https://www.jianshu.com/p/47d484b9227e

?

3.2.3 為什么很多overflow的cve沒(méi)有exp

長(zhǎng)期以來(lái),我都將存在緩沖區(qū)溢出漏洞等同于系統(tǒng)命令執(zhí)行、等同于系統(tǒng)淪陷。但很多overflow類型的cve都只是評(píng)分“很低”的dos而不是execute code,而且只有極少數(shù)才有exp,這很令人不解。

而基于以上難點(diǎn)的討論,這種現(xiàn)像就好理解了,緩沖區(qū)溢出到導(dǎo)致程序運(yùn)行出錯(cuò)所以基本都能dos,但由于編寫shellcode本身就比較困難再加上各種保護(hù)機(jī)制,有溢出不是必然就有exp的。

?

參考:

https://www.jianshu.com/p/47d484b9227e

https://www.shiyanlou.com/courses/231

https://www.cnblogs.com/yejianyong/p/7506465.html

https://blog.csdn.net/nicholas199109/article/details/8560988

轉(zhuǎn)載于:https://www.cnblogs.com/lsdb/p/9547380.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的从函数调用过程中的堆栈变化理解缓冲区溢出的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩1级片 | 在线一区二区三区 | 91在线欧美| 一级aaaa毛片 | 深夜福利网| 日韩制服在线 | jizz中国女人 | 秋霞影院一区二区 | 在线看91 | 在线观看一区二区视频 | 日本色呦呦 | 96看片| 亚洲永久在线观看 | 国产精品伦一区 | 逼逼av网站 | 日韩v欧美| 国产成人精品一区二区三区视频 | 男男啪啪无遮挡 | 九七影院在线观看免费观看电视 | 色欲亚洲Av无码精品天堂 | 欧美视频一区二区在线 | 久久国产露脸精品国产 | 综合av网| 国产v综合v亚洲欧美久久 | 国产91精品高潮白浆喷水 | 草啪啪 | 亚洲av无一区二区三区怡春院 | 99国产精品免费视频 | 婷婷五综合 | av美女在线 | www.avcao | 亚洲青青草 | 婷婷综合 | 哪里可以看毛片 | 成年人黄色片网站 | 国产又色又爽无遮挡免费动态图 | 理论片一区 | 国产伊人网| 亚洲AV蜜桃永久无码精品性色 | 午夜高清视频 | 打屁股调教视频 | 亚洲av中文无码乱人伦在线视色 | 中文字幕永久在线播放 | 天天干天天干天天干 | 久久免费黄色网址 | 第一页国产 | 国产欧美日韩综合精品一区二区 | 欧美特级特黄aaaaaa在线看 | 黑人玩弄人妻一区二区绿帽子 | 麻豆av在线看 | 综合久久影院 | 色天天av | 欧美一区二区三 | 肉嫁高柳家 高清 | 自拍在线视频 | 国产一区精品在线 | 亚洲视频自拍 | 林天顾悦瑶笔趣阁 | 99在线精品视频免费观看20 | 午夜影院 | 亚洲天堂777| 福利免费在线观看 | 五月婷婷丁香久久 | 婷婷九九 | 精品人伦一区二区三 | 99自拍视频在线观看 | 美女啪啪网 | 欧美日韩二区三区 | 91视频综合网| 亚洲午夜在线视频 | 糖心视频在线 | 中文字幕亚洲无线码在线一区 | 99re这里只有精品66 | 深爱五月激情五月 | 美女国产免费 | 特级西西444www大精品视频免费看 | 来吧亚洲综合网 | 伊人久久影院 | 日韩青青草 | 老牛影视av一区二区在线观看 | 久久精品无码av | 麻豆免费网站 | xxxx.国产 | 天堂资源在线 | 成a人v| 噜噜狠狠狠狠综合久久 | 人人人插| 欧美老女人视频 | 国产欧美一区二区在线 | 免费国产黄色 | 中文字幕日韩有码 | 黄色免费视频观看 | 国产精品成av人在线视午夜片 | 亚洲图片欧美另类 | 精品少妇一二三区 | 久久在线播放 | 一级二级av| 久久av一区二区三区漫画 | 杨幂毛片午夜性生毛片 |