新聞中心
前言

創(chuàng)新互聯(lián)建站技術(shù)團(tuán)隊(duì)10多年來(lái)致力于為客戶提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站設(shè)計(jì)、成都營(yíng)銷網(wǎng)站建設(shè)、搜索引擎SEO優(yōu)化等服務(wù)。經(jīng)過(guò)多年發(fā)展,公司擁有經(jīng)驗(yàn)豐富的技術(shù)團(tuán)隊(duì),先后服務(wù)、推廣了上1000+網(wǎng)站,包括各類中小企業(yè)、企事單位、高校等機(jī)構(gòu)單位。
在平時(shí)的惡意軟件分析和逆向工作中,我們往往需要對(duì)某些類型的加密算法或者解壓縮算法進(jìn)行逆向。而這一逆向工作,可能會(huì)需要好幾個(gè)小時(shí)、好幾天、好幾個(gè)月,甚至是好幾年才能完成。在我們分析的過(guò)程中,常常需要弄明白惡意軟件所使用的數(shù)據(jù)Blob是什么。
要回答這個(gè)問(wèn)題,本身就是一件有挑戰(zhàn)性的工作,我通常并沒(méi)有那么多的時(shí)間來(lái)對(duì)一些加密的程序做完全徹底的逆向。我一般只需要弄明白這個(gè)數(shù)據(jù)是惡意軟件用來(lái)做什么的配置文件,甚至有的時(shí)候,我根本不知道這些數(shù)據(jù)是什么。盡管很不愿意接受這樣的結(jié)果,但卻是時(shí)常發(fā)生的。
目前,有幾種方法可以解密惡意軟件,并解壓其中的數(shù)據(jù)。我們可以運(yùn)行惡意軟件并轉(zhuǎn)儲(chǔ)內(nèi)存段、在調(diào)試器中對(duì)其進(jìn)行調(diào)試、在解密/解壓縮的部分放置Hook從而dump出其返回值、進(jìn)行靜態(tài)分析等等。雖然這些方法都很不錯(cuò),但無(wú)疑要花費(fèi)大量的時(shí)間。
如果我們有幾個(gè)需要解密或解壓縮的數(shù)據(jù)Blob,那么該怎么辦呢?如果可以直接從惡意軟件的解密/解壓縮部分中得到其匯編代碼,那便可以將其放在一個(gè)編譯器中(比如Visual Studio),將其編譯成動(dòng)態(tài)鏈接庫(kù)(DLL),然后再使用我們熟悉的腳本語(yǔ)言(比如Python)對(duì)其進(jìn)行調(diào)用。
本文將重點(diǎn)講解可以實(shí)現(xiàn)這一點(diǎn)的技術(shù)方法。在分析惡意軟件Reaver的過(guò)程中,Unit 42安全小組發(fā)布了一個(gè)API調(diào)用及字符串的數(shù)據(jù)庫(kù)查找工具,地址為:
https://github.com/pan-unit42/public_tools/tree/master/Reaver_Decompression
分析過(guò)程
我們以針對(duì)Reaver惡意軟件家族的分析為例,嘗試確定其使用的壓縮算法,并確定是否可以在不運(yùn)行惡意軟件的前提下,從中逆向出其使用的算法。請(qǐng)注意,這里的前提是不運(yùn)行惡意軟件。
在我對(duì)該惡意軟件的分析過(guò)程中,發(fā)現(xiàn)它似乎使用了一個(gè)修改過(guò)的Lempel-Ziv-Welch(LZW)壓縮算法。我們所分析的Reaver惡意軟件樣本中,解壓縮算法位于地址0x100010B2,其匯編代碼大約有200行。解壓縮例程如下所示:
- ; void __thiscall decompress(_DWORD *this, int nstream, int output, int zero, int zero2, int zero3)
- decompress proc near ; CODE XREF: decompressingData+5A↓p
- nstream = dword ptr 8
- output = dword ptr 0Ch
- zero = dword ptr 10h
- zero2 = dword ptr 14h
- zero3 = dword ptr 18h
- push ebp
- mov ebp, esp
- push ebx
- push esi
- push edi
- mov esi, ecx
- push 16512 ; unsigned int
- call Malloc
- pop ecx
- mov edi, eax
- mov ecx, 1020h
- xor eax, eax
- mov [esi], edi
- xor ebx, ebx
- rep stosd
為了簡(jiǎn)潔起見,我們沒(méi)有展示該函數(shù)的全部代碼。需要注意的地方是:
該函數(shù)調(diào)用約定(Calling Convention)是__thiscall(說(shuō)明是C++);
該函數(shù)使用了5個(gè)參數(shù);
該函數(shù)從惡意軟件中調(diào)用一次(通過(guò)在IDA Pro中標(biāo)識(shí)的交叉引用數(shù)量來(lái)看到的)。
下面是該函數(shù)調(diào)用部分的代碼:
- xor eax, eax
- mov ecx, [ebp+v6]
- push eax
- push eax
- push eax
- movzx eax, word ptr [ebx+24]
- push dword ptr [edx] ; output
- lea eax, [eax+ebx+26]
- push eax
- call decompress
對(duì)調(diào)用解壓縮函數(shù)的分析如下:
會(huì)清除EAX寄存器,因此EAX為0;
指向?qū)ο蟮闹羔槾鎯?chǔ)在ECX(Thiscall)中;
EAX的三次push說(shuō)明了解壓縮例程的第3、4、5個(gè)參數(shù)始終為0;
第2個(gè)參數(shù)是指向目標(biāo)緩沖區(qū)的指針;
第1個(gè)參數(shù)是指向壓縮數(shù)據(jù)的指針。
而壓縮的數(shù)據(jù)如下:
- 08 00 A5 04 01 12 03 06 8C 18 36 7A 04 21 62 25 ..¥.....?.6z.!b%
- 08 94 24 33 64 B8 20 C3 86 4D 03 05 02 09 1A 8C .”$3d? ??M.....?
- 71 A3 C7 91 32 74 AA CC 29 23 C7 49 98 36 65 82 q£?‘2taì)#?I?6e?
- 5C CC 58 F0 20 8E 1E 52 CA 9C 19 C2 E6 CD C8 25 ìXe ?.Rê?.??íè%
- 65 F2 AC 1C D8 32 46 0E 98 32 9F C0 29 E3 06 67 eò?.?2F.?2?à)?.g
- 9E 22 78 54 62 E4 69 50 06 0C A0 33 E5 94 09 43 ?"xTb?iP.. 3?”.C
- A7 8C 51 A4 4A 59 36 8D 01 75 0A 48 2B 61 D8 D4 §?Q¤JY6..u.H+a??
- 29 83 75 A7 46 18 32 64 40 25 52 86 0D C8 32 60 )?u§F.2d@%R?.è2`
- C5 A6 34 DB 52 C6 0C 85 64 D4 D4 99 43 87 CA 9B ?|4?R?.…d???C?ê?
- 35 44 A1 C8 49 63 27 8D DB 33 65 E6 D0 6D 4A A3 5D?èIc'.?3e?DmJ£
- 07 93 37 7F EB C0 11 4C D8 B0 4C B8 61 C7 66 65 .“7.?à.L?°L?a?fe
- 8A B6 46 0F A1 81 E5 BC 19 93 78 8E 5F C0 6E 16 ??F.?.??.“x?_àn.
- A3 4D 38 85 4E 18 39 74 BC CA 29 4C 7A F3 59 19 £M8…N.9t?ê)LzóY.
為了簡(jiǎn)潔起見,在這里也不展示壓縮數(shù)據(jù)的全部?jī)?nèi)容,其完整大小是45115字節(jié)。
第1-7字節(jié)(08 00 A5 04 01 12 03)是壓縮例程的一個(gè)“魔法值”,我們?cè)谒蠷eaver變種中都發(fā)現(xiàn)了這個(gè)頭部。
在掌握了上述這些之后,我們就可以將注意力集中在解壓縮例程的工作機(jī)制上。
請(qǐng)大家注意:在這里,我們可以監(jiān)視調(diào)用或轉(zhuǎn)儲(chǔ)目標(biāo)緩沖區(qū)內(nèi)容后所得到的返回結(jié)果,其中會(huì)包含解壓縮的數(shù)據(jù),但是如果選擇這種方法,就需要我們?cè)谡{(diào)試器中運(yùn)行代碼。而我們的前提是不運(yùn)行惡意軟件樣本。
創(chuàng)建DLL
在掌握了一定信息后,我們開始創(chuàng)建一個(gè)DLL。我們可以使用Visual Studio,或者任何能處理編譯程序集(NASM/MASM)的編譯器。創(chuàng)建一個(gè)新的空DLL項(xiàng)目,并添加一個(gè)新的頭文件。
舉例來(lái)說(shuō),我創(chuàng)建了一個(gè)頭文件,如下所示:
- #pragma once
- #ifndef _DEFINE_LZWDecompress_DLL
- #define _DEFINE_LZWDecompress_DLL
- #ifdef __cplusplus
- extern "C" {
- #endif
- __declspec(dllexport) BOOL Decompress(char *src, char *dst);
- #ifdef __cplusplus
- }
- #endif
- BOOL Decompress(char *src, char *dst);
- #endif
上述代碼會(huì)創(chuàng)建一個(gè)名為“Decompress”的文件,并且能接收兩個(gè)參數(shù)。我們?cè)谶@里之所以僅使用了兩個(gè)參數(shù),原因在于其他三個(gè)參數(shù)始終為0,所以無(wú)需定義他們。該函數(shù)的返回類型為布爾型。
針對(duì)源文件(.cpp或.c),需要從IDA Pro或其他調(diào)試器中獲得匯編代碼,再將其添加到源文件中。以下是我修復(fù)后的源文件代碼:
- #include
- #include
- #include "TestDLL.h"
- BOOL Decompress(char *src, char *dst)
- {
- //Use calloc vs malloc. Temp buffer is for the dictionary
- void *pTmpbuff;
- pTmpbuff = (int*) calloc(0x4080u, sizeof(unsigned int));
- if (src && dst)
- {
- __asm
- {
- xor ebx, ebx; //Need to clear ebx register
- SUB ESP, 0x40; //Need to subtract stack, so we don’t overwrite some Ctypes return data
- MOV ESI, ESP;
- PUSH EAX;
- POP EDI; //Our Temp Buffer
- PUSH[EBP + 8]; //Source Buffer
- POP EAX;
- PUSH[EBP + 0xC]; //Destination Buffer
- POP EDX;
- LEA ECX, DWORD PTR DS : [EAX + 1]; //Where we start. Get the 1st DWORD of the compressed data appears to be magic value
- MOV DWORD PTR DS : [ESI], EDI;//Temp buffer address
- MOV DWORD PTR DS : [ESI + 0x1C], EDX;//Destination address
- MOV DWORD PTR DS : [ESI + 0x18], ECX;//Compressed Data
- MOV BYTE PTR DS : [ESI + 0x20], BL;//0
- MOV CL, BYTE PTR DS : [EAX];//08
- PUSH 1;
- POP EAX;
- MOV BYTE PTR DS : [ESI + 0x22], CL;
- SHL EAX, CL;
- MOV DWORD PTR DS : [ESI + 0x30], EBX;
- MOV WORD PTR DS : [ESI + 8], AX;
- INC EAX;
- MOV WORD PTR DS : [ESI + 0xA], AX;
- MOV EAX, DWORD PTR SS : [EBP + 0x10];
- MOV DWORD PTR DS : [ESI + 0x2C], EAX;
- LEA EAX, DWORD PTR DS : [EAX * 8 + 0x1F];
- SHR EAX, 5;
- SHL EAX, 2;
- CMP BYTE PTR SS : [EBP + 0x18], BL;
- MOV DWORD PTR DS : [ESI + 0x38], EAX;
- SETE AL;
- DEC EAX;
- AND AL, 1;
- ADD EAX, 0x0FF;
- CMP AL, BL;
- MOV BYTE PTR DS : [ESI + 0xC], AL;
- JNZ SHORT check3;
- MOV EAX, DWORD PTR SS : [EBP + 0x14];
- MOV DWORD PTR DS : [ESI + 0x14], EDX;
- MOV DWORD PTR DS : [ESI + 0x28], EAX;
- MOV DWORD PTR DS : [ESI + 0x34], EBX;
- check3:
- MOV ECX, ESI;
- CALL check4;
- check26:
- MOV ECX, ESI;
- CALL check10;
- MOV EDI, EAX;
- CMP DI, WORD PTR DS : [ESI + 0xA];
- JE Finished;
- CMP DI, WORD PTR DS : [ESI + 8];
- JNZ SHORT check22;
- MOV ECX, ESI;
- CALL check4;
- check24:
- MOV ECX, ESI;
- CALL check10;
- MOV EDI, EAX
- CMP DI, WORD PTR DS : [ESI + 8]
- JNZ SHORT check23;
- JMP SHORT check24;
- check22:
- CMP DI, WORD PTR DS : [ESI + 0X24]
- JNB SHORT check25;
- PUSH EDI
- JMP SHORT check27;
- check25:
- PUSH EBX;
- check27:
- MOV ECX, ESI;
- CALL check28;
- MOVZX AX, AL;
- PUSH EAX;
- PUSH EBX;
- MOV ECX, ESI;
- CALL check31;
- PUSH EDI;
- MOV ECX, ESI;
- CALL check35;
- MOV EBX, EDI;
- JMP SHORT check26;
- check10:
- MOVZX EAX, BYTE PTR DS : [ECX + 0x20];
- PUSH EBX;
- PUSH ESI;
- PUSH EDI;
- MOVZX EDI, BYTE PTR DS : [ECX + 0x23];
- ADD EAX, EDI;
- CMP EAX, 8;
- JA SHORT Check6;
- MOV EDX, DWORD PTR DS : [ECX + 0x18];
- MOVZX ESI, BYTE PTR DS : [EDX];
- JMP SHORT Check8;
- Check6:
- MOV EDX, DWORD PTR DS : [ECX + 0x18];
- CMP EAX, 0x10;
- JA SHORT Check7;
- MOVZX ESI, WORD PTR DS : [EDX];
- JMP SHORT Check8;
- Check7:
- MOVZX ESI, BYTE PTR DS : [EDX + 2];
- MOVZX EBX, WORD PTR DS : [EDX];
- SHL ESI, 0X10;
- OR ESI, EBX;
- Check8:
- MOV EBX, EAX;
- PUSH 0x20;
- SHR EBX, 3;
- ADD EBX, EDX;
- MOV DL, AL;
- AND DL, 7;
- MOV DWORD PTR DS : [ECX + 0X18], EBX;
- MOV BYTE PTR DS : [ECX + 0X20], DL;
- POP ECX;
- SUB ECX, EAX;
- MOV EAX, ESI;
- PUSH 0x20;
- SHL EAX, CL;
- POP ECX;
- SUB ECX, EDI;
- POP EDI;
- POP ESI;
- POP EBX;
- SHR EAX, CL;
- RETN;
- check28:
- MOV EAX, DWORD PTR DS : [ECX];
- MOV EDX, DWORD PTR SS : [ESP + 4];
- check30:
- MOVZX ECX, DX;
- MOV CX, WORD PTR DS : [EAX + ECX * 4];
- CMP CX, 0x0FFFF;
- JE SHORT check29;
- MOV EDX, ECX;
- JMP SHORT check30;
- check29:
- MOVZX ECX, DX;
- MOV AL, BYTE PTR DS : [EAX + ECX * 4 + 2];
- RETN 4;
- check31:
- MOVZX EDX, WORD PTR DS : [ECX + 0x24];
- LEA EAX, DWORD PTR DS : [ECX + 0x24];
- PUSH ESI;
- MOV ESI, DWORD PTR DS : [ECX];
- PUSH EDI;
- MOV DI, WORD PTR SS : [ESP + 0xC];
- MOV WORD PTR DS : [ESI + EDX * 4], DI;
- MOV ESI, DWORD PTR DS : [ECX];
- MOVZX EDX, WORD PTR DS : [EAX];
- MOV DI, WORD PTR SS : [ESP + 0x10];
- MOV WORD PTR DS : [ESI + EDX * 4 + 2], DI;
- INC WORD PTR DS : [EAX];
- MOV AX, WORD PTR DS : [EAX];
- POP EDI;
- CMP AX, 8;
- POP ESI;
- JE SHORT check32;
- CMP AX, 0x10;
- JE SHORT check32;
- CMP AX, 0x20;
- JE SHORT check32;
- CMP AX, 0x40;
- JE SHORT check32;
- CMP AX, 0x80;
- JE SHORT check32;
- CMP AX, 0x100;
- JE SHORT check32;
- CMP AX, 0x200;
- JE SHORT check32;
- CMP AX, 0x400;
- JE SHORT check32;
- CMP AX, 0x800;
- JNZ SHORT check33;
- check32:
- INC BYTE PTR DS : [ECX + 0x23];
- check33:
- RETN 8;
- check4:
- MOV EDX, ECX;
- PUSH EDI;
- MOV ECX, 0x1000;
- OR EAX, 0xFFFFFFFF;
- MOV EDI, DWORD PTR DS : [EDX]
- REP STOS DWORD PTR ES : [EDI];
- XOR EAX, EAX;
- POP EDI;
- CMP WORD PTR DS : [EDX + 8], AX;
- JBE SHORT check1;
- PUSH ESI;
- MOV ESI, DWORD PTR DS : [EDX];
- check2:
- MOVZX ECX, AX;
- MOV WORD PTR DS : [ESI + ECX * 4 + 2], AX;
- INC EAX;
- CMP AX, WORD PTR DS : [EDX + 8];
- JB SHORT check2;
- POP ESI;
- check1:
- MOV AX, WORD PTR DS : [EDX + 0xA];
- INC AX;
- MOV WORD PTR DS : [EDX + 0x24], AX;
- MOV AL, BYTE PTR DS : [EDX + 0x22];
- INC AL;
- MOV BYTE PTR DS : [EDX + 0x23], AL;
- RETN;
- check23:
- PUSH EDI;
- MOV ECX, ESI;
- CALL check35;
- MOV EBX, EDI;
- JMP SHORT check26;
- check35:
- PUSH EBP;
- MOV EBP, ESP;
- PUSH ESI;
- PUSH EDI;
- MOV ESI, ECX;
- NOP;
- MOV AX, WORD PTR SS : [EBP + 8];
- CMP AX, WORD PTR DS : [ESI + 8];
- JNB SHORT check36;
- NOP;
- MOV ECX, DWORD PTR DS : [ESI];
- MOV EDX, DWORD PTR DS : [ESI + 0x1C];
- MOV EDI, DWORD PTR DS : [ESI + 0x30];
- MOVZX EAX, AX;
- MOV AL, BYTE PTR DS : [ECX + EAX * 4 + 2];
- MOV BYTE PTR DS : [EDX + EDI], AL;
- INC DWORD PTR DS : [ESI + 0x30];
- NOP;
- MOV EAX, DWORD PTR DS : [ESI + 0x30];
- CMP EAX, DWORD PTR DS : [ESI + 0x2C];
- JNZ SHORT FuncRetn;
- MOV ECX, ESI;
- CALL check37;
- NOP;
- JMP SHORT FuncRetn;
- check36:
- MOVZX EDI, AX;
- MOV EAX, DWORD PTR DS : [ESI];
- MOV ECX, ESI;
- SHL EDI, 2;
- MOV AX, WORD PTR DS : [EDI + EAX];
- PUSH EAX;
- CALL check35;
- NOP;
- MOV EAX, DWORD PTR DS : [ESI];
- MOV ECX, ESI;
- MOV AX, WORD PTR DS : [EDI + EAX + 2];
- PUSH EAX;
- CALL check35;
- NOP;
- NOP;
- POP EDI;
- POP ESI;
- POP EBP;
- RETN 4;
- check38:
- MOVZX EDX, AL;
- MOVZX EDX, BYTE PTR DS : [EDX + ECX + 0xD];
- ADD DWORD PTR DS : [ECX + 0x34], EDX;
- MOV EDX, DWORD PTR DS : [ECX + 0x34];
- CMP EDX, DWORD PTR DS : [ECX + 0x28];
- JB SHORT FuncRetrn2;
- INC AL;
- CMP AL, 4;
- MOV BYTE PTR DS : [ECX + 0xC], AL;
- JNB SHORT Frtn;
- MOVZX EAX, AL;
- MOVZX EAX, BYTE PTR DS : [EAX + ECX + 0xD];
- SHR EAX, 1;
- MOV DWORD PTR DS : [ECX + 0x34], EAX;
- FuncRetrn2:
- MOV EAX, DWORD PTR DS : [ECX + 0x38];
- MOV EDX, DWORD PTR DS : [ECX + 0x14];
- IMUL EAX, DWORD PTR DS : [ECX + 0x34];
- SUB EDX, EAX;
- MOV DWORD PTR DS : [ECX + 0x1C], EDX;
- Frtn:
- RETN;
- FuncRetn:
- NOP;
- POP EDI;
- POP ESI;
- POP EBP;
- RETN 4;
- check37:
- MOV AL, BYTE PTR DS : [ECX + 0xC];
- AND DWORD PTR DS : [ECX + 0x30], 0;
- CMP AL, 0x0FF;
- JNZ SHORT check38;
- MOV EAX, DWORD PTR DS : [ECX + 0x38];
- SUB DWORD PTR DS : [ECX + 0x1C], EAX;
- RETN;
- Finished:
- MOV ESP,EBP;
- POP EBP;
- //Debug VS Release build have different stack sizes. The following is needed for the return parameters and CTYPES
- #ifdef _DEBUG
- ADD ESI, 0x120;
- #else
- ADD ESI, 0x58; //Need for Pythnon CTypes return parameters!
- #endif
- RETN;
- }
- }
- return TRUE;
- }
通過(guò)IDA Pro或者例如Immunity Debugger這樣的反匯編程序來(lái)獲取匯編代碼并不難,但是在獲得之后,還需要我們進(jìn)行一些處理。特別需要注意的一個(gè)地方就是在代碼塊中進(jìn)行的函數(shù)調(diào)用。在匯編中,每一次調(diào)用過(guò)程都需要一個(gè)名稱(標(biāo)簽),并且所有的代碼需要按照調(diào)用順序正確地排列,否則將產(chǎn)生意外的結(jié)果,或者是直接崩潰。因此,我們?cè)趶?fù)制每個(gè)函數(shù)的匯編代碼時(shí)都需要非常謹(jǐn)慎。在剛剛的例子中,為了方便快速,我直接使用了“check”來(lái)表示函數(shù)名稱或者跳轉(zhuǎn)的位置。
由于LZW使用索引將數(shù)據(jù)編碼到字典中,解壓例程所做的第一件事,就是分配內(nèi)存中的16512字節(jié)(0x4080)的緩沖區(qū)來(lái)創(chuàng)建字典。在匯編中,它使用C++ API malloc分配緩沖區(qū),并將緩沖區(qū)設(shè)置為NULL(這是malloc的工作方式)。有一種更簡(jiǎn)單有效的方法,是使用calloc函數(shù),在減少指令數(shù)量的前提下實(shí)現(xiàn)緩沖區(qū)的分配。
我們首先在C++中進(jìn)行編碼,然后再Visual Studio中使用__asm關(guān)鍵字內(nèi)嵌匯編語(yǔ)言。在__asm內(nèi)的代碼塊就是我們放置匯編指令并進(jìn)行必要調(diào)整的位置:
將EBX設(shè)置為0;
從棧中減去64字節(jié)(0x40),以防止我們覆蓋任何棧的數(shù)據(jù);
將棧指針保存到ESI中;
EDI指向我們通過(guò)calloc創(chuàng)建的字典緩沖區(qū);
EAX指向我們的源數(shù)據(jù);
EDX指向我們的目標(biāo)緩沖區(qū)。
為了滿足解壓縮算法的要求,我們手工添加了下面的9行代碼,其余代碼直接從Immunity Debugger中復(fù)制即可:
- xor ebx, ebx; //Need to clear ebx register
- SUB ESP, 0x40; //Need to subtract stack, so we don’t overwrite some Ctypes return data
- MOV ESI, ESP;
- PUSH EAX;
- POP EDI; //Our Temp Buffer
- PUSH[EBP + 8]; //Source Buffer
- POP EAX;
- PUSH[EBP + 0xC]; //Destination Buffer
- POP EDX;
此時(shí),我們需要做的就是更新匯編調(diào)用,跳轉(zhuǎn)到有意義的名稱,并按正確的順序來(lái)排列它們。現(xiàn)在代碼應(yīng)該可以編譯并運(yùn)行了。但當(dāng)例程結(jié)束后,我們必須手動(dòng)恢復(fù)棧,從而讓Python ctypes返回到正確的調(diào)用方。我們添加了以下代碼:
- Finished:
- MOV ESP,EBP;
- POP EBP;
- //Debug VS Release build have different stack sizes. The following is needed for the return parameters and CTYPES
- #ifdef _DEBUG
- ADD ESI, 0x120;
- #else
- ADD ESI, 0x58; //Need for CTypes return parameters!!!!
- #endif
- RETN;
- }
在這里,我們嘗試恢復(fù)堆棧指針寄存器(SP)和基址指針寄存器(BP),并將0x120或0x58添加到ESI,具體要取決于VS的版本是測(cè)試版還是正式版。
調(diào)用DLL
至此,我們就有了一個(gè)DLL,可以開始調(diào)用它,并通過(guò)Python和ctypes來(lái)傳遞它的數(shù)據(jù)。下面這個(gè)Python腳本的作用就是利用這個(gè)DLL,來(lái)解密Reaver的數(shù)據(jù):
- #-------------------------------------------------------------------------------
- # Name: LzwDecompression
- # Purpose:
- #
- # Author: Mike Harbison Unit 42
- #
- # Created: 11/11/2017
- #-------------------------------------------------------------------------------
分享名稱:一種快速提取惡意軟件解密邏輯代碼的方法
文章網(wǎng)址:http://fisionsoft.com.cn/article/coeecoe.html


咨詢
建站咨詢
