一、破解目标:PE-Armor 0.765 主程序
二、破解工具:OllyDbg v1.10,ImportREC 1.6 Final,LordPE
三、破解作者:DarkBull#126.com
四、破解过程:
1.用HideOD隐藏OllyDbg,忽略所有异常,在第一个段下内存访问断点,解密代码如下:
003B345E 55 PUSH EBP
003B345F 8BEC MOV EBP,ESP
003B3461 83C4 FC ADD ESP,-4
003B3464 60 PUSHAD
003B3465 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+10] ; KEY(20H个字节)
003B3468 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8] ; 段起始地址
003B346B 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C] ; 段大小
003B346E D1EB SHR EBX,1
003B3470 EB 41 JMP SHORT 003B34B3
003B3472 53 PUSH EBX
003B3473 33DB XOR EBX,EBX
003B3475 66:C745 FE>MOV WORD PTR SS:[EBP-2],0
003B347B EB 25 JMP SHORT 003B34A2
003B347D 66:8B16 MOV DX,WORD PTR DS:[ESI]
003B3480 66:23145F AND DX,WORD PTR DS:[EDI+EBX*2] ; EBX为索引
003B3484 B9 1000000>MOV ECX,10
003B3489 33C0 XOR EAX,EAX
003B348B 66:D1E2 SHL DX,1
003B348E 73 01 JNB SHORT 003B3491
003B3490 40 INC EAX
003B3491 ^ E2 F8 LOOPD SHORT 003B348B
003B3493 66:83E0 01 AND AX,1
003B3497 66:8BCB MOV CX,BX
003B349A 66:D3E0 SHL AX,CL
003B349D 66:0145 FE ADD WORD PTR SS:[EBP-2],AX
003B34A1 43 INC EBX
003B34A2 83FB 10 CMP EBX,10
003B34A5 ^ 72 D6 JB SHORT 003B347D
003B34A7 5B POP EBX
003B34A8 66:8B45 FE MOV AX,WORD PTR SS:[EBP-2]
003B34AC 66:8906 MOV WORD PTR DS:[ESI],AX ; 写入代码
003B34AF 83C6 02 ADD ESI,2
003B34B2 4B DEC EBX
003B34B3 0BDB OR EBX,EBX
003B34B5 ^ 75 BB JNZ SHORT 003B3472
003B34B7 61 POPAD
003B34B8 C9 LEAVE
003B34B9 C2 0C00 RET 0C
解密后(段的第四个字节为段压缩前的大小,第八字节为段压缩后的大小)再对该段进行解压缩,解压代码较长,这里省略。
2.修复IAT。
下断点BP GetModuleHandleW,拦截后执行到返回,再查找二进制数8BF00BC9,代码如下:
003A92FD 8BF0 MOV ESI,EAX ; DLL的基址
003A92FF 0BC9 OR ECX,ECX
003A9301 0F85 A5070>JNZ 003A9AAC ; 是否Hook API(不要跳)
003A9307 8BCF MOV ECX,EDI
003A9309 68 00FE98C>PUSH C798FE00
003A930E 50 PUSH EAX
003A930F E8 5D00000>CALL 003A9371
没有被HOOK的函数名解压代码如下:
003A978E 33C0 XOR EAX,EAX ; Patch1
003A9790 AC LODSB
003A9791 EB 07 JMP SHORT 003A979A
003A9793 C0C0 03 ROL AL,3
003A9796 F6D0 NOT AL
003A9798 AA STOSB ; 写入函数名
003A9799 AC LODSB
003A979A 0BC0 OR EAX,EAX
003A979C ^ 75 F5 JNZ SHORT 003A9793
003A979E AA STOSB
被HOOK的函数名解压代码(在堆栈里)如下:
0012FF68 50 PUSH EAX
0012FF69 AC LODSB
0012FF6A 34 79 XOR AL,79
0012FF6C 2C 55 SUB AL,55
0012FF6E C0C0 03 ROL AL,3
0012FF71 F6D0 NOT AL
0012FF73 AA STOSB ; 写入函数名
0012FF74 31C0 XOR EAX,EAX
0012FF76 49 DEC ECX
0012FF77 ^ 75 F0 JNZ SHORT 0012FF69
0012FF79 AA STOSB
0012FF7A 58 POP EAX
0012FF7B C3 RET
当模块为kernel32.dll和user32.dll时,在003A978E写入Patch代码:
003A978E AC LODSB ; Patch1
003A978F 34 79 XOR AL,79
003A9791 2C 55 SUB AL,55
003A9793 C0C0 03 ROL AL,3
003A9796 F6D0 NOT AL
003A9798 AA STOSB ; 写入函数名
003A9799 AC LODSB
003A979A 0BC0 OR EAX,EAX
003A979C ^ 75 F1 JNZ SHORT 003A978F
003A979E AA STOSB
等壳处理完所有DLL后,用ImportREC获得IAT,有8个地址未解析,为壳模拟的系统函数(大概有23个吧),偶只有手动追踪了。完整的IAT如下:
OEP: 00015675 IATRVA: 0003E000 IATSize: 000002A4
FThunk: 0003E000 NbFunc: 00000003
1 0003E000 advapi32.dll 01EE RegQueryValueExA
1 0003E004 advapi32.dll 01E4 RegOpenKeyExA
1 0003E008 advapi32.dll 01CB RegCloseKey
FThunk: 0003E010 NbFunc: 00000001
1 0003E010 comctl32.dll 0011 InitCommonControls
FThunk: 0003E018 NbFunc: 00000001
1 0003E018 comdlg32.dll 006E GetOpenFileNameA
FThunk: 0003E020 NbFunc: 0000000A
1 0003E020 gdi32.dll 0013 BitBlt
1 0003E024 gdi32.dll 002D CreateCompatibleBitmap
1 0003E028 gdi32.dll 003B CreateFontIndirectA
1 0003E02C gdi32.dll 0051 CreateSolidBrush
1 0003E030 gdi32.dll 01B5 GetTextExtentPoint32A
1 0003E034 gdi32.dll 020F SelectObject
1 0003E038 gdi32.dll 0217 SetBkMode
1 0003E03C gdi32.dll 023D SetTextColor
1 0003E040 gdi32.dll 024F TextOutA
1 0003E044 gdi32.dll 002E CreateCompatibleDC
FThunk: 0003E04C NbFunc: 00000053
1 0003E04C kernel32.dll 02A4 ReadFile
1 0003E050 kernel32.dll 02C6 RtlZeroMemory
1 0003E054 kernel32.dll 0307 SetFilePointer
1 0003E058 kernel32.dll 033E SizeofResource
1 0003E05C kernel32.dll 033F Sleep
1 0003E060 kernel32.dll 00E0 FindResourceA
1 0003E064 kernel32.dll 0258 MapViewOfFile
1 0003E068 kernel32.dll 01D2 GetTickCount
1 0003E06C kernel32.dll 0242 LoadLibraryA
1 0003E070 kernel32.dll 0247 LoadResource
1 0003E074 kernel32.dll 038C WriteFile
1 0003E078 kernel32.dll 0391 WritePrivateProfileStringA
1 0003E07C kernel32.dll 03A4 lstrcat
1 0003E080 kernel32.dll 03AA lstrcmpi
1 0003E084 kernel32.dll 0063 CreateProcessA
1 0003E088 kernel32.dll 0051 CreateFileMappingA
1 0003E08C kernel32.dll 0050 CreateFileA
1 0003E090 kernel32.dll 0040 CopyFileA
1 0003E094 kernel32.dll 01C9 GetTempPathA
1 0003E098 kernel32.dll 01AD GetStartupInfoA
1 0003E09C kernel32.dll 0198 GetProcAddress
1 0003E0A0 kernel32.dll 018E GetPrivateProfileIntA
1 0003E0A4 kernel32.dll 0176 GetModuleHandleA
1 0003E0A8 kernel32.dll 015C GetFileSize
1 0003E0AC kernel32.dll 00F1 FreeLibrary
1 0003E0B0 kernel32.dll 037B WaitForSingleObject
1 0003E0B4 kernel32.dll 00B7 ExitProcess
1 0003E0B8 kernel32.dll 0082 DeleteFileA
1 0003E0BC kernel32.dll 006D CreateThread
1 0003E0C0 kernel32.dll 036E VirtualFree
1 0003E0C4 kernel32.dll 035B UnmapViewOfFile
1 0003E0C8 kernel32.dll 036B VirtualAlloc
1 0003E0CC kernel32.dll 0032 CloseHandle
1 0003E0D0 kernel32.dll 02C5 RtlUnwind
1 0003E0D4 kernel32.dll 0297 RaiseException
1 0003E0D8 kernel32.dll 02FE SetEndOfFile
1 0003E0DC kernel32.dll 0038 CompareStringA
1 0003E0E0 kernel32.dll 004C CreateEventA
1 0003E0E4 kernel32.dll 0098 EnumCalendarInfoA
1 0003E0E8 kernel32.dll 00EC FormatMessageA
1 0003E0EC kernel32.dll 00F7 GetACP
1 0003E0F0 kernel32.dll 00FE GetCPInfo
1 0003E0F4 kernel32.dll 0146 GetDiskFreeSpaceA
1 0003E0F8 kernel32.dll 016B GetLocalTime
1 0003E0FC kernel32.dll 01B1 GetStringTypeExA
1 0003E100 kernel32.dll 01DC GetVersionExA
1 0003E104 kernel32.dll 01EB GlobalAlloc
1 0003E108 kernel32.dll 01F2 GlobalFree
1 0003E10C kernel32.dll 01F6 GlobalLock
1 0003E110 kernel32.dll 01F5 GlobalHandle
1 0003E114 kernel32.dll 01F9 GlobalReAlloc
1 0003E118 kernel32.dll 01FD GlobalUnlock
1 0003E11C kernel32.dll 02BD ResetEvent
1 0003E120 kernel32.dll 0302 SetEvent
1 0003E124 kernel32.dll 034C TlsAlloc
1 0003E128 kernel32.dll 034D TlsFree
1 0003E12C kernel32.dll 034E TlsGetValue
1 0003E130 kernel32.dll 034F TlsSetValue
1 0003E134 kernel32.dll 015F GetFileType
1 0003E138 kernel32.dll 01AF GetStdHandle
1 0003E13C kernel32.dll 010A GetCommandLineA
1 0003E140 kernel32.dll 0358 UnhandledExceptionFilter
1 0003E144 kernel32.dll 00CD FindClose
1 0003E148 kernel32.dll 00D1 FindFirstFileA
1 0003E14C kernel32.dll 021E InterlockedIncrement
1 0003E150 kernel32.dll 0373 VirtualQuery
1 0003E154 kernel32.dll 0080 DeleteCriticalSection
1 0003E158 kernel32.dll 0241 LeaveCriticalSection
1 0003E15C kernel32.dll 0097 EnterCriticalSection
1 0003E160 kernel32.dll 0216 InitializeCriticalSection
1 0003E164 kernel32.dll 024C LocalFree
1 0003E168 kernel32.dll 0248 LocalAlloc
1 0003E16C kernel32.dll 013F GetCurrentThreadId
1 0003E170 kernel32.dll 021A InterlockedDecrement
1 0003E174 kernel32.dll 03B0 lstrcpyn
1 0003E178 kernel32.dll 0243 LoadLibraryExA
1 0003E17C kernel32.dll 037F WideCharToMultiByte
1 0003E180 kernel32.dll 0265 MultiByteToWideChar
1 0003E184 kernel32.dll 03B3 lstrlen
1 0003E188 kernel32.dll 016C GetLocaleInfoA
1 0003E18C kernel32.dll 01CD GetThreadLocale
1 0003E190 kernel32.dll 0174 GetModuleFileNameA
1 0003E194 kernel32.dll 0169 GetLastError
FThunk: 0003E19C NbFunc: 00000019
1 0003E19C oleaut32.dll 0008 VariantInit
1 0003E1A0 oleaut32.dll 0009 VariantClear
1 0003E1A4 oleaut32.dll 007D VarBoolFromStr
1 0003E1A8 oleaut32.dll 0071 VarBstrFromCy
1 0003E1AC oleaut32.dll 000B VariantCopyInd
1 0003E1B0 oleaut32.dll 0006 SysFreeString
1 0003E1B4 oleaut32.dll 000A VariantCopy
1 0003E1B8 oleaut32.dll 0093 VariantChangeTypeEx
1 0003E1BC oleaut32.dll 0072 VarBstrFromDate
1 0003E1C0 oleaut32.dll 00AD VarNeg
1 0003E1C4 oleaut32.dll 00AE VarNot
1 0003E1C8 oleaut32.dll 0040 VarI4FromStr
1 0003E1CC oleaut32.dll 0054 VarR8FromStr
1 0003E1D0 oleaut32.dll 005E VarDateFromStr
1 0003E1D4 oleaut32.dll 0068 VarCyFromStr
1 0003E1D8 oleaut32.dll 0005 SysReAllocStringLen
1 0003E1DC oleaut32.dll 0014 SafeArrayGetLBound
1 0003E1E0 oleaut32.dll 0013 SafeArrayGetUBound
1 0003E1E4 oleaut32.dll 0074 VarBstrFromBool
1 0003E1E8 oleaut32.dll 000F SafeArrayCreate
1 0003E1EC oleaut32.dll 0028 SafeArrayRedim
1 0003E1F0 oleaut32.dll 0094 SafeArrayPtrOfIndex
1 0003E1F4 oleaut32.dll 0019 SafeArrayGetElement
1 0003E1F8 oleaut32.dll 001A SafeArrayPutElement
1 0003E1FC oleaut32.dll 0004 SysAllocStringLen
FThunk: 0003E204 NbFunc: 00000004
1 0003E204 shell32.dll 008A DragAcceptFiles
1 0003E208 shell32.dll 008B DragFinish
1 0003E20C shell32.dll 008C DragQueryFile
1 0003E210 shell32.dll 0167 ShellExecuteA
FThunk: 0003E218 NbFunc: 00000020
1 0003E218 user32.dll 01DC MessageBeep
1 0003E21C user32.dll 0254 SetDlgItemTextA
1 0003E220 user32.dll 0128 GetKeyboardType
1 0003E224 user32.dll 002B CharNextA
1 0003E228 user32.dll 015E GetSystemMetrics
1 0003E22C user32.dll 0056 CreateDialogParamA
1 0003E230 user32.dll 0039 CheckDlgButton
1 0003E234 user32.dll 000E BeginPaint
1 0003E238 user32.dll 02D9 wsprintfA
1 0003E23C user32.dll 027B SetTimer
1 0003E240 user32.dll 0284 SetWindowPos
1 0003E244 user32.dll 0287 SetWindowTextA
1 0003E248 user32.dll 0293 ShowWindow
1 0003E24C user32.dll 01DD MessageBoxA
1 0003E250 user32.dll 023C SendMessageA
1 0003E254 user32.dll 01C9 LoadStringA
1 0003E258 user32.dll 01B6 LoadBitmapA
1 0003E25C user32.dll 01B3 KillTimer
1 0003E260 user32.dll 0178 GetWindowTextA
1 0003E264 user32.dll 0112 GetDlgItem
1 0003E268 user32.dll 0111 GetDlgCtrlID
1 0003E26C user32.dll 010D GetDC
1 0003E270 user32.dll 00E3 FillRect
1 0003E274 user32.dll 00CC EnumChildWindows
1 0003E278 user32.dll 00C9 EndPaint
1 0003E27C user32.dll 00C5 EnableWindow
1 0003E280 user32.dll 009F DialogBoxParamA
1 0003E284 user32.dll 0061 CreateWindowExA
1 0003E288 user32.dll 022B ReleaseDC
1 0003E28C user32.dll 0237 SendDlgItemMessageA
1 0003E290 user32.dll 0200 PostMessageA
1 0003E294 user32.dll 0202 PostQuitMessage
FThunk: 0003E29C NbFunc: 00000001
1 0003E29C winmm.dll 0041 mciSendCommandA
3.寻找OEP。
在第一个段下内存访问断点,会发现壳对原代码的JMP和CALL的偏移地址进行修正,继续运行,最后停在OEP,代码如下:
00415675 C705 4B0E4>MOV DWORD PTR DS:[440E4B],0 ; OEP
0041567F 6A 00 PUSH 0
00415681 E8 8671000>CALL prot765.0041C80C ; 被HOOK的GetModuleHandleA
00415686 A3 FC15440>MOV DWORD PTR DS:[4415FC],EAX
0041568B E8 AE72000>CALL prot765.0041C93E ; JMP to comctl32.InitCommonControls
00415690 8D35 01024>LEA ESI,DWORD PTR DS:[440201]
00415696 8D3D 341B4>LEA EDI,DWORD PTR DS:[441B34]
0041569C B9 1000000>MOV ECX,10
004156A1 F3:A4 REP MOVSB
004156A3 C705 181B4>MOV DWORD PTR DS:[441B18],-0C
004156AD C705 281B4>MOV DWORD PTR DS:[441B28],109
004156B7 C605 2F1B4>MOV BYTE PTR DS:[441B2F],1
004156BE 6A 00 PUSH 0
004156C0 68 E156410>PUSH prot765.004156E1
004156C5 6A 00 PUSH 0
004156C7 68 1F00440>PUSH prot765.0044001F ; ASCII "IDD_DIALOG1"
004156CC FF35 FC154>PUSH DWORD PTR DS:[4415FC]
004156D2 E8 D771000>CALL prot765.0041C8AE
004156D7 6A 00 PUSH 0
004156D9 E8 1671000>CALL prot765.0041C7F4
004156DE 33C0 XOR EAX,EAX
004156E0 C3 RET
4.修复被HOOK的API。
进入0041C80C,发现原本JMP DWORD PTR DS:[XXXXXXXX]的形式被HOOK成NOP; CALL 003B2B53,代码如下:
<HookAPI>> 50 PUSH EAX
003B2B54 60 PUSHAD
003B2B55 E8 0000000>CALL 003B2B5A
003B2B5A 5D POP EBP
003B2B5B 81ED 3B164>SUB EBP,41163B
003B2B61 8B7C24 24 MOV EDI,DWORD PTR SS:[ESP+24]
003B2B65 8BB5 A5414>MOV ESI,DWORD PTR SS:[EBP+4141A5]
003B2B6B 8B8D 034B4>MOV ECX,DWORD PTR SS:[EBP+414B03]
003B2B71 8B048E MOV EAX,DWORD PTR DS:[ESI+ECX*4] ; ESI为被HOOK的地址表
003B2B74 33D2 XOR EDX,EDX
003B2B76 99 CDQ
003B2B77 25 FFFFFF7>AND EAX,7FFFFFFF
003B2B7C 0385 4D414>ADD EAX,DWORD PTR SS:[EBP+41414D]
003B2B82 3BC7 CMP EAX,EDI ; 根据返回地址查表
003B2B84 75 10 JNZ SHORT 003B2B96
003B2B86 8D348E LEA ESI,DWORD PTR DS:[ESI+ECX*4]
003B2B89 0BD2 OR EDX,EDX
003B2B8B 75 04 JNZ SHORT 003B2B91
003B2B8D EB 66 JMP SHORT 003B2BF5
003B2B8F EB 05 JMP SHORT 003B2B96
003B2B91 E9 E101000>JMP 003B2D77 ; 出口
003B2B96 8B85 A9414>MOV EAX,DWORD PTR SS:[EBP+4141A9]
003B2B9C C1E8 02 SHR EAX,2
003B2B9F 83E8 02 SUB EAX,2
003B2BA2 894424 F8 MOV DWORD PTR SS:[ESP-8],EAX
003B2BA6 33C0 XOR EAX,EAX
003B2BA8 894424 FC MOV DWORD PTR SS:[ESP-4],EAX
003B2BAC 8B4C24 FC MOV ECX,DWORD PTR SS:[ESP-4]
003B2BB0 034C24 F8 ADD ECX,DWORD PTR SS:[ESP-8]
003B2BB4 D1E9 SHR ECX,1
003B2BB6 8B048E MOV EAX,DWORD PTR DS:[ESI+ECX*4]
003B2BB9 33D2 XOR EDX,EDX
003B2BBB 99 CDQ
003B2BBC 25 FFFFFF7>AND EAX,7FFFFFFF
003B2BC1 0385 4D414>ADD EAX,DWORD PTR SS:[EBP+41414D]
003B2BC7 3BC7 CMP EAX,EDI ; 根据返回地址查表
003B2BC9 75 18 JNZ SHORT 003B2BE3
003B2BCB 898D 034B4>MOV DWORD PTR SS:[EBP+414B03],ECX
003B2BD1 8D348E LEA ESI,DWORD PTR DS:[ESI+ECX*4]
003B2BD4 0BD2 OR EDX,EDX
003B2BD6 75 04 JNZ SHORT 003B2BDC
003B2BD8 EB 1B JMP SHORT 003B2BF5
003B2BDA EB 17 JMP SHORT 003B2BF3
003B2BDC E9 9601000>JMP 003B2D77 ; 出口
003B2BE1 EB 10 JMP SHORT 003B2BF3
003B2BE3 3BC7 CMP EAX,EDI
003B2BE5 76 07 JBE SHORT 003B2BEE
003B2BE7 49 DEC ECX
003B2BE8 894C24 F8 MOV DWORD PTR SS:[ESP-8],ECX
003B2BEC EB 05 JMP SHORT 003B2BF3
003B2BEE 41 INC ECX
003B2BEF 894C24 FC MOV DWORD PTR SS:[ESP-4],ECX
003B2BF3 ^ EB B7 JMP SHORT 003B2BAC
向下查找二进制数8B00894424246183C404C3,找到代码如下:
003B2EE5 0385 4D414>ADD EAX,DWORD PTR SS:[EBP+41414D] ; EAX为IAT地址
003B2EEB 2B85 71414>SUB EAX,DWORD PTR SS:[EBP+414171]
003B2EF1 8B00 MOV EAX,DWORD PTR DS:[EAX] ; EAX为函数地址
003B2EF3 894424 24 MOV DWORD PTR SS:[ESP+24],EAX
003B2EF7 61 POPAD
003B2EF8 83C4 04 ADD ESP,4
003B2EFB C3 RET
找到IAT地址后,就可以还原被HOOK的API了。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: