日韩性视频-久久久蜜桃-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ò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 波多野结衣黄色 | 女人久久 | 国产热99| 57pao国产成永久免费视频 | 手机看片日韩在线 | 黄色欧美一级片 | 内射无码专区久久亚洲 | 爱情岛亚洲论坛入口福利 | 国产片天天弄 | 人操人爽| 亚洲天堂五月 | 亚洲人成一区 | 香蕉视频色 | 摸大乳喷奶水www视频 | 蜜臀av性久久久久蜜臀aⅴ | 波多av在线| 男女黄床上色视频 | 国产精品高潮视频 | 国产高潮国产高潮久久久 | 51精品国自产在线 | 91久久综合精品国产丝袜蜜芽 | 国产资源第一页 | 成人亚洲一区二区 | 四虎免费影视 | 亚洲国产成人精品女人久久 | 中文视频一区 | 91在线视频观看 | 国产ts三人妖大战直男 | 日本在线中文 | 日韩第1页 | 精品在线一区二区三区 | 国产最新在线 | 狠狠亚洲 | 啪啪网站大全 | 男女激情免费网站 | 国产精品98| 成人性做爰aaa片免费看不忠 | 91av免费| 乳色吐息免费看 | 外国黄色网| 日韩精品在线电影 | 午夜精品久久久久久久99老熟妇 | 国产精品videossex久久发布 | 在线成人日韩 | 天啪| 长腿校花无力呻吟娇喘的视频 | 三男一女吃奶添下面 | 欧美另类自拍 | 韩日产理伦片在线观看 | 91色网站 | 曰本无码人妻丰满熟妇啪啪 | aaa毛片视频 | 草草影院第一页 | 亚洲第一色站 | 妖精视频一区二区三区 | 欧美午夜精品 | 国产一区黄 | 日本高清免费视频 | 中国女人内谢69xxxxⅹ视频 | 成人精品视频一区二区 | 亚洲专区欧美 | 国产一区二区播放 | 91看片网站 | 国产九九 | 亚洲成人不卡 | 欧美看片| 日韩无砖 | 国产激情成人 | 玖玖色资源| 国产寡妇亲子伦一区二区三区四区 | 欧美一级淫片免费视频黄 | 久久久久中文字幕亚洲精品 | 丁香婷婷一区二区三区 | 欧美日韩综合 | 精品国产一区二区三区日日嗨 | 国产女人叫床高潮大片免费 | 中文字幕一区二区三区乱码在线 | 岛国精品在线播放 | 九七精品 | 日韩成年人视频 | 特黄老太婆aa毛毛片 | 蜜桃精品视频在线 | 午夜一级大片 | 中出av在线 | 91爱| 一区二区日本视频 | 97精品人妻一区二区三区蜜桃 | 99精品久久毛片a片 成人网一区 | avtt亚洲| 亚洲中文字幕无码一区二区三区 | 久操超碰 | 国产a级一级片 | 午夜在线免费观看 | 自拍偷拍21p | 91在线播放国产 | 欧美精品成人一区二区在线观看 | 北岛玲在线 | 久久9久久 | 无码人妻aⅴ一区二区三区玉蒲团 |