教你如何分析未文檔化的數(shù)據(jù)結(jié)構(gòu)

原始連接:http://www.x86asm.com/DisplayArticle.asp?BoardID=3&ArticleID=108
?Editor:admin??Time:2005-8-20?23:22??Read:9985??Score:8??Print
?Writer:HSLY
?Excerpt:80x86匯編小站

[標(biāo)題] 教你如何分析未文檔化的數(shù)據(jù)結(jié)構(gòu)

[作者] hsly110 或者 豬頭三

[個(gè)人網(wǎng)站] http://www.x86asm.com 80x86匯編小站

[Email] pliceman_110@163.com PS:本文如果有錯(cuò)漏請(qǐng)來信指出

[范圍] 逆向工程

[目的] 分享逆向技術(shù)心德

[目標(biāo)API] 未文檔化的RtlInitializeGenericTable

[參考文獻(xiàn)] Secrets of Reverse Engineering

[備注] 歡迎轉(zhuǎn)載該文章,只要保留完整內(nèi)容即可

2005-08-20 撰寫
2005-08-21 修正
2005-08-23 修正
------------------------------------------------------

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

2 實(shí)踐:
用OllyDbg對(duì)NTDLL.DLL進(jìn)行反匯編,前提你要加入NTDLL.DLL的符號(hào)表,這樣你才能更好的對(duì)未文檔化的API進(jìn)行反匯編,你們到微軟官方網(wǎng)站獲取相應(yīng)版本W(wǎng)indows系統(tǒng)的系統(tǒng)符號(hào)表。
下面是RtlInitializeGenericTable函數(shù)的反匯編代碼:

01 MOV EDI, EDI ;

//壓入堆棧,保存EBP的數(shù)值
02 PUSH EBP ; ???????????????????????????

03 MOV EBP, ESP ;

// 獲取[ESP+8]的數(shù)值傳入EAX
// 此處指令我們可以翻譯為:
// MOV EAX, DWORD PTR SS:[ESP+8]
// 含義: 把當(dāng)前堆棧頂向下偏移8h處的值賦給EAX,也就是該函數(shù)的第1個(gè)參數(shù)
// 聲明:我喜歡用ESP指針來想象堆棧。但是CPU處理的話,是用EBP來進(jìn)行偏移處理

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

05 XOR EDX, EDX ;

// EAX+4的數(shù)值當(dāng)作指針傳入ECX
06 LEA ECX, DWORD PTR DS:[EAX+4] ;

// EDX的數(shù)值傳入[EAX],說明EAX的值是某個(gè)結(jié)構(gòu)的指針
// 假設(shè)pUnknowStruct的地址為 EAX的數(shù)值
// 07的匯編指令對(duì)應(yīng)的C語(yǔ)言: pUnknowStruct->member1 = 0 ;

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

// 此處指令我們可以翻譯為:
// MOV DWORD PTR DS:[EAX+8], EAX+4 ;
// 備注: [EAX] 為某結(jié)構(gòu)的第1個(gè)變量
// [EAX+4]為某結(jié)構(gòu)的第2個(gè)變量
// [EAX+8]為某結(jié)構(gòu)的第3個(gè)變量
// 含義:該結(jié)構(gòu)的第3個(gè)成員變量被賦于指向該結(jié)構(gòu)的第2個(gè)成員變量的指針數(shù)值
// 08的匯編指令對(duì)應(yīng)的C語(yǔ)言: pUnknowStruct->member3 = &pUnknowStruct->member2

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

// 此處指令我們可以翻譯為:
// MOV DWORD PTR DS:[EAX+4], EAX+4 ;
// 09的匯編指令對(duì)應(yīng)的C語(yǔ)言: pUnknowStruct->member2 = &pUnknowStruct->member2

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

// 此處指令我們可以翻譯為:
// MOV DWORD PTR DS:[EAX+C], EAX+4 ;
// 10的匯編指令對(duì)應(yīng)的C語(yǔ)言: pUnknowStruct->member4 = &pUnknowStruct->member2

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

// 此處指令我們可以翻譯為:
// MOV ECX, DWORD PTR SS:[ESP+C]
// 含義: 把當(dāng)前堆棧頂向下偏移Ch處的值賦給ECX,也就是該函數(shù)的第2個(gè)參數(shù)

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

// 含義: 把第2個(gè)參數(shù)傳送給某結(jié)構(gòu)的第7個(gè)成員變量
// 12的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member7 = Param2

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

// 此處指令我們可以翻譯為:
// MOV ECX, DWORD PTR SS:[ESP+10]
// 含義: 把當(dāng)前堆棧頂向下偏移10h處的值賦給ECX,也就是該函數(shù)的第3個(gè)參數(shù)

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

// 含義:把參數(shù)3傳給某結(jié)構(gòu)的第8個(gè)成員變量
// 14的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member8 = Param3

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

// 此處指令我們可以翻譯為:
// MOV ECX, DWORD PTR SS:[ESP+14]
// 含義: 把當(dāng)前堆棧頂向下偏移14h處的值賦給ECX,也就是該函數(shù)的第4個(gè)參數(shù)

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

// 含義:把參數(shù)3傳給某結(jié)構(gòu)的第9個(gè)成員變量
// 16的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member9 = Param4

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

// 此處指令我們可以翻譯為:
// MOV ECX, DWORD PTR SS:[ESP+18]
// 含義: 把當(dāng)前堆棧頂向下偏移18h處的值賦給ECX,也就是該函數(shù)的第5個(gè)參數(shù)

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

// 含義:把EDX的數(shù)值賦給某結(jié)構(gòu)的第6個(gè)成員變量
// 18的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member6 = 0

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

// 含義:把EDX的數(shù)值賦給某結(jié)構(gòu)的第6個(gè)成員變量
// 19的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member5 = 0

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

// 含義:把參數(shù)5傳給某結(jié)構(gòu)的第10個(gè)成員變量
// 29的匯編指令對(duì)應(yīng)的C語(yǔ)言為: pUnknowStruct->member10 = Param5

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

21 POP EBP

22 RET 14

3 逆出偽代碼:

說明: 反匯編分析出如下關(guān)鍵指令
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] ;
可以看得出,該函數(shù)使用了5個(gè)參數(shù),可以假設(shè)為: 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: 圖片分析流程

獲取參數(shù)流程圖



結(jié)構(gòu)賦值流程圖


5:總結(jié)
經(jīng)過反匯編分析,雖然只有22行代碼,但是完成了這個(gè)結(jié)構(gòu)的初始化工作,該結(jié)構(gòu)的指針存放在EAX寄存器,賦值時(shí),就是對(duì)EAX存放的地址進(jìn)行偏移處理。大家可以查看流程圖來思考一下。

6:遺憾
由于時(shí)間有限,未能寫出下一篇: 教你如何分析結(jié)構(gòu)成員變量的類型
我盡量吧~~~~~~~工作太忙了!