准備
簡介:
PEiD(PE Identifier)是一款著名的查殼工具,其功能強大,幾乎可以偵測出所有的殼,其數量已超過470 種PE 文檔 的加殼類型和簽名。
整個過程需要測試文件成品:https://www.lanzous.com/b07r7qu0d
首先使用PEiD檢測之前做的一個異常捕捉測試程序。源碼在下面,編譯器為VC++ 6.0,編譯方法為 Win32 Release
#include <stdio.h> class CExcepctionBase { public: virtual const char* GetExcepctionInfo() = 0; }; class CDiv0Excepction :public CExcepctionBase { public: CDiv0Excepction() { printf("CExcepctionDiv0()\r\n"); } virtual ~CDiv0Excepction() { printf("~CDiv0Excepction()\r\n"); } virtual const char* GetExcepctionInfo() { return "div zero excepction"; } }; class CAccessExcepction :public CExcepctionBase { public: CAccessExcepction() { printf("CAccessExcepction()\r\n"); } virtual ~CAccessExcepction() { printf("~CAccessExcepction()\r\n"); } virtual const char* GetExcepctionInfo() { return "access excepction"; } }; void TestExcepction(int n) { try { if (1 == n) { throw 3; } if (2 == n) { throw 3.0f; } if (3 == n) { throw '3'; } if (4 == n) { throw 3.0; } if (5 == n) { throw CDiv0Excepction(); } if (6 == n) { throw CAccessExcepction(); } if (7 == n) { CAccessExcepction excAccess; throw& excAccess; } } catch (int n) { printf("catch int %d\r\n", n); } catch (float f) { printf("catch float %f\r\n", f); } catch (char c) { printf("catch char %c\r\n", c); } catch (double d) { printf("catch double %f\r\n", d); } catch (CExcepctionBase &exc) { printf("catch error %s\r\n", exc.GetExcepctionInfo()); } catch (CAccessExcepction *pExc) { printf("catch error %s\r\n", pExc->GetExcepctionInfo()); } catch (...) { printf("catch ... ..."); } printf("Test End!\r\n"); } int main() { for (int i = 1; i <= 8; ++i) { TestExcepction(i); } return 0; }
使用PEiD檢測情況
文件判定分析
函數定位
從PEiD的分析情況,可以看到“Microsoft Visual C++ 6.0”的字符串,使用OD打開PEiD,找到字符串位置后下斷點
00438FF6 |> \8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C] 00438FFD |> 6A 18 push 0x18 00438FFF |. 68 285A4000 push upPEiD.00405A28 ; ASCII "Microsoft Visual C++ 6.0" 00439004 |> 8D4D 04 lea ecx,dword ptr ss:[ebp+0x4] 00439007 |. E8 04D4FFFF call upPEiD.00436410
實際上,運行到此處時,已經結束了文件判斷分析階段,得到了結果,在上一條指令(紅線指引),我們可以返回到跳轉之前的函數,即是文件判定函數。
文件判定函數分析
接着向上查找,找到函數的入口處,設置斷點,開始文件判定函數的分析
00438C20 /$ 81EC 88040000 sub esp,0x488 00438C26 |. 53 push ebx 00438C27 |. 55 push ebp 00438C28 |. 56 push esi 00438C29 |. 57 push edi 00438C2A |. B0 72 mov al,0x72 ; 定義特征碼 00438C2C |. 884424 2F mov byte ptr ss:[esp+0x2F],al 00438C30 |. 884424 31 mov byte ptr ss:[esp+0x31],al 00438C34 |. 884424 34 mov byte ptr ss:[esp+0x34],al 00438C38 |. 884424 39 mov byte ptr ss:[esp+0x39],al 00438C3C |. 884424 3D mov byte ptr ss:[esp+0x3D],al 00438C40 |. B0 63 mov al,0x63 ; 定義特征碼 00438C42 |. 884424 40 mov byte ptr ss:[esp+0x40],al 00438C46 |. 884424 41 mov byte ptr ss:[esp+0x41],al 00438C4A |. B0 73 mov al,0x73 ; 定義特征碼 00438C4C |. 884424 43 mov byte ptr ss:[esp+0x43],al 00438C50 |. 884424 44 mov byte ptr ss:[esp+0x44],al 00438C54 |. B0 6C mov al,0x6C ; 定義特征碼 00438C56 |. 884424 47 mov byte ptr ss:[esp+0x47],al 00438C5A |. 884424 48 mov byte ptr ss:[esp+0x48],al 00438C5E |. 8BB424 A00400>mov esi,dword ptr ss:[esp+0x4A0] 00438C65 |. 8B46 0C mov eax,dword ptr ds:[esi+0xC] ; PE首地址,即IMAGE_NT_HEADERS 00438C68 |. 8B56 18 mov edx,dword ptr ds:[esi+0x18] ; ".text"節首地址 00438C6B |. B1 6D mov cl,0x6D ; 定義特征碼 00438C6D |. 884C24 36 mov byte ptr ss:[esp+0x36],cl 00438C71 |. 884C24 3E mov byte ptr ss:[esp+0x3E],cl 00438C75 |. B3 41 mov bl,0x41 ; 定義特征碼 00438C77 |. C64424 2C 7B mov byte ptr ss:[esp+0x2C],0x7B 00438C7C |. C64424 2D 4F mov byte ptr ss:[esp+0x2D],0x4F 00438C81 |. C64424 2E 75 mov byte ptr ss:[esp+0x2E],0x75 00438C86 |. C64424 30 50 mov byte ptr ss:[esp+0x30],0x50 00438C8B |. C64424 32 6F mov byte ptr ss:[esp+0x32],0x6F 00438C90 |. C64424 33 67 mov byte ptr ss:[esp+0x33],0x67 00438C95 |. C64424 35 61 mov byte ptr ss:[esp+0x35],0x61 00438C9A |. C64424 37 44 mov byte ptr ss:[esp+0x37],0x44 00438C9F |. C64424 38 69 mov byte ptr ss:[esp+0x38],0x69 00438CA4 |. C64424 3A 7D mov byte ptr ss:[esp+0x3A],0x7D 00438CA9 |. C64424 3B 5C mov byte ptr ss:[esp+0x3B],0x5C 00438CAE |. 885C24 3C mov byte ptr ss:[esp+0x3C],bl 00438CB2 |. 885C24 3F mov byte ptr ss:[esp+0x3F],bl 00438CB6 |. C64424 42 65 mov byte ptr ss:[esp+0x42],0x65 00438CBB |. C64424 45 2E mov byte ptr ss:[esp+0x45],0x2E 00438CC0 |. C64424 46 64 mov byte ptr ss:[esp+0x46],0x64 00438CC5 |. C64424 18 4D mov byte ptr ss:[esp+0x18],0x4D 00438CCA |. C64424 19 53 mov byte ptr ss:[esp+0x19],0x53 00438CCF |. C64424 1A 43 mov byte ptr ss:[esp+0x1A],0x43 00438CD4 |. C64424 1B 46 mov byte ptr ss:[esp+0x1B],0x46 00438CD9 |. 0FB740 06 movzx eax,word ptr ds:[eax+0x6] ; eax中為IMAGE_NT_HEADERS首地址,[eax+0x6]為Section Number(節數目) = 3 00438CDD |. 8D0C80 lea ecx,dword ptr ds:[eax+eax*4] ; 節數目乘5 00438CE0 |. 8B6CCA E8 mov ebp,dword ptr ds:[edx+ecx*8-0x18] ; 得到".data"所占大小 00438CE4 |. 8D44CA D8 lea eax,dword ptr ds:[edx+ecx*8-0x28] ; 保存".data"節的首地址 00438CE8 |. 8B78 14 mov edi,dword ptr ds:[eax+0x14] ; ".data"在磁盤中的偏移 00438CEB |. 8B46 04 mov eax,dword ptr ds:[esi+0x4] ; 第二個參數指向結構中的第二項數據 00438CEE |. 03FD add edi,ebp ; ".data"偏移地址+".data"節所占大小=".data"節末尾 00438CF0 |. 8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C] ; 獲取第一個參數 00438CF7 |. 8D8F 00390000 lea ecx,dword ptr ds:[edi+0x3900] ; .data節在內存中的位置 00438CFD |. 3BC1 cmp eax,ecx ; 判斷第二個參數是否不小於.data節(.data之后就是OEP),如果成功,跳過OEP檢查 00438CFF |. 73 1A jnb XupPEiD.00438D1B ; 跳過OEP檢查 00438D01 |. 8B55 20 mov edx,dword ptr ss:[ebp+0x20] ; 獲取到程序入口地址 00438D04 |. 85D2 test edx,edx ; 檢查OEP 00438D06 |. 74 13 je XupPEiD.00438D1B 00438D08 |. 8B4E 18 mov ecx,dword ptr ds:[esi+0x18] ; .text節首地址 00438D0B |. 8B79 14 mov edi,dword ptr ds:[ecx+0x14] ; .text節文件偏移 00438D0E |. 0379 10 add edi,dword ptr ds:[ecx+0x10] ; .text節文件偏移+.text節大小=.text節末尾 00438D11 |. 3BD7 cmp edx,edi ; 判斷OEP是否在.text節中 00438D13 |. 0F82 E4020000 jb upPEiD.00438FFD ; 如果在,跳轉,檢查結束
通過,分析實際上這個函數就做了兩件事,一是判定第二個參數是否在.data節中,二是判斷OEP是否在.text節中。對於節區以及對應位置功能的判斷,可以使用PEView,010 Editor以及結合OD寄存器區判斷,這里不給出判定過程了。但是,在這里卻沒有用到特征碼,我們將最后一步的跳轉命令nop。分析OEP檢查錯誤情況的代碼。
OEP檢查錯誤和編譯器判斷
00438D13 90 nop ; 如果在,跳轉,檢查結束 00438D14 90 nop 00438D15 90 nop 00438D16 90 nop 00438D17 90 nop 00438D18 90 nop ; ************下面的代碼是OEP檢查失敗的情況************ 00438D19 |. 8BFA mov edi,edx ; OEP偏移地址存入EDI,0x1634 00438D1B |> 2BC7 sub eax,edi ; 保存.data節的末尾地址 00438D1D |. 83F8 09 cmp eax,0x9 ; 判斷OEP是否在.data節中 00438D20 |. 0F82 D7020000 jb upPEiD.00438FFD ; 不在就跳轉 00438D26 |. 8B16 mov edx,dword ptr ds:[esi] ; edx保存IMAGE_DOS_HEADER首地址 00438D28 |. 8D0C3A lea ecx,dword ptr ds:[edx+edi] ; 得到OEP的地址 00438D2B |. 8B11 mov edx,dword ptr ds:[ecx] ; 將OEP前四個直接存入edx中,edx=0x6AEC8B55 00438D2D |. 81FA 496E7374 cmp edx,0x74736E49 ; OEP與特征碼比較 00438D33 |. 75 15 jnz XupPEiD.00438D4A ; 條件成立,跳轉,不成立則繼續比較OEP后雙字的數據 00438D35 |. 8179 04 616C6C5>cmp dword ptr ds:[ecx+0x4],0x536C6C61 ; OEP與特征碼比較 00438D3C |. 75 0C jnz XupPEiD.00438D4A ; 成立則跳轉 00438D3E |. 6A 17 push 0x17 ; 壓入字符串長度 00438D40 |. 68 B45A4000 push upPEiD.00405AB4 ; ASCII "InstallShield 2003 Stub" 00438D45 |. E9 BA020000 jmp upPEiD.00439004 ; 跳轉到顯示字符串函數處 00438D4A |> 81FA 64617461 cmp edx,0x61746164 ; OEP與特征碼比較 00438D50 |. 75 27 jnz XupPEiD.00438D79 00438D52 |. 8179 04 312E636>cmp dword ptr ds:[ecx+0x4],0x61632E31 ; 下面實際上就是一些其他版本的特征碼比較了 00438D59 |. 75 1E jnz XupPEiD.00438D79 00438D5B |. 68 B45A4000 push upPEiD.00405AB4 ; ASCII "InstallShield 2003 Stub" 00438D60 |. 8D4D 04 lea ecx,dword ptr ss:[ebp+0x4] 00438D63 |. E8 38E9FFFF call upPEiD.004376A0 00438D68 |. 5F pop edi 00438D69 |. 5E pop esi 00438D6A |. C645 00 01 mov byte ptr ss:[ebp],0x1 00438D6E |. 5D pop ebp 00438D6F |. B0 01 mov al,0x1 00438D71 |. 5B pop ebx 00438D72 |. 81C4 88040000 add esp,0x488 00438D78 |. C3 retn 00438D79 |> 3D 00020000 cmp eax,0x200 00438D7E |. BD 00020000 mov ebp,0x200 00438D83 |. 77 02 ja XupPEiD.00438D87 00438D85 |. 8BE8 mov ebp,eax 00438D87 |> 6A 1D push 0x1D 00438D89 |. 8D4424 30 lea eax,dword ptr ss:[esp+0x30] 00438D8D |. 50 push eax 00438D8E |. 8D8C24 98000000 lea ecx,dword ptr ss:[esp+0x98] 00438D95 |. E8 26E5FFFF call upPEiD.004372C0 00438D9A |. 8B16 mov edx,dword ptr ds:[esi] 00438D9C |. 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10] 00438DA0 |. 51 push ecx 00438DA1 |. 55 push ebp 00438DA2 |. 03D7 add edx,edi 00438DA4 |. 52 push edx 00438DA5 |. 8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C] 00438DAC |. E8 4FE6FFFF call upPEiD.00437400 00438DB1 |. 84C0 test al,al 00438DB3 |. 74 26 je XupPEiD.00438DDB 00438DB5 |. 8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C] 00438DBC |. 6A 1B push 0x1B 00438DBE |. 68 985A4000 push upPEiD.00405A98 ; ASCII "Silicon Realms Install Stub" 00438DC3 |. 8D4E 04 lea ecx,dword ptr ds:[esi+0x4] 00438DC6 |. E8 45D6FFFF call upPEiD.00436410 00438DCB |. 5F pop edi 00438DCC |. C606 01 mov byte ptr ds:[esi],0x1 00438DCF |. 5E pop esi 00438DD0 |. 5D pop ebp 00438DD1 |. B0 01 mov al,0x1 00438DD3 |. 5B pop ebx 00438DD4 |. 81C4 88040000 add esp,0x488 00438DDA |. C3 retn 00438DDB |> 8B46 04 mov eax,dword ptr ds:[esi+0x4] 00438DDE |. 2BC7 sub eax,edi 00438DE0 |. 3D 00400000 cmp eax,0x4000 00438DE5 |. BD 00400000 mov ebp,0x4000 00438DEA |. 77 02 ja XupPEiD.00438DEE 00438DEC |. 8BE8 mov ebp,eax 00438DEE |> 6A 04 push 0x4 00438DF0 |. 8D4424 1C lea eax,dword ptr ss:[esp+0x1C] 00438DF4 |. 50 push eax 00438DF5 |. 8D8C24 98000000 lea ecx,dword ptr ss:[esp+0x98] 00438DFC |. E8 BFE4FFFF call upPEiD.004372C0 00438E01 |. 8B16 mov edx,dword ptr ds:[esi] 00438E03 |. 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10] 00438E07 |. 51 push ecx 00438E08 |. 55 push ebp 00438E09 |. 03D7 add edx,edi 00438E0B |. 52 push edx 00438E0C |. 8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C] 00438E13 |. E8 E8E5FFFF call upPEiD.00437400 00438E18 |. 84C0 test al,al 00438E1A |. 74 24 je XupPEiD.00438E40 00438E1C |. 8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C] 00438E23 |. 68 845A4000 push upPEiD.00405A84 ; ASCII "InstallShield AFW" 00438E28 |. 8D4E 04 lea ecx,dword ptr ds:[esi+0x4] 00438E2B |. E8 70E8FFFF call upPEiD.004376A0 00438E30 |. 5F pop edi 00438E31 |. C606 01 mov byte ptr ds:[esi],0x1 00438E34 |. 5E pop esi 00438E35 |. 5D pop ebp 00438E36 |. B0 01 mov al,0x1 00438E38 |. 5B pop ebx 00438E39 |. 81C4 88040000 add esp,0x488 00438E3F |. C3 retn 00438E40 |> 8B46 0C mov eax,dword ptr ds:[esi+0xC] ; eax為IMAGE_NT_HEADERS地址=0x64800D8 00438E43 |. 8B40 28 mov eax,dword ptr ds:[eax+0x28] ; eax為代碼段的地址 00438E46 |. 50 push eax 00438E47 |. 8BCE mov ecx,esi 00438E49 |. E8 32A40100 call upPEiD.00453280 ; 計算偏移位置,得到正確的OEP 00438E4E |. 8BF8 mov edi,eax 00438E50 |. 8B46 18 mov eax,dword ptr ds:[esi+0x18] ; 獲取.text節首地址,0x064801D0 00438E53 |. 8B48 14 mov ecx,dword ptr ds:[eax+0x14] ; .text節文件偏移地址 00438E56 |. 0348 10 add ecx,dword ptr ds:[eax+0x10] ; .text節文件偏移地址+.text節大小=.text節末尾偏移地址 00438E59 |. 3BF9 cmp edi,ecx ; 比較OEP是否在.text節中 00438E5B |. 0F82 95010000 jb upPEiD.00438FF6 ; 跳轉到顯示編譯器版本處,此處即顯示"Microsoft Visual C++ 6.0”
因為在第一部分對OEP的檢測中,已經完成的跳轉,實際上是不會執行這一段代碼的,因此對於真正的文件判定代碼,是會調用上面這段函數的。
要找到函數的調用處,因為函數在最后ret時,都會出棧函數調用處的調用地址,所以直接在函數結尾設置斷點,執行觀察棧區。
轉到0x452F46
存放數據處
"真"文件分析函數
對上面分析函數進行分析
00452E90 /$ 64:A1 00000000 mov eax,dword ptr fs:[0] ; 入口地址 00452E96 |. 6A FF push -0x1 00452E98 |. 68 C8CD4600 push upPEiD.0046CDC8 ; 異常處理 00452E9D |. 50 push eax 00452E9E |. 64:8925 0000000>mov dword ptr fs:[0],esp 00452EA5 |. 83EC 10 sub esp,0x10 ; 局部變量空間 00452EA8 |. 56 push esi 00452EA9 |. 8B7424 24 mov esi,dword ptr ss:[esp+0x24] ; 第一個參數 00452EAD |. 8B46 14 mov eax,dword ptr ds:[esi+0x14] 00452EB0 |. 8B40 10 mov eax,dword ptr ds:[eax+0x10] ; 獲取起始相對虛擬偏移地址 00452EB3 |. 57 push edi ; 壓入參數一 00452EB4 |. 8BF9 mov edi,ecx ; 獲取this指針 00452EB6 |. 50 push eax ; 壓入代碼起始RVA 00452EB7 |. 8BCE mov ecx,esi 00452EB9 |. E8 C2030000 call upPEiD.00453280 ; 檢查PE文件格式,將OEP的RWA與RVA進行轉換 00452EBE |. 3B46 04 cmp eax,dword ptr ds:[esi+0x4] ; 函數返回調整之后的OEP 00452EC1 |. 72 15 jb XupPEiD.00452ED8 ; 條件成立,跳轉到分析階段 00452EC3 |. 5F pop edi ; =============分析失敗代碼=========== 00452EC4 |. 32C0 xor al,al 00452EC6 |. 5E pop esi 00452EC7 |. 8B4C24 10 mov ecx,dword ptr ss:[esp+0x10] 00452ECB |. 64:890D 0000000>mov dword ptr fs:[0],ecx 00452ED2 |. 83C4 1C add esp,0x1C 00452ED5 |. C2 0800 retn 0x8 ; ======================================= 00452ED8 |> 53 push ebx 00452ED9 |. 8B5C24 30 mov ebx,dword ptr ss:[esp+0x30] 00452EDD |. 8943 20 mov dword ptr ds:[ebx+0x20],eax ; 保存調整之后的OEP 00452EE0 |. 8B4E 04 mov ecx,dword ptr ds:[esi+0x4] 00452EE3 |. 8B16 mov edx,dword ptr ds:[esi] 00452EE5 |. 2BC8 sub ecx,eax 00452EE7 |. 51 push ecx 00452EE8 |. 03D0 add edx,eax 00452EEA |. 52 push edx ; 載入內存后的程序入口地址 00452EEB |. 8D4C24 14 lea ecx,dword ptr ss:[esp+0x14] 00452EEF |. 51 push ecx 00452EF0 |. 8BCF mov ecx,edi 00452EF2 |. E8 E9740000 call upPEiD.0045A3E0 ; 將OEP代碼與特征碼進行對比--PEiD可以檢查出分析程序是否在可識別的編譯器范圍內 00452EF7 |. 8B4424 14 mov eax,dword ptr ss:[esp+0x14] 00452EFB |. 8B4C24 10 mov ecx,dword ptr ss:[esp+0x10] 00452EFF |. 8BD0 mov edx,eax 00452F01 |. 2BD1 sub edx,ecx 00452F03 |. C1FA 02 sar edx,0x2 00452F06 |. 52 push edx 00452F07 |. 50 push eax 00452F08 |. 51 push ecx 00452F09 |. C74424 30 00000>mov dword ptr ss:[esp+0x30],0x0 00452F11 |. E8 9AF5FFFF call upPEiD.004524B0 ; 根據函數0x45A3E0對OEP處特征碼的對比結果,將特征匹配的處理流程的函數指針,在數組中的下標值都存放在地址ESP+1C的數組中 00452F16 |. 8B7C24 1C mov edi,dword ptr ss:[esp+0x1C] 00452F1A |. 8B4424 20 mov eax,dword ptr ss:[esp+0x20] 00452F1E |. 83C4 0C add esp,0xC 00452F21 |. 3BF8 cmp edi,eax 00452F23 |. 74 37 je XupPEiD.00452F5C ; 沒有匹配的特征函數,結束分析 00452F25 |> 8B07 /mov eax,dword ptr ds:[edi] 00452F27 |. 50 |push eax 00452F28 |. 56 |push esi 00452F29 |. 53 |push ebx 00452F2A |. FF15 8C1E4000 |call dword ptr ds:[0x401E8C] ; 檢查.rdata節是否存在 00452F30 |. 83C4 0C |add esp,0xC 00452F33 |. 84C0 |test al,al 00452F35 |. 75 48 |jnz XupPEiD.00452F7F ; 如果不存在,結束查詢分析 00452F37 |. 8B07 |mov eax,dword ptr ds:[edi] 00452F39 |. 50 |push eax 00452F3A |. 56 |push esi 00452F3B |. 8D0C40 |lea ecx,dword ptr ds:[eax+eax*2] 00452F3E |. 53 |push ebx 00452F3F |. FF148D 8C1E4000 |call dword ptr ds:[ecx*4+0x401E8C] ; 調用分析函數,存放數據的首地址在0x401E8C 00452F46 |. 83C4 0C |add esp,0xC 00452F49 |. 84C0 |test al,al 00452F4B |. 75 32 |jnz XupPEiD.00452F7F 00452F4D |. 8B4424 14 |mov eax,dword ptr ss:[esp+0x14] 00452F51 |. 83C7 04 |add edi,0x4 00452F54 |. 3BF8 |cmp edi,eax 00452F56 |.^ 75 CD \jnz XupPEiD.00452F25 ; 循環跳轉。一直循環到匹配到對應的處理函數
上面的函數,整個過程:
- 對OEP的特征碼比較
- 通過比較結果匹配儲存函數指針的數組中的過程,將下標存儲到數組
- 檢測程序中是否存在.rdata節
- 從存儲下標的數組中取出下標,調用對應的函數。
在第一步中,會產生一個使用OEP的哪些機器碼作為特征碼進行比較的問題(特征碼的定義)。因此,我們進一步分析函數0x45A3E0
00452EF2 |. E8 E9740000 call upPEiD.0045A3E0 ; 將OEP代碼與特征碼進行對比--PEiD可以檢查出分析程序是否在可識別的編譯器范圍內
特征碼分析
0045A3E0 /$ 6A FF push -0x1 0045A3E2 |. 68 38D24600 push upPEiD.0046D238 ; SE 處理程序安裝 0045A3E7 |. 64:A1 00000000 mov eax,dword ptr fs:[0] 0045A3ED |. 50 push eax 0045A3EE |. 64:8925 0000000>mov dword ptr fs:[0],esp 0045A3F5 |. 83EC 14 sub esp,0x14 0045A3F8 |. 53 push ebx 0045A3F9 |. 55 push ebp 0045A3FA |. 33DB xor ebx,ebx 0045A3FC |. 56 push esi 0045A3FD |. 57 push edi 0045A3FE |. 8BF1 mov esi,ecx ; 獲取this指針 0045A400 |. 895C24 10 mov dword ptr ss:[esp+0x10],ebx ; 將數組清零 0045A404 |. 895C24 18 mov dword ptr ss:[esp+0x18],ebx 0045A408 |. 895C24 1C mov dword ptr ss:[esp+0x1C],ebx 0045A40C |. 895C24 20 mov dword ptr ss:[esp+0x20],ebx 0045A410 |. 8B7C24 38 mov edi,dword ptr ss:[esp+0x38] ; 獲取OEP,保存到EDI 0045A414 |. 0FB607 movzx eax,byte ptr ds:[edi] ; 獲取OEP地址處的數據 0045A417 |. 8B4486 14 mov eax,dword ptr ds:[esi+eax*4+0x14] ; 對this指針偏移計算 0045A41B |. 83F8 FF cmp eax,-0x1 0045A41E |. 8B6C24 3C mov ebp,dword ptr ss:[esp+0x3C] ; OEP差值 0045A422 |. 895C24 2C mov dword ptr ss:[esp+0x2C],ebx ; EBX=0,將局部變量清0 0045A426 |. 74 0F je XupPEiD.0045A437 0045A428 |. 55 push ebp 0045A429 |. 57 push edi 0045A42A |. 50 push eax 0045A42B |. 8D4C24 20 lea ecx,dword ptr ss:[esp+0x20] ; 獲取數組首地址 0045A42F |. 51 push ecx 0045A430 |. 8BCE mov ecx,esi ; 將ECX賦值為this指針 0045A432 |. E8 99FDFFFF call upPEiD.0045A1D0 ; 檢查OEP處代碼是否與特征碼相同(將OEP處的字節碼與特征碼對比,從而比較OEP處的機器碼) 0045A437 |> 8B86 14040000 mov eax,dword ptr ds:[esi+0x414] 0045A43D |. 83F8 FF cmp eax,-0x1 0045A440 |. 74 0F je XupPEiD.0045A451 0045A442 |. 55 push ebp 0045A443 |. 57 push edi 0045A444 |. 50 push eax 0045A445 |. 8D5424 20 lea edx,dword ptr ss:[esp+0x20] 0045A449 |. 52 push edx 0045A44A |. 8BCE mov ecx,esi 0045A44C |. E8 7FFDFFFF call upPEiD.0045A1D0 ; 檢查OEP處代碼是否與特征碼相同(將OEP處的字節碼與特征碼對比,從而比較OEP處的機器碼)
機器碼和特征碼的介紹與關系:https://www.cnblogs.com/qiumingcheng/p/5400265.html
在上面的函數中通過0x45A1D0比較OEP的機器碼與特征碼,提取出具有相同特性的編譯器版本。
例如
這是OEP的部分數據
05551634 55 8B EC 6A FF 68 F0 80 40 00 68 40 41 40 00 64 U嬱jh饊@.h@A@.d 05551644 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 10 ?...Pd?....冹 05551654 53 56 57 89 65 E8 FF 15 0C 80 40 00 33 D2 8A D4 SVW塭?.€@.3見? 05551664 89 15 6C BA 40 00 8B C8 81 E1 FF 00 00 00 89 0D ?l篅.嬋佱...? 05551674 68 BA 40 00 C1 E1 08 03 CA 89 0D 64 BA 40 00 C1 h篅.玲蕢.d篅.?
使用數據拼接成機器碼指令
0x55 0x8b 0xec 0x6a 0xff
0045A3E0 55 push ebp 0045A3E1 8BEC mov ebp,esp 0045A3E3 6A FF push -0x1
PEiD解析流程
- PEiD解析編譯器的流程總結:
- 讀取文件,分析出PE結構,保存。
- 檢查OEP,修正OE,再次檢查OEP
- 使用OEP處的機器碼與特征碼比較
- 通過比較結果匹配儲存函數指針的數組中的過程,將下標存儲到數組
- 檢查文件是否存在rdata節
- 循環,從存儲下標的數組中取出下標,調用對應的函數。
- 在處理函數中再次檢查OEP的機器碼與特征碼
- 獲取並顯示編譯器版本
開發環境偽造
在第一次文件判定中,我們知道會檢測OEP是否在.text節中,因此,我們只需要將偽造OEP寫入.text節后,使用HEX Editor改變原來OEP即可
55 8B EC 6A FF 68 F0 80 40 00 68 40 41 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 10 53 56 57 89 65 E8 5F 5E 5B 83 C4 10 58 64 A3 00 00 00 00 58 58 58 58 E8 76 FA FF FF 00 00 00 00
使用一個簡單的Hello World程序進行偽造OEP
1.初始的OEP地址在0xF012C2處,寫入偽造OEP數據
2.保存修改后的文件后,OD打開,起始偏移地址為1810
3.HEX Editor定位到偏移地址0x110處
將原OEP偏移地址0x12C2改為0x1810即可
本次實戰復現主要是對程序特征碼的識別,日后可以用於病毒程序,游戲外掛的識別判斷。遲到了...wokao...