日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
【博文推薦】如何獲得C語言函數起始地址和返回地址
 本博文出自博客gmxydm 博主,有任何問題請進入博主頁面互動討論!
博文地址:http://5412097.blog./5402097/1641374
 

在反外掛系統中,經常會檢測函數的返回地址,確認函數的返回地址在規(guī)定的范圍之內,從而保證,游戲程序中的函數,不被外掛所調用。這種檢查方式就涉及到一個基本的技術問題,如何獲得函數的返回地址?

10年積累的成都做網站、網站建設經驗,可以快速應對客戶對網站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網絡服務。我雖然不認識你,你也不認識我。但先網站策劃后付款的網站建設流程,更有茂名免費網站建設讓你可以放心的選擇與我們合作。

例如下面的***段代碼:

 
 
  1. #include 
  2. int main() 
  3. getchar(); 
  4. return 0; 

非常簡單的一段程序,那么我們如何獲得該函數的起始地址和返回地址呢?起始地址獲取非常容易,如下:

 
 
  1. #include 
  2. int main() 
  3. printf("%0x\n",main); 
  4. getchar(); 
  5. return 0; 

那么如何獲得函數的返回地址呢?這個就相對來說比較困難。我們先看***段代碼反匯編后的結果:

 
 
  1. #include 
  2. intmain() 
  3. 009919E0 push ebp 
  4. 009919E1 mov ebp,esp 
  5. 009919E3 sub esp,0C0h 
  6. 009919E9 push ebx 
  7. 009919EA push esi 
  8. 009919EB push edi 
  9. 009919EC lea edi,[ebp-0C0h] 
  10. 009919F2 mov ecx,30h 
  11. 009919F7 mov eax,0CCCCCCCCh 
  12. 009919FC rep stos dword ptr es:[edi] 
  13. getchar(); 
  14. 009919FE mov esi,esp 
  15. 00991A00 call dword ptr [__imp__getchar (9982B0h)] 
  16. 00991A06 cmp esi,esp 
  17. 00991A08 call @ILT+295(__RTC_CheckEsp) (99112Ch) 
  18. return 0; 
  19. 00991A0D xor eax,eax 
  20. 00991A0F pop edi 
  21. 00991A10 pop esi 
  22. 00991A11 pop ebx 
  23. 00991A12 add esp,0C0h 
  24. 00991A18 cmp ebp,esp 
  25. 00991A1A call @ILT+295(__RTC_CheckEsp) (99112Ch) 
  26. 00991A1F mov esp,ebp 
  27. 00991A21 pop ebp 
  28. 00991A22 ret

代碼開始部分,先保存ebp的內容,然后將ESP的內容寫入EBP:

 
 
  1. 009919E0 push ebp 
  2.  
  3. 009919E1 mov ebp,esp 

匯編指令call會做兩件事情,其一,將call指令后面的一條指令的地址壓入棧中,無條件跳轉到call指令的調用地指處,開始執(zhí)行子程序。

和call指令對應的ret指令,則開始執(zhí)行call指令后面的一條指令。

那么,ret指令如何知道call指令后面一條指令的地址呢?因為call指令已經將這條指令壓入到了棧中,所以ret指令可以找到call指令后的一條指令的地址。

既然ret指令可以找到call的返回地址,也就是call的下一條指令的地址,那么我們也可以找到?。?!

main函數在執(zhí)行前以及執(zhí)行過程中,棧的分布如下:

通過以上幾張圖,我們可以清楚的看到,main函數的返回地址在[EBP+4]處。所以,獲得main函數的返回地址的代碼如下:

 
 
  1. #include 
  2. int main() 
  3. int re_addr; 
  4. __asm 
  5. mov eax,dword ptr [ebp+4] 
  6. mov re_addr,eax 
  7. printf("%0X\n",re_addr); 
  8. getchar(); 
  9. return 0; 

其中__tmainCRTStartup()函數調用了main函數,調用的匯編代碼如下:

mainret = main(argc, argv, envp);

00B81926  mov        eax,dword ptr [envp (0B87140h)] 

00B8192B  push       eax 

00B8192C  mov        ecx,dword ptr [argv (0B87144h)] 

00B81932  push       ecx 

00B81933  mov        edx,dword ptr [argc (0B8713Ch)] 

00B81939  push       edx 

00B8193A call        @ILT+300(_main)(0B81131h) 

00B8193F  add        esp,0Ch 

00B81942  mov        dword ptr [mainret (0B87154h)],eax

可以看出,call main指令后的一條指令的地址為:00B8193F,而我們獲得的main的返回地址如下:

B8193F

說明我們獲得的結果正確。

對于其他函數的情況類似,下面筆者就把獲得某個函數的返回值得功能,做成一個函數,提供給大家,如下:

 
 
  1. #include 
  2.  
  3. int Get_return_addr() 
  4. int re_addr; 
  5. __asm 
  6. mov eax,dword ptr [ebp] 
  7. mov ebx,dword ptr [eax+4] 
  8. mov re_addr,ebx 
  9. returnre_addr; 
  10.  
  11.  
  12. int main() 
  13. intre_addr=Get_return_addr(); 
  14. printf("%0X\n",re_addr); 
  15. getchar(); 
  16. return 0; 

Get_return_add函數中,為什么會多幾條匯編指令呢?大家可以自行思考。


分享標題:【博文推薦】如何獲得C語言函數起始地址和返回地址
分享URL:http://www.5511xx.com/article/ccodpep.html