逆向分析AHpack

时间:2023-03-09 22:02:58
逆向分析AHpack

从暑假开始逆向研究也有一个半月了,今晚分析了一个压缩壳,第一次脱离书本逆向一个程序,放上来纪念一下。

其实像这种壳完全可以esp定律秒掉的,之所以分析它,是因为我想知道所谓IAT修复具体是怎么个算法,还有压缩壳到底流程是怎么样的,我认为学逆向最大的乐趣就是可以满足人的好奇心,只要精力够,程序的每个细节是怎么做的都可以知道。

aplib部分看上去比较烦,以我现在水平去分析,那简直太烧脑子了。

其实aplib部分我觉得作者本来应该是放在一个函数里的,这个现象是编译器优化所造成的

004040FF > 60 PUSHAD
00404100 68 54404000 PUSH AHpack.00404054 ; ASCII "KERNEL32.DLL"
00404105 B8 48404000 MOV EAX,<&KERNEL32.GetModuleHandleA>
0040410A FF10 CALL DWORD PTR DS:[EAX] ; 获得kernerl32基地址
0040410C 68 B3404000 PUSH AHpack.004040B3 ; ASCII "GlobalAlloc"
00404111 50 PUSH EAX
00404112 B8 44404000 MOV EAX,<&KERNEL32.GetProcAddress>
00404117 FF10 CALL DWORD PTR DS:[EAX] ; 从kernel32里获取GlobalAlloc函数
00404119 68 00080000 PUSH 800
0040411E 6A 40 PUSH 40 ; GPTR
00404120 FFD0 CALL EAX ; 申请800字节
00404122 8905 CA404000 MOV DWORD PTR DS:[4040CA],EAX
00404128 89C7 MOV EDI,EAX
0040412A BE 00104000 MOV ESI,AHpack.00401000
0040412F 60 PUSHAD ; 开始aplib
00404130 FC CLD
00404131 B2 80 MOV DL,80
00404133 31DB XOR EBX,EBX
00404135 A4 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 
00404136 B3 02 MOV BL,2
00404138 E8 6D000000 CALL AHpack.004041AA
0040413D ^ 73 F6 JNB SHORT AHpack.00404135
0040413F 31C9 XOR ECX,ECX
00404141 E8 64000000 CALL AHpack.004041AA
00404146 73 1C JNB SHORT AHpack.00404164
00404148 31C0 XOR EAX,EAX
0040414A E8 5B000000 CALL AHpack.004041AA
0040414F 73 23 JNB SHORT AHpack.00404174
00404151 B3 02 MOV BL,2
00404153 41 INC ECX
00404154 B0 10 MOV AL,10
00404156 E8 4F000000 CALL AHpack.004041AA
0040415B 10C0 ADC AL,AL
0040415D ^ 73 F7 JNB SHORT AHpack.00404156
0040415F 75 3F JNZ SHORT AHpack.004041A0
00404161 AA STOS BYTE PTR ES:[EDI]
00404162 ^ EB D4 JMP SHORT AHpack.00404138
00404164 E8 4D000000 CALL AHpack.004041B6
00404169 29D9 SUB ECX,EBX
0040416B 75 10 JNZ SHORT AHpack.0040417D
0040416D E8 42000000 CALL AHpack.004041B4
00404172 EB 28 JMP SHORT AHpack.0040419C
00404174 AC LODS BYTE PTR DS:[ESI]
00404175 D1E8 SHR EAX,1
00404177 74 4D JE SHORT AHpack.004041C6
00404179 11C9 ADC ECX,ECX
0040417B EB 1C JMP SHORT AHpack.00404199
0040417D 91 XCHG EAX,ECX
0040417E 48 DEC EAX
0040417F C1E0 08 SHL EAX,8
00404182 AC LODS BYTE PTR DS:[ESI]
00404183 E8 2C000000 CALL AHpack.004041B4
00404188 3D 007D0000 CMP EAX,7D00
0040418D 73 0A JNB SHORT AHpack.00404199
0040418F 80FC 05 CMP AH,5
00404192 73 06 JNB SHORT AHpack.0040419A
00404194 83F8 7F CMP EAX,7F
00404197 77 02 JA SHORT AHpack.0040419B
00404199 41 INC ECX
0040419A 41 INC ECX
0040419B 95 XCHG EAX,EBP
0040419C 89E8 MOV EAX,EBP
0040419E B3 01 MOV BL,1
004041A0 56 PUSH ESI
004041A1 89FE MOV ESI,EDI
004041A3 29C6 SUB ESI,EAX
004041A5 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
004041A7 5E POP ESI
004041A8 ^ EB 8E JMP SHORT AHpack.00404138
004041AA 00D2 ADD DL,DL
004041AC 75 05 JNZ SHORT AHpack.004041B3
004041AE 8A16 MOV DL,BYTE PTR DS:[ESI]
004041B0 46 INC ESI
004041B1 10D2 ADC DL,DL
004041B3 C3 RETN
004041B4 31C9 XOR ECX,ECX
004041B6 41 INC ECX
004041B7 E8 EEFFFFFF CALL AHpack.004041AA
004041BC 11C9 ADC ECX,ECX
004041BE E8 E7FFFFFF CALL AHpack.004041AA
004041C3 ^ 72 F2 JB SHORT AHpack.004041B7
004041C5 C3 RETN
004041C6 61 POPAD ; 结束aplib,数据解到404120处申请的内存中
004041C7 B9 FC070000 MOV ECX,7FC
004041CC 8B1C08 MOV EBX,DWORD PTR DS:[EAX+ECX]
004041CF 8999 00104000 MOV DWORD PTR DS:[ECX+401000],EBX
004041D5 ^ E2 F5 LOOPD SHORT AHpack.004041CC ; 404120处申请的内存包含解压后数据,把它拷贝到oep处
004041D7 90 NOP ; 下面开始修复IAT,呵呵,9090不会是故意给个分割吧
004041D8 90 NOP
004041D9 BA 00004000 MOV EDX,AHpack.00400000
004041DE BE 70200000 MOV ESI,2070
004041E3 01D6 ADD ESI,EDX ; esi用来迭代IMAGE_IMPORT_DESCRIPTOR,esi现在初始化为指向第一个IMAGE_IMPORT_DESCRIPTOR的指针
004041E5 8B46 0C MOV EAX,DWORD PTR DS:[ESI+C] ; eax指向要修复的dll名
004041E8 85C0 TEST EAX,EAX
004041EA 0F84 87000000 JE AHpack.00404277 ; 如果全部修复完毕就跳转
004041F0 01D0 ADD EAX,EDX
004041F2 89C3 MOV EBX,EAX
004041F4 50 PUSH EAX
004041F5 B8 48404000 MOV EAX,<&KERNEL32.GetModuleHandleA>
004041FA FF10 CALL DWORD PTR DS:[EAX] ; 获取要修复dll的基地址
004041FC 85C0 TEST EAX,EAX
004041FE 75 08 JNZ SHORT AHpack.00404208 ; 如果获取失败,就加载一次
00404200 53 PUSH EBX
00404201 B8 4C404000 MOV EAX,<&KERNEL32.LoadLibraryA>
00404206 FF10 CALL DWORD PTR DS:[EAX]
00404208 8905 CE404000 MOV DWORD PTR DS:[4040CE],EAX ; 要修复dll基址存到4040CE
0040420E C705 D2404000 0>MOV DWORD PTR DS:[4040D2],0 ; 4040D2用来描述此dll已经修复的个数,[4040D2]/4=已修复个数
00404218 BA 00004000 MOV EDX,AHpack.00400000
0040421D 8B06 MOV EAX,DWORD PTR DS:[ESI]
0040421F 85C0 TEST EAX,EAX
00404221 75 03 JNZ SHORT AHpack.00404226
00404223 8B46 10 MOV EAX,DWORD PTR DS:[ESI+10]
00404226 01D0 ADD EAX,EDX ; 基地址加IAT的偏移
00404228 0305 D2404000 ADD EAX,DWORD PTR DS:[4040D2] ; 再加修复次数*4
0040422E 8B18 MOV EBX,DWORD PTR DS:[EAX] ; [eax]指向IMPORT_BY_NAME
00404230 8B7E 10 MOV EDI,DWORD PTR DS:[ESI+10]
00404233 01D7 ADD EDI,EDX
00404235 033D D2404000 ADD EDI,DWORD PTR DS:[4040D2]
0040423B 85DB TEST EBX,EBX
0040423D 74 2B JE SHORT AHpack.0040426A ; 如果这个dll已经修复完则跳转
0040423F F7C3 00000080 TEST EBX,80000000 ; 判断下是否取错数据
00404245 75 04 JNZ SHORT AHpack.0040424B
00404247 01D3 ADD EBX,EDX
00404249 43 INC EBX ; 因为第一个字段占一个word,所以两次inc是为了访问IMPORT_BY_NAME.Name
0040424A 43 INC EBX
0040424B 81E3 FFFFFF0F AND EBX,0FFFFFFF ; 前4位清零
00404251 53 PUSH EBX ; 要修复函数名
00404252 FF35 CE404000 PUSH DWORD PTR DS:[4040CE] ; 要修复函数所在的dll
00404258 B8 44404000 MOV EAX,<&KERNEL32.GetProcAddress>
0040425D FF10 CALL DWORD PTR DS:[EAX] ; 使用GetProcAddress把正确地址取出来
0040425F 8907 MOV DWORD PTR DS:[EDI],EAX ; 修复IAT
00404261 8305 D2404000 0>ADD DWORD PTR DS:[4040D2],4 ; 已修复个数+1
00404268 ^ EB AE JMP SHORT AHpack.00404218 ; 跳上去继续修复下一个函数
0040426A 83C6 14 ADD ESI,14 ; 0x14为IMAGE_IMPORT_DESCRIPTOR大小,继续迭代到下个dll
0040426D BA 00004000 MOV EDX,AHpack.00400000 ; 这步是多余操作
00404272 ^ E9 6EFFFFFF JMP AHpack.004041E5 ; 跳上去继续修复下一个dll
00404277 68 54404000 PUSH AHpack.00404054 ; ASCII "KERNEL32.DLL"
0040427C B8 48404000 MOV EAX,<&KERNEL32.GetModuleHandleA>
00404281 FF10 CALL DWORD PTR DS:[EAX] ; 获得kernel32基地址
00404283 68 BF404000 PUSH AHpack.004040BF ; ASCII "GlobalFree"
00404288 50 PUSH EAX
00404289 B8 44404000 MOV EAX,<&KERNEL32.GetProcAddress>
0040428E FF10 CALL DWORD PTR DS:[EAX] ; 从kernel32取GlobalFree()
00404290 8B15 CA404000 MOV EDX,DWORD PTR DS:[4040CA]
00404296 52 PUSH EDX
00404297 FFD0 CALL EAX ; 释放之前申请的buffer
00404299 61 POPAD
0040429A BA 00104000 MOV EDX,AHpack.00401000
0040429F FFE2 JMP EDX ; 跳oep
004042A1 90 NOP
004042A2 C3 RETN

qq1454322323