程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 如何分析未文檔化的數據結構

如何分析未文檔化的數據結構

編輯:匯編語言

1 前言:

這2天看了Secrets of Reverse Engineering一書,對分析未文檔化的API的技術比較有心得,希望各位看了下面的教程,能拋磚引玉靈活的應用在逆向工程和破解技術上,方法是死的,但是人的思維是活,最重要是靈活應用。

2 實踐:

用OllyDbg對NTDLL.DLL進行反匯編,前提你要加入NTDLL.DLL的符號表,這樣你才能更好的對未文檔化的API進行反匯編,你們到微軟官方網站獲取相應版本Windows系統的系統符號表。

下面是RtlInitializeGenericTable函數的反匯編代碼:

01 MOV EDI, EDI ;

//壓入堆棧,保存EBP的數值

02 PUSH EBP ;              

03 MOV EBP, ESP ;

// 獲取[ESP+8]的數值傳入EAX

// 此處指令我們可以翻譯為:

// MOV EAX, DWORD PTR SS:[ESP+8]

// 含義: 把當前堆棧頂向下偏移8h處的值賦給EAX,也就是該函數的第1個參數

// 聲明:我喜歡用ESP指針來想象堆棧。但是CPU處理的話,是用EBP來進行偏移處理

04 MOV EAX, DWORD PTR SS:[EBP+8] ;

05 XOR EDX, EDX ;

// EAX+4的數值當作指針傳入ECX

06 LEA ECX, DWORD PTR DS:[EAX+4] ;

// EDX的數值傳入[EAX],說明EAX的值是某個結構的指針

// 假設pUnknowStruct的地址為 EAX的數值

// 07的匯編指令對應的C語言: pUnknowStruct->member1 = 0 ;

07 MOV DWROD PTR DS:[EAX], EDX ;

// 此處指令我們可以翻譯為:

// MOV DWORD PTR DS:[EAX+8], EAX+4 ;

// 備注: [EAX] 為某結構的第1個變量

// [EAX+4]為某結構的第2個變量

// [EAX+8]為某結構的第3個變量

// 含義:該結構的第3個成員變量被賦於指向該結構的第2個成員變量的指針數值
  // 08的匯編指令對應的C語言: pUnknowStruct->member3 = &pUnknowStruct->member2

08 MOV DWORD PTR DS:[ECX+4], ECX ;

// 此處指令我們可以翻譯為:

// MOV DWORD PTR DS:[EAX+4], EAX+4 ;

// 09的匯編指令對應的C語言: pUnknowStruct->member2 = &pUnknowStruct->member2

09 MOV DWORD PTR DS:[ECX], ECX ;

// 此處指令我們可以翻譯為:

// MOV DWORD PTR DS:[EAX+C], EAX+4 ;

// 10的匯編指令對應的C語言: pUnknowStruct->member4 = &pUnknowStruct->member2

10 MOV DWORD PTR DS:[EAX+C], ECX ;

// 此處指令我們可以翻譯為:

// MOV ECX, DWORD PTR SS:[ESP+C]

// 含義: 把當前堆棧頂向下偏移Ch處的值賦給ECX,也就是該函數的第2個參數

11 MOV ECX, DWORD PTR SS:[EBP+C] ;

// 含義: 把第2個參數傳送給某結構的第7個成員變量

// 12的匯編指令對應的C語言為: pUnknowStruct->member7 = Param2

12 MOV DWORD PTR DS:[EAX+18], ECX ;

// 此處指令我們可以翻譯為:

// MOV ECX, DWORD PTR SS:[ESP+10]

// 含義: 把當前堆棧頂向下偏移10h處的值賦給ECX,也就是該函數的第3個參數

13 MOV ECX, DWORD PTR SS:[EBP+10] ;

// 含義:把參數3傳給某結構的第8個成員變量

// 14的匯編指令對應的C語言為: pUnknowStruct->member8 = Param3

14 MOV DWORD PTR DS:[EAX+1C], ECX ;

// 此處指令我們可以翻譯為:

// MOV ECX, DWORD PTR SS:[ESP+14]

// 含義: 把當前堆棧頂向下偏移14h處的值賦給ECX,也就是該函數的第4個參數
  15 MOV ECX, DWORD PTR SS:[EBP+14] ;

// 含義:把參數3傳給某結構的第9個成員變量

// 16的匯編指令對應的C語言為: pUnknowStruct->member9 = Param4

16 MOV DWORD PTR DS:[EAX+20], ECX ;

// 此處指令我們可以翻譯為:

// MOV ECX, DWORD PTR SS:[ESP+18]

// 含義: 把當前堆棧頂向下偏移18h處的值賦給ECX,也就是該函數的第5個參數

17 MOV ECX, DWORD PTR SS:[EBP+18] ;

// 含義:把EDX的數值賦給某結構的第6個成員變量

// 18的匯編指令對應的C語言為: pUnknowStruct->member6 = 0

18 MOV DWORD PTR DS:[EAX+14], EDX ;

// 含義:把EDX的數值賦給某結構的第6個成員變量

// 19的匯編指令對應的C語言為: pUnknowStruct->member5 = 0

19 MOV DWORD PTR DS:[EAX+10], EDX ;

// 含義:把參數5傳給某結構的第10個成員變量

// 29的匯編指令對應的C語言為: pUnknowStruct->member10 = Param5

20 MOV DWORD PTR DS:[EAX+24], ECX ;

21 POP EBP

22 RET 14

3 逆出偽代碼:

說明: 反匯編分析出如下關鍵指令

04 MOV EAX, DWORD PTR SS:[EBP+8] ;

11 MOV ECX, DWORD PTR SS:[EBP+C] ;

13 MOV ECX, DWORD PTR SS:[EBP+10] ;

15 MOV ECX, DWORD PTR SS:[EBP+14] ;

17 MOV ECX, DWORD PTR SS:[EBP+18] ;

可以看得出,該函數使用了5個參數,可以假設為: Param1...5 ;

struct UnknowStruct
{
  UNKNOWN Member1 ;
  UNKNOWN_PTR Member2 ;
  UNKNOWN_PTR Member3 ;
  UNKNOWN_PTR Member4 ;
  UNKNOWN Member5 ;
  UNKNOWN Member6 ;
  UNKNOWN Member7 ;
  UNKNOWN Member8 ;
  UNKNOWN Member9 ;
  UNKNOWN Member10 ;
} ;
struct UnknowStruct *pUnknowStruct ;
pUnknowStruct = Param1 ;
pUnknowStruct->Member1 = 0 ;
pUnknowStruct->Member3 = &pUnknowStruct->Member2 ;
pUnknowStruct->Member2 = &pUnknowStruct->Member2 ;
pUnknowStruct->Member4 = &pUnknowStruct->Member2 ;
pUnknowStrcut->Member7 = Param2 ;
pUnknowStruct->Member8 = Param3 ;
pUnknowStruct->Member9 = Param4 ;
pUnknowStruct->Member6 = 0
pUnknowStruct->Member5 = 0
pUnknowStruct->Member10 = Param5 ;
  4: 圖片分析流程

獲取參數流程圖

結構賦值流程圖

5:總結

經過反匯編分析,雖然只有22行代碼,但是完成了這個結構的初始化工作,該結構的指針存放在EAX寄存器,賦值時,就是對EAX存放的地址進行偏移處理。大家可以查看流程圖來思考一下。

6:遺憾

由於時間有限,未能寫出下一篇: 教你如何分析結構成員變量的類型

我盡量吧~~~~~~~工作太忙了!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved