青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Shuffy

不斷的學習,不斷的思考,才能不斷的進步.Let's do better together!
posts - 102, comments - 43, trackbacks - 0, articles - 19

windows進程中的內存結構

Posted on 2007-04-13 22:49 Shuffy 閱讀(149) 評論(0)  編輯 收藏 引用 所屬分類: VC++/C/C++/C#瀏覽集合

信息來源:中國源碼下載站

接觸過編程的人都知道,高級語言都能通過變量名來訪問內存中的數據。那么這些變量在內存中是如何存放的呢?程序又是如何使用這些變量的呢?下面就會對此進行深入的討論。下文中的C語言代碼如沒有特別聲明,默認都使用VC編譯的release版。 
首先,來了解一下 C 語言的變量是如何在內存分部的。C 語言有全局變量(Global)、本地變量(Local),靜態變量(Static)、寄存器變量(Regeister)。每種變量都有不同的分配方式。先來看下面這段代碼: 
#include <stdio.h> 
int g1=0, g2=0, g3=0; 
int main() 

static int s1=0, s2=0, s3=0; 
int v1=0, v2=0, v3=0; 
//打印出各個變量的內存地址 
printf("0x%08x\n",&v1); //打印各本地變量的內存地址 
printf("0x%08x\n",&v2); 
printf("0x%08x\n\n",&v3); 
printf("0x%08x\n",&g1); //打印各全局變量的內存地址 
printf("0x%08x\n",&g2); 
printf("0x%08x\n\n",&g3); 
printf("0x%08x\n",&s1); //打印各靜態變量的內存地址 
printf("0x%08x\n",&s2); 
printf("0x%08x\n\n",&s3); 
return 0; 

編譯后的執行結果是: 
0x0012ff78 
0x0012ff7c 
0x0012ff80 
0x004068d0 
0x004068d4 
0x004068d8 
0x004068dc 
0x004068e0 
0x004068e4 
輸出的結果就是變量的內存地址。其中v1,v2,v3是本地變量,g1,g2,g3是全局變量,s1,s2,s3是靜態變量。你可以看到這些變量在內存是連續分布的,但是本地變量和全局變量分配的內存地址差了十萬八千里,而全局變量和靜態變量分配的內存是連續的。這是因為本地變量和全局/靜態變量是分配在不同類型的內存區域中的結果。對于一個進程的內存空間而言,可以在邏輯上分成3個部份:代碼區,靜態數據區和動態數據區。動態數據區一般就是“堆棧”。“棧(stack)”和“堆(heap)”是兩種不同的動態數據區,棧是一種線性結構,堆是一種鏈式結構。進程的每個線程都有私有的“棧”,所以每個線程雖然代碼一樣,但本地變量的數據都是互不干擾。一個堆棧可以通過“基地址”和“棧頂”地址來描述。全局變量和靜態變量分配在靜態數據區,本地變量分配在動態數據區,即堆棧中。程序通過堆棧的基地址和偏移量來訪問本地變量。 

├———————┤低端內存區域 
│ …… │ 
├———————┤ 
│ 動態數據區 │ 
├———————┤ 
│ …… │ 
├———————┤ 
│ 代碼區 │ 
├———————┤ 
│ 靜態數據區 │ 
├———————┤ 
│ …… │ 
├———————┤高端內存區域 

堆棧是一個先進后出的數據結構,棧頂地址總是小于等于棧的基地址。我們可以先了解一下函數調用的過程,以便對堆棧在程序中的作用有更深入的了解。不同的語言有不同的函數調用規定,這些因素有參數的壓入規則和堆棧的平衡。windows API的調用規則和ANSI C的函數調用規則是不一樣的,前者由被調函數調整堆棧,后者由調用者調整堆棧。兩者通過“__stdcall”和“__cdecl”前綴區分。先看下面這段代碼: 
#include <stdio.h> 
void __stdcall func(int param1,int param2,int param3) 

int var1=param1; 
int var2=param2; 
int var3=param3; 
printf("0x%08x\n",&para;m1); //打印出各個變量的內存地址 
printf("0x%08x\n",&para;m2); 
printf("0x%08x\n\n",&para;m3); 
printf("0x%08x\n",&var1); 
printf("0x%08x\n",&var2); 
printf("0x%08x\n\n",&var3); 
return; 

int main() 

func(1,2,3); 
return 0; 

編譯后的執行結果是: 
0x0012ff78 
0x0012ff7c 
0x0012ff80 
0x0012ff68 
0x0012ff6c 
0x0012ff70 

├———————┤<—函數執行時的棧頂(ESP)、低端內存區域 
│ …… │ 
├———————┤ 
│ var 1 │ 
├———————┤ 
│ var 2 │ 
├———————┤ 
│ var 3 │ 
├———————┤ 
│ RET │ 
├———————┤<—“__cdecl”函數返回后的棧頂(ESP) 
│ parameter 1 │ 
├———————┤ 
│ parameter 2 │ 
├———————┤ 
│ parameter 3 │ 
├———————┤<—“__stdcall”函數返回后的棧頂(ESP) 
│ …… │ 
├———————┤<—棧底(基地址 EBP)、高端內存區域 

上圖就是函數調用過程中堆棧的樣子了。首先,三個參數以從又到左的次序壓入堆棧,先壓“param3”,再壓“param2”,最后壓入“param1”;然后壓入函數的返回地址(RET),接著跳轉到函數地址接著執行(這里要補充一點,介紹UNIX下的緩沖溢出原理的文章中都提到在壓入RET后,繼續壓入當前EBP,然后用當前ESP代替EBP。然而,有一篇介紹windows下函數調用的文章中說,在windows下的函數調用也有這一步驟,但根據我的實際調試,并未發現這一步,這還可以從param3和var1之間只有4字節的間隙這點看出來);第三步,將棧頂(ESP)減去一個數,為本地變量分配內存空間,上例中是減去12字節(ESP=ESP-3*4,每個int變量占用4個字節);接著就初始化本地變量的內存空間。由于“__stdcall”調用由被調函數調整堆棧,所以在函數返回前要恢復堆棧,先回收本地變量占用的內存(ESP=ESP+3*4),然后取出返回地址,填入EIP寄存器,回收先前壓入參數占用的內存(ESP=ESP+3*4),繼續執行調用者的代碼。參見下列匯編代碼: 
;--------------func 函數的匯編代碼------------------- 
:00401000 83EC0C sub esp, 0000000C //創建本地變量的內存空間 
:00401003 8B442410 mov eax, dword ptr [esp+10] 
:00401007 8B4C2414 mov ecx, dword ptr [esp+14] 
:0040100B 8B542418 mov edx, dword ptr [esp+18] 
:0040100F 89442400 mov dword ptr [esp], eax 
:00401013 8D442410 lea eax, dword ptr [esp+10] 
:00401017 894C2404 mov dword ptr [esp+04], ecx 
……………………(省略若干代碼) 
:00401075 83C43C add esp, 0000003C ;恢復堆棧,回收本地變量的內存空間 
:00401078 C3 ret 000C ;函數返回,恢復參數占用的內存空間 
;如果是“__cdecl”的話,這里是“ret”,堆棧將由調用者恢復 
;-------------------函數結束------------------------- 

;--------------主程序調用func函數的代碼-------------- 
:00401080 6A03 push 00000003 //壓入參數param3 
:00401082 6A02 push 00000002 //壓入參數param2 
:00401084 6A01 push 00000001 //壓入參數param1 
:00401086 E875FFFFFF call 00401000 //調用func函數 
;如果是“__cdecl”的話,將在這里恢復堆棧,“add esp, 0000000C” 
聰明的讀者看到這里,差不多就明白緩沖溢出的原理了。先來看下面的代碼: 
#include <stdio.h> 
#include <string.h> 
void __stdcall func() 

char lpBuff[8]="\0"; 
strcat(lpBuff,"AAAAAAAAAAA"); 
return; 

int main() 

func(); 
return 0; 

編譯后執行一下回怎么樣?哈,“"0x00414141"指令引用的"0x00000000"內存。該內存不能為"read"。”,“非法操作”嘍!"41"就是"A"的16進制的ASCII碼了,那明顯就是strcat這句出的問題了。"lpBuff"的大小只有8字節,算進結尾的’\0’,那strcat最多只能寫入7個"A",但程序實際寫入了11個"A"外加1個’\0’。再來看看上面那幅圖,多出來的4個字節正好覆蓋了RET的所在的內存空間,導致函數返回到一個錯誤的內存地址,執行了錯誤的指令。如果能精心構造這個字符串,使它分成三部分,前一部份僅僅是填充的無意義數據以達到溢出的目的,接著是一個覆蓋RET的數據,緊接著是一段shellcode,那只要著個RET地址能指向這段shellcode的第一個指令,那函數返回時就能執行shellcode了。但是軟件的不同版本和不同的運行環境都可能影響這段shellcode在內存中的位置,那么要構造這個RET是十分困難的。一般都在RET和shellcode之間填充大量的NOP指令,使得exploit有更強的通用性。 

├———————┤<—低端內存區域 
│ …… │ 
├———————┤<—由exploit填入數據的開始 
│ │ 
│ buffer │<—填入無用的數據 
│ │ 
├———————┤ 
│ RET │<—指向shellcode,或NOP指令的范圍 
├———————┤ 
│ NOP │ 
│ …… │<—填入的NOP指令,是RET可指向的范圍 
│ NOP │ 
├———————┤ 
│ │ 
│ shellcode │ 
│ │ 
├———————┤<—由exploit填入數據的結束 
│ …… │ 
├———————┤<—高端內存區域

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产亚洲精品久久久久婷婷瑜伽| 久久免费视频在线| 亚洲欧美日韩国产综合精品二区| 欧美77777| 亚洲高清中文字幕| 日韩视频精品在线| 久久久午夜电影| 亚洲美女av黄| 香蕉免费一区二区三区在线观看| 欧美日韩精品| 在线观看久久av| 欧美一区二区成人| 亚洲精品一级| 免费av成人在线| 国产日韩欧美91| 亚洲欧美偷拍卡通变态| 国产精品videossex久久发布| 国产日韩av高清| 精品不卡一区二区三区| 国产精品美女一区二区在线观看| 欧美日韩一级片在线观看| 国产欧美 在线欧美| 亚洲国产精品久久久久久女王| 99精品国产99久久久久久福利| 亚洲毛片在线观看.| 午夜精品久久久久久久久久久久| 亚洲国产日韩综合一区| 久久久午夜视频| 国产欧美日韩综合精品二区| 一本色道久久精品| 亚洲国产三级在线| 久久成人18免费网站| 国产欧美在线| 亚洲第一精品电影| 国产日产亚洲精品系列| 亚洲欧美日韩中文视频| 日韩一二三区视频| 亚洲黑丝在线| 在线观看日韩专区| 欧美日韩视频一区二区| 欧美三区美女| 亚洲一区观看| 亚洲福利精品| 亚洲视频电影图片偷拍一区| 欧美一区二区三区免费视| 欧美精品日韩一区| 在线免费观看视频一区| 欧美一级淫片aaaaaaa视频| 亚洲成人在线网站| 亚欧成人在线| 国产乱码精品1区2区3区| 欧美区国产区| 麻豆91精品91久久久的内涵| 国产精品网站一区| 中文一区二区| 99视频精品在线| 欧美日韩精品伦理作品在线免费观看| 狠狠色噜噜狠狠色综合久| 午夜视频久久久| 日韩视频在线免费| 欧美理论电影在线播放| 亚洲国产精品一区二区久| 久久国产欧美日韩精品| 亚洲一区二区精品视频| 国产精品久久久久久久久果冻传媒| 亚洲国产精品一区制服丝袜| 美国十次了思思久久精品导航| 欧美中文字幕久久| 狠狠色狠狠色综合日日tαg| 久久蜜桃av一区精品变态类天堂| 欧美一级黄色网| 狠狠狠色丁香婷婷综合激情| 久久亚洲国产精品日日av夜夜| 久久不射2019中文字幕| 欲色影视综合吧| 亚洲国产精品一区制服丝袜| 欧美一区二区免费| 亚洲一区中文| 红桃av永久久久| 欧美激情精品久久久久久黑人| 女同性一区二区三区人了人一 | 亚洲国产精品高清久久久| 久久免费视频这里只有精品| 亚洲国产成人一区| 亚洲精品一品区二品区三品区| 欧美日本视频在线| 美女露胸一区二区三区| 你懂的视频一区二区| 久久久五月天| 欧美三区美女| 精品69视频一区二区三区| 久久久久国内| 蜜臀av国产精品久久久久| 亚洲人成啪啪网站| 一区二区欧美日韩| 国产亚洲成精品久久| 欧美激情精品久久久久久蜜臀| 欧美日韩xxxxx| 久久婷婷麻豆| 国产精品大片| 亚洲第一主播视频| 国产精品视频成人| 亚洲国产精品第一区二区三区| 国产精品乱码一区二区三区| 农夫在线精品视频免费观看| 欧美午夜不卡| 欧美第一黄色网| 国产精品综合久久久| 亚洲国产欧美一区二区三区同亚洲 | 亚洲人成网站999久久久综合| 欧美在线看片| 国产精品入口尤物| 亚洲综合丁香| 裸体女人亚洲精品一区| 亚洲精品在线观看免费| 国产精品成人一区二区网站软件 | 欧美一区二区在线| 欧美不卡视频一区| 亚洲欧洲在线播放| 亚洲欧美网站| 亚洲第一色在线| 欧美黄色一区| 欧美亚洲专区| 亚洲影院色无极综合| 久久国产精品久久久久久| 亚洲精品系列| 亚洲激情国产| 亚洲日本成人在线观看| 欧美金8天国| 欧美一区激情| 午夜久久一区| 一本久久青青| 亚洲欧洲一区二区在线观看| 久久久久久一区| 亚洲欧洲三级电影| 91久久在线播放| 欧美日韩第一页| 亚洲午夜激情网页| 久久九九久久九九| 亚洲专区在线视频| 午夜精品影院| 欧美日韩国产三级| 亚洲国产精品久久久久婷婷老年 | 久久综合色影院| 久久婷婷综合激情| 一区二区三区中文在线观看 | 猛干欧美女孩| 亚洲国产黄色| 亚洲日韩欧美视频一区| 久久精品成人一区二区三区 | 国产日韩欧美麻豆| 国产精品成av人在线视午夜片| 欧美精品一区二区三区视频| 久久在线观看视频| 久久久福利视频| 久久综合色播五月| 国产一区导航| 一本色道88久久加勒比精品| 中文精品视频| 9i看片成人免费高清| 久久九九热免费视频| 在线视频欧美日韩| 欧美激情一区二区三区成人| 久久久999| 激情综合色综合久久| 欧美在线播放| 另类天堂av| 亚洲高清av在线| 欧美激情一二区| 亚洲欧洲日韩综合二区| 久久婷婷国产综合国色天香| 老司机午夜免费精品视频 | 亚洲综合色噜噜狠狠| 在线日韩日本国产亚洲| 亚洲欧美电影院| 欧美中文日韩| 狠狠干狠狠久久| 欧美成人一区在线| 亚洲国产成人av| 一区二区久久| 国产日韩欧美一区在线| 亚洲精品综合久久中文字幕| 久久精品国产96久久久香蕉| 开元免费观看欧美电视剧网站| 激情国产一区| 欧美日韩在线大尺度| 亚洲午夜视频在线观看| 久久精品在线| 亚洲精品视频二区| 国产麻豆精品视频| 欧美bbbxxxxx| 欧美一区二区三区啪啪 | 亚洲一区二区三区在线观看视频| 欧美绝品在线观看成人午夜影视| 亚洲综合日韩在线| 亚洲精品免费网站| 久久综合狠狠综合久久综合88 | 欧美激情成人在线视频| 亚洲免费视频网站| 一区二区三区高清不卡|