前言:以前版分析的一个版本,通过对旧版的了解可以很快的掌握新版的变化的,新版刚看完,谢谢hnhuqiong的帮助,脚本太多了,我自己看不下去:-(,
我还是选择了自己的方法,走了一程。走了后感觉新版变化也不是很大,虽然多
乱序IAT和特殊代码加密转换了一种比较方式,不过去乱序iat感觉就像鸡肋,
特殊代码处理虽然有一定难度,但很可惜,花指令太死了,如果有足够的时间的话,可以完全不用去掉花指令跟踪到特殊代码,也许是Magic esp的烂用吧:-),
没有任何的杀伤力可言。
当然这个壳的精彩代码是非常不错的,也因此非常感谢hexer。这段代码我现在还专门记录下来了:-).这篇文章把Simxx和hexer部分没有分析清楚的,自己补了一下。新版的总体流程还是差不多的。
Hying's PeLock v0.7x 外壳分析
【目 标】:Delphi
【工 具】:Olydbg1.1(diy版)
【任 务】:分析外壳loader
【操作平台】:Windows XP sp2
【作 者】:LOVEBOOM[DFCG][FCG][US]
【相关链接】:NONE
【简要说明】:Hying的外壳上次没有完全分析完下篇,这回来个全面的,外壳有几个地方很有"意思",新版本的花指令也比较有"意思"的.也随便把Hexer和simonzh2000
文章中没有分析明白的,自己分析了下.文章我大部分地方用了标签来注明,也因此很少额外写注释的.应该直接看下就知道什么意思了,看完后,事理一下可以做出
一个和原版一样的loader来的:-).
【详细过程】:
因为全面分析的文章,所以我也懒得多打几个字.边分析边写吧:-).
用OD载入,下断Bp VirtualAlloc然后执行到返回,之所以这样是因为前面的解压代码很是无聊,也没有什么价值,直接入主题更好:-).
来到这里:
0045A11A 6A 04 PUSH 4
0045A11C 68 00100000 PUSH 1000
0045A121 FF75 10 PUSH DWORD PTR SS:[EBP+10]
0045A124 6A 00 PUSH 0
0045A126 FF55 2C CALL DWORD PTR SS:[EBP+2C] ; VirtualAlloc
0045A129 50 PUSH EAX ; 返回这里
0045A12A 8945 0C MOV DWORD PTR SS:[EBP+C], EAX
0045A12D 8B5D 08 MOV EBX, DWORD PTR SS:[EBP+8]
0045A130 03DD ADD EBX, EBP
0045A132 50 PUSH EAX
0045A133 53 PUSH EBX
0045A134 E8 18000000 CALL <aplib_Unpack> ; 解压代码
0045A139 5A POP EDX ; 0012FFE0
0045A13A 52 PUSH EDX
0045A13B 55 PUSH EBP
0045A13C 8D85 DE000000 LEA EAX, DWORD PTR SS:[EBP+DE]
0045A142 C600 EB MOV BYTE PTR DS:[EAX], 0EB ; 对dll的再次重入进行处理
0045A145 C640 01 10 MOV BYTE PTR DS:[EAX+1], 10
0045A149 8B45 30 MOV EAX, DWORD PTR SS:[EBP+30]
0045A14C 8945 74 MOV DWORD PTR SS:[EBP+74], EAX
0045A14F - FFE2 JMP EDX ; 这里跳去壳的部分
************************************************************************************************************************************************
aplib_Unpack:
0045A151 > 60 PUSHAD ; aplib_Unpack
0045A152 8B7424 24 MOV ESI, DWORD PTR SS:[ESP+24] ; aplib解压代码,后面壳里还会用到一次
0045A156 8B7C24 28 MOV EDI, DWORD PTR SS:[ESP+28] ; 因此直接抓下来
0045A15A FC CLD
0045A15B B2 80 MOV DL, 80
0045A15D 33DB XOR EBX, EBX
0045A15F A4 MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
0045A160 B3 02 MOV BL, 2
0045A162 E8 6D000000 CALL 0045A1D4
0045A167 ^ 73 F6 JNB SHORT 0045A15F
0045A169 33C9 XOR ECX, ECX
0045A16B E8 64000000 CALL 0045A1D4
0045A170 73 1C JNB SHORT 0045A18E
0045A172 33C0 XOR EAX, EAX
0045A174 E8 5B000000 CALL 0045A1D4
0045A179 73 23 JNB SHORT 0045A19E
0045A17B B3 02 MOV BL, 2
0045A17D 41 INC ECX
0045A17E B0 10 MOV AL, 10
0045A180 E8 4F000000 CALL 0045A1D4
0045A185 12C0 ADC AL, AL
0045A187 ^ 73 F7 JNB SHORT 0045A180
0045A189 75 3F JNZ SHORT 0045A1CA
0045A18B AA STOS BYTE PTR ES:[EDI]
0045A18C ^ EB D4 JMP SHORT 0045A162
0045A18E E8 4D000000 CALL 0045A1E0
0045A193 2BCB SUB ECX, EBX
0045A195 75 10 JNZ SHORT 0045A1A7
0045A197 E8 42000000 CALL 0045A1DE
0045A19C EB 28 JMP SHORT 0045A1C6
0045A19E AC LODS BYTE PTR DS:[ESI]
0045A19F D1E8 SHR EAX, 1
0045A1A1 74 4D JE SHORT 0045A1F0
0045A1A3 13C9 ADC ECX, ECX
0045A1A5 EB 1C JMP SHORT 0045A1C3
0045A1A7 91 XCHG EAX, ECX
0045A1A8 48 DEC EAX
0045A1A9 C1E0 08 SHL EAX, 8
0045A1AC AC LODS BYTE PTR DS:[ESI]
0045A1AD E8 2C000000 CALL 0045A1DE
0045A1B2 3D 007D0000 CMP EAX, 7D00
0045A1B7 73 0A JNB SHORT 0045A1C3
0045A1B9 80FC 05 CMP AH, 5
0045A1BC 73 06 JNB SHORT 0045A1C4
0045A1BE 83F8 7F CMP EAX, 7F
0045A1C1 77 02 JA SHORT 0045A1C5
0045A1C3 41 INC ECX
0045A1C4 41 INC ECX
0045A1C5 95 XCHG EAX, EBP
0045A1C6 8BC5 MOV EAX, EBP
0045A1C8 B3 01 MOV BL, 1
0045A1CA 56 PUSH ESI
0045A1CB 8BF7 MOV ESI, EDI
0045A1CD 2BF0 SUB ESI, EAX
0045A1CF F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
0045A1D1 5E POP ESI ; 0012FFE0
0045A1D2 ^ EB 8E JMP SHORT 0045A162
0045A1D4 02D2 ADD DL, DL
0045A1D6 75 05 JNZ SHORT 0045A1DD
0045A1D8 8A16 MOV DL, BYTE PTR DS:[ESI]
0045A1DA 46 INC ESI
0045A1DB 12D2 ADC DL, DL
0045A1DD C3 RETN
0045A1DE 33C9 XOR ECX, ECX
0045A1E0 41 INC ECX
0045A1E1 E8 EEFFFFFF CALL 0045A1D4
0045A1E6 13C9 ADC ECX, ECX
0045A1E8 E8 E7FFFFFF CALL 0045A1D4
0045A1ED ^ 72 F2 JB SHORT 0045A1E1
0045A1EF C3 RETN
0045A1F0 2B7C24 28 SUB EDI, DWORD PTR SS:[ESP+28] ; kernel32.7C816D4F
0045A1F4 897C24 1C MOV DWORD PTR SS:[ESP+1C], EDI
0045A1F8 61 POPAD
0045A1F9 C2 0800 RETN 8
************************************************************************************************************************************************
jmp edx,来到这里:
00370000 E8 24000000 CALL 00370029 ; 这里有很多无意义的异常,跳过这一段没用的垃圾代码的说明
00370005 8B4424 04 MOV EAX, DWORD PTR SS:[ESP+4]
00370009 8B00 MOV EAX, DWORD PTR DS:[EAX]
0037000B 3D 04000080 CMP EAX, 80000004
00370010 75 08 JNZ SHORT 0037001A
00370012 8B6424 08 MOV ESP, DWORD PTR SS:[ESP+8]
.......
经过N个漫长的SEH,飞到下面来:
003731DE 8B06 MOV EAX, DWORD PTR DS:[ESI] ; 循环把API搬到壳中,取两次
003731E0 90 NOP
003731E1 90 NOP
003731E2 90 NOP
003731E3 90 NOP
003731E4 90 NOP
003731E5 90 NOP
003731E6 90 NOP
003731E7 8907 MOV DWORD PTR DS:[EDI], EAX ; 从00375A8A开始
003731E9 90 NOP
003731EA 90 NOP
003731EB 90 NOP
003731EC 90 NOP
003731ED 90 NOP
003731EE 90 NOP
003731EF 90 NOP
003731F0 90 NOP
003731F1 90 NOP
003731F2 90 NOP
003731F3 90 NOP
003731F4 83C6 04 ADD ESI, 4
003731F7 90 NOP
003731F8 90 NOP
003731F9 90 NOP
003731FA 90 NOP
003731FB 90 NOP
003731FC 83C7 04 ADD EDI, 4
003731FF 90 NOP
00373200 90 NOP
00373201 90 NOP
00373202 90 NOP
00373203 ^ E2 D9 LOOPD SHORT 003731DE
00373205 90 NOP
00373206 90 NOP
00373207 90 NOP
00373208 90 NOP
00373209 90 NOP
0037320A 8B45 04 MOV EAX, DWORD PTR SS:[EBP+4]
0037320D 90 NOP
0037320E 90 NOP
0037320F 90 NOP
00373210 90 NOP
00373211 90 NOP
00373212 90 NOP
00373213 90 NOP
00373214 90 NOP
00373215 90 NOP
00373216 90 NOP
00373217 90 NOP
00373218 8982 B2434000 MOV DWORD PTR DS:[EDX+<IMGBASE>], EAX
0037321E 90 NOP
0037321F 90 NOP
00373220 90 NOP
00373221 90 NOP
00373222 90 NOP
00373223 90 NOP
00373224 90 NOP
00373225 8D85 51010000 LEA EAX, DWORD PTR SS:[EBP+151]
0037322B 90 NOP
0037322C 90 NOP
0037322D 90 NOP
0037322E 90 NOP
0037322F 90 NOP
00373230 8982 12444000 MOV DWORD PTR DS:[EDX+404412], EAX
00373236 90 NOP
00373237 90 NOP
00373238 90 NOP
00373239 90 NOP
0037323A 90 NOP
0037323B 8B45 2C MOV EAX, DWORD PTR SS:[EBP+2C]
0037323E 90 NOP
0037323F 90 NOP
00373240 90 NOP
00373241 90 NOP
00373242 90 NOP
00373243 90 NOP
00373244 90 NOP
00373245 90 NOP
00373246 90 NOP
00373247 90 NOP
00373248 90 NOP
00373249 90 NOP
0037324A 90 NOP
0037324B 90 NOP
0037324C 90 NOP
0037324D 90 NOP
0037324E 90 NOP
0037324F 90 NOP
00373250 90 NOP
00373251 90 NOP
00373252 8982 AE434000 MOV DWORD PTR DS:[EDX+<APIVirtualAlloc>], EAX ; VirtualAlloc
00373258 90 NOP
00373259 90 NOP
......
003732F9 6A 00 PUSH 0 ; 获取 ImageBase
003732FB FF95 A6434000 CALL DWORD PTR SS:[EBP+<GetModhandle>] ; kernel32.GetModuleHandleA
00373301 90 NOP
00373302 90 NOP
00373303 90 NOP
00373304 68 C2100000 PUSH 10C2
00373309 E8 01000000 CALL 0037330F
0037330E 90 NOP
0037330F 68 24080E68 PUSH 680E0824
00373314 68 90908344 PUSH 44839090
00373319 - FFE4 JMP ESP ; 呵呵,有个性的花指令这里指令没有起什么作用只是跳去下一步而已
0037331B 90 NOP
0037331C 8985 B2434000 MOV DWORD PTR SS:[EBP+<IMGBASE>], EAX
......
00373339 6A 04 PUSH 4
0037333B 68 00100000 PUSH 1000
00373340 68 00100000 PUSH 1000
00373345 6A 00 PUSH 0
00373347 FF95 AE434000 CALL DWORD PTR SS:[EBP+<APIVirtualAlloc>] ; kernel32.VirtualAlloc
0037334D 8985 E5494000 MOV DWORD PTR SS:[EBP+<hMEM334d>], EAX ; 申请空间
00373353 5E POP ESI ; 下面就准备开始壳中最为精彩的代码了
00373354 E8 28010000 CALL <Important_SEH> ; 这里开始精彩代码
下面开始引用HEXER那篇文章里讲的,这个目标也是差不多,只是代码不是一开始就解压出来了,每层都是动态解压出来的,我是开两个来记录的.
嗯看精彩代码:
;********************************************************************************************************
;=====注意看精彩片段开始了==================================================================================
TELOCK中有一段曾经被称为非常精彩的代码,下面这一段是青处于蓝而胜于蓝,精彩倍增:
00373359 E8 04000000 CALL <SEH_Disposal>
0037335E 90 NOP
0037335F 90 NOP
00373360 90 NOP
00373361 90 NOP
00373362 > 5A POP EDX ; SEH_Disposal
00373363 8B4424 04 MOV EAX, DWORD PTR SS:[ESP+4]
00373367 8B00 MOV EAX, DWORD PTR DS:[EAX] ; EXCEPTION REASON
00373369 8B4C24 0C MOV ECX, DWORD PTR SS:[ESP+C] ; pContext
0037336D C701 17000100 MOV DWORD PTR DS:[ECX], 10017
00373373 FF81 B8000000 INC DWORD PTR DS:[ECX+B8] ; regEIP+1
00373379 3D 03000080 CMP EAX, 80000003 ; 判断是否为断点异常int 3
0037337E 75 51 JNZ SHORT <SINGLE STEP BREAKPIONT >
00373380 8B81 B4000000 MOV EAX, DWORD PTR DS:[ECX+B4] ; 第一次断点异常后,壳开始设置硬件断点实现DEBUG他自己
00373386 8D80 F41D4000 LEA EAX, DWORD PTR DS:[EAX+<Dr0:003734D8>]
0037338C 8941 04 MOV DWORD PTR DS:[ECX+4], EAX ; 设置Dr0
0037338F 8B81 B4000000 MOV EAX, DWORD PTR DS:[ECX+B4]
00373395 8D80 221E4000 LEA EAX, DWORD PTR DS:[EAX+<Dr1:00373506>]
0037339B 8941 08 MOV DWORD PTR DS:[ECX+8], EAX ; 设置Dr1
0037339E 8B81 B4000000 MOV EAX, DWORD PTR DS:[ECX+B4]
003733A4 8D80 4F1E4000 LEA EAX, DWORD PTR DS:[EAX+<Dr2:00373533>]
003733AA 8941 0C MOV DWORD PTR DS:[ECX+C], EAX ; 设置Dr2
003733AD 8B81 B4000000 MOV EAX, DWORD PTR DS:[ECX+B4]
003733B3 8D80 821E4000 LEA EAX, DWORD PTR DS:[EAX+<Dr3:00373566>]
003733B9 8941 10 MOV DWORD PTR DS:[ECX+10], EAX ; 设置Dr3
003733BC 33C0 XOR EAX, EAX
003733BE 8161 14 F00FFFF>AND DWORD PTR DS:[ECX+14], FFFF0FF0 ; 设置Dr6,dr6所有是1的位都是保留为1的,初始化调试状态寄存器
003733C5 C741 18 5501000>MOV DWORD PTR DS:[ECX+18], 155 ; 设置DR7,设置调试控制寄存器,允许4个当前任务的执行断点
003733CC E9 AF000000 JMP <Return_System>
003733D1 > 3D 04000080 CMP EAX, 80000004 ; SINGLE STEP BREAKPIONT
003733D6 75 64 JNZ SHORT <DIVIDE BY ZERO > ; 这里是解密整个壳的关键
003733D8 FF02 INC DWORD PTR DS:[EDX] ; 因为前面设置了四个硬件断点,因此,正常运行的话,肯定会要经过这里的
003733DA 8B02 MOV EAX, DWORD PTR DS:[EDX]
003733DC 83F8 01 CMP EAX, 1 ; Dr0:003734D8异常
003733DF 75 08 JNZ SHORT 003733E9
003733E1 F791 B0000000 NOT DWORD PTR DS:[ECX+B0] ; 第一次异常发生在3734d8处时,执行操作not regEAX
003733E7 EB 4F JMP SHORT 00373438
003733E9 83F8 02 CMP EAX, 2 ; Dr1:00373506异常
003733EC 75 11 JNZ SHORT 003733FF
003733EE 8B81 B0000000 MOV EAX, DWORD PTR DS:[ECX+B0] ; 第二次异常发生在00373506处时,ROL regEAX,13h
003733F4 C1C0 13 ROL EAX, 13
003733F7 8981 B0000000 MOV DWORD PTR DS:[ECX+B0], EAX ; 写回regEAX
003733FD EB 39 JMP SHORT 00373438
003733FF 83F8 03 CMP EAX, 3 ; Dr2:00373533异常
00373402 75 2B JNZ SHORT <Exception Dr3>
00373404 53 PUSH EBX
00373405 8181 B0000000 2>ADD DWORD PTR DS:[ECX+B0], 4B23526 ; 第三次单步异常发生在373533处时,执行add regEAX,4b23526
0037340F 8B81 B0000000 MOV EAX, DWORD PTR DS:[ECX+B0] ; regEAX
00373415 8B99 A4000000 MOV EBX, DWORD PTR DS:[ECX+A4] ; regEBX
0037341B 66:93 XCHG AX, BX ; 相加后 ax和bx交换再加上bx
0037341D 66:03C3 ADD AX, BX
00373420 8981 B0000000 MOV DWORD PTR DS:[ECX+B0], EAX ; 写回eax
00373426 8999 A4000000 MOV DWORD PTR DS:[ECX+A4], EBX ; 写回regEBX
0037342C 5B POP EBX ; 0012FFE0
0037342D EB 09 JMP SHORT 00373438
0037342F > 8B81 A0000000 MOV EAX, DWORD PTR DS:[ECX+A0]
00373435 8030 55 XOR BYTE PTR DS:[EAX], 55 ; Dr3:00373566异常
00373438 33C0 XOR EAX, EAX ; 第四次异常发生时,xor [regESI],55h
0037343A EB 44 JMP SHORT <Return_System>
0037343C > 3D 940000C0 CMP EAX, C0000094 ; DIVIDE BY ZERO
00373441 75 3A JNZ SHORT 0037347D
00373443 C702 00000000 MOV DWORD PTR DS:[EDX], 0
00373449 FF81 B8000000 INC DWORD PTR DS:[ECX+B8] ; inc regEIP
0037344F 33C0 XOR EAX, EAX ; 最后一次除0异常后,写入值到Drx中, 后面要参与计算关键值的
00373451 C741 04 2301FF0>MOV DWORD PTR DS:[ECX+4], 0FFF0123 ; 设置Dr0
00373458 C741 08 6745FF0>MOV DWORD PTR DS:[ECX+8], 0FFF4567 ; 设置Dr1
0037345F C741 0C AB89FF0>MOV DWORD PTR DS:[ECX+C], 0FFF89AB ; 设置Dr2
00373466 C741 10 EFCDFF0>MOV DWORD PTR DS:[ECX+10], 0FFFCDEF ; 设置Dr3
0037346D 8161 14 F00FFFF>AND DWORD PTR DS:[ECX+14], FFFF0FF0 ; 设置Dr6
00373474 C741 18 5501000>MOV DWORD PTR DS:[ECX+18], 155 ; 设置Dr7
0037347B EB 03 JMP SHORT <Return_System>
0037347D 33C0 XOR EAX, EAX
0037347F 40 INC EAX
00373480 > C3 RETN ; Return_System
00373481 > 56 PUSH ESI ; Important_SEH
00373482 8DB5 951C4000 LEA ESI, DWORD PTR SS:[EBP+401C95] ; 进入int3异常之前解压出处理int3的代码
00373488 8BFE MOV EDI, ESI
0037348A B9 55000000 MOV ECX, 55
0037348F AC LODS BYTE PTR DS:[ESI]
00373490 32C1 XOR AL, CL
00373492 C0C0 04 ROL AL, 4
00373495 AA STOS BYTE PTR ES:[EDI]
00373496 ^ E2 F7 LOOPD SHORT 0037348F
00373498 5E POP ESI ; 一层一层的解开,真是"浪费"时间:-)
00373499 33C0 XOR EAX, EAX
0037349B 64:FF35 0000000>PUSH DWORD PTR FS:[0]
003734A2 64:8925 0000000>MOV DWORD PTR FS:[0], ESP
003734A9 CC INT3
003734AA 90 NOP
003734AB 56 PUSH ESI
003734AC 8DB5 ED1C4000 LEA ESI, DWORD PTR SS:[EBP+401CED] ; 循环解压出处理四个单步异常的代码
003734B2 8BFE MOV EDI, ESI
003734B4 B9 6B000000 MOV ECX, 6B
003734B9 AC LODS BYTE PTR DS:[ESI]
003734BA 32C1 XOR AL, CL
003734BC 04 4D ADD AL, 4D
003734BE C0C0 03 ROL AL, 3
003734C1 AA STOS BYTE PTR ES:[EDI]
003734C2 ^ E2 F5 LOOPD SHORT 003734B9
003734C4 5E POP ESI ; 0012FFE0
003734C5 8D8D A01A4000 LEA ECX, DWORD PTR SS:[EBP+<Crc_Start_addr>] ; 解压出处理四个单步异常的代码后,开始检测是代码是否被修改过
003734CB 2BCE SUB ECX, ESI ; 这一招有够利害,直接下CC断点,crc检测通不过
003734CD 33DB XOR EBX, EBX ; 下硬件断点的话,原来的硬件断点就破坏了.
003734CF 33C0 XOR EAX, EAX
003734D1 AC LODS BYTE PTR DS:[ESI]
003734D2 03D8 ADD EBX, EAX ; 计算校验值
003734D4 ^ E2 FB LOOPD SHORT 003734D1
003734D6 8BC3 MOV EAX, EBX
003734D8 F8 CLC ; 第一次异常处,not eax
003734D9 90 NOP
003734DA 8DB5 0D1E4000 LEA ESI, DWORD PTR SS:[EBP+<De1>] ; 异常后开始解压出下面将要执行的代码
003734E0 B9 91250000 MOV ECX, 2591
003734E5 F7E1 MUL ECX
003734E7 D3C8 ROR EAX, CL
003734E9 3006 XOR BYTE PTR DS:[ESI], AL
003734EB 46 INC ESI
003734EC 40 INC EAX
003734ED D40A AAM
003734EF ^ E2 F4 LOOPD SHORT 003734E5
003734F1 B9 D5010000 MOV ECX, 1D5 ; De1
003734F6 8DB5 A01A4000 LEA ESI, DWORD PTR SS:[EBP+<Crc_Start_addr>] ; 刚解压出来代码再次检测内存代码,把计算出的值作为解密KEY
003734FC 33C0 XOR EAX, EAX
003734FE 3206 XOR AL, BYTE PTR DS:[ESI]
00373500 C1C8 08 ROR EAX, 8
00373503 46 INC ESI
00373504 ^ E2 F8 LOOPD SHORT 003734FE
00373506 FC CLD ; 第二次异常处
00373507 90 NOP
00373508 B9 64250000 MOV ECX, 2564 ; rol eax,13
0037350D 8DB5 3A1E4000 LEA ESI, DWORD PTR SS:[EBP+401E3A]
00373513 8D4481 43 LEA EAX, DWORD PTR DS:[ECX+EAX*4+43]
00373517 3006 XOR BYTE PTR DS:[ESI], AL
00373519 D40A AAM
0037351B 46 INC ESI
0037351C ^ E2 F5 LOOPD SHORT 00373513 ; 再次把通过异常中断处理来计算eax的值
0037351E B9 B2000000 MOV ECX, 0B2 ; 通过eax的值来解密出37351e处的代码
00373523 C1E9 02 SHR ECX, 2
00373526 8DB5 9D1D4000 LEA ESI, DWORD PTR SS:[EBP+401D9D] ; 这里从开始解密处的代码处开始计算检测值
0037352C 33DB XOR EBX, EBX
0037352E AD LODS DWORD PTR DS:[ESI]
0037352F 33D8 XOR EBX, EAX
00373531 ^ E2 FB LOOPD SHORT 0037352E ; 这样在这段范围内的代码又不可以被修改又不可以被下断点
00373533 F9 STC ; 第三次异常处
00373534 90 NOP ; 执行add regEAX,4b23526
00373535 B9 2A250000 MOV ECX, 252A ; xchg ax,bx
0037353A C1E9 02 SHR ECX, 2 ; add ax,bx
0037353D 8DB5 741E4000 LEA ESI, DWORD PTR SS:[EBP+401E74]
00373543 33D2 XOR EDX, EDX
00373545 F7E3 MUL EBX
00373547 81C2 2635B204 ADD EDX, 4B23526
0037354D 3116 XOR DWORD PTR DS:[ESI], EDX
0037354F 8BC3 MOV EAX, EBX
00373551 8BDA MOV EBX, EDX
00373553 83C6 04 ADD ESI, 4
00373556 ^ E2 EB LOOPD SHORT 00373543 ; 通过SEH来计算出EAX和ebx的值,用于解出00373558处的代码
00373558 8DB5 8E1E4000 LEA ESI, DWORD PTR SS:[EBP+401E8E]
0037355E B9 C0060000 MOV ECX, 6C0
00373563 C1E9 02 SHR ECX, 2
00373566 90 NOP ; 这里第四次异常,其实也就是把Dr3夹在里面
00373567 90 NOP ; 执行xor [esi],55
00373568 802E 13 SUB BYTE PTR DS:[ESI], 13
0037356B F616 NOT BYTE PTR DS:[ESI]
0037356D 83C6 04 ADD ESI, 4
00373570 ^ E2 F4 LOOPD SHORT 00373566 ; 通过SEH处理来换算出373570处的代码
00373572 8DB5 581D4000 LEA ESI, DWORD PTR SS:[EBP+401D58] ; 到了这里后开始解压出处理除0异常的代码
00373578 8BFE MOV EDI, ESI
0037357A B9 41000000 MOV ECX, 41
0037357F AC LODS BYTE PTR DS:[ESI]
00373580 32C1 XOR AL, CL
00373582 04 63 ADD AL, 63
00373584 AA STOS BYTE PTR ES:[EDI]
00373585 ^ E2 F8 LOOPD SHORT 0037357F
00373587 B8 00010000 MOV EAX, 100
0037358C 33D2 XOR EDX, EDX
0037358E 33DB XOR EBX, EBX
00373590 F7F3 DIV EBX ; DIVIDE BY ZERO,最后一次SEH,恢复一些原始状态
00373592 90 NOP
00373593 64:8F05 0000000>POP DWORD PTR FS:[0] ; 恢复SEH
0037359A 58 POP EAX ; 0012FFE0
;=====此阶段精彩片段结束===================================================================================
;********************************************************************************************************
嗯这里挺过来了就好办,上面这段代码设计的非常不错,操作不当很容易出错的,当然动下脑还是很容易跳过这段代码,我的做法是写个脚本,脚本大概的做法就是把壳原有的
异常都让我的脚本来操作,脚本先把seh时那几个Drx保存起来,然后脚本通知OD去解开代码就成了:-).
继续向下分析:
0037359B 8BFC MOV EDI, ESP ; 用esp来转换解压,有个性的:-)
0037359D 8DA5 9D434000 LEA ESP, DWORD PTR SS:[EBP+40439D] ; 从375a81处开始倒着向上解压
003735A3 B9 B3240000 MOV ECX, 24B3
003735A8 8B85 16444000 MOV EAX, DWORD PTR SS:[EBP+404416]
003735AE BB BDD89800 MOV EBX, 98D8BD
003735B3 BE D5260000 MOV ESI, 26D5
003735B8 > 33D2 XOR EDX, EDX ; Loop_Decode_3735cf
003735BA F7E6 MUL ESI ; 循环解出3735cf处的代码
003735BC 05 78563412 ADD EAX, 12345678
003735C1 83D2 00 ADC EDX, 0
003735C4 F7F3 DIV EBX
003735C6 58 POP EAX ; 0012FFE0
003735C7 32C2 XOR AL, DL
003735C9 50 PUSH EAX
003735CA 4C DEC ESP
003735CB 8BC2 MOV EAX, EDX
003735CD ^ E2 E9 LOOPD SHORT <Loop_Decode_3735cf>
上面精彩的过了,这回来了个变本加厉的,下面还有一段关键代码,不过感觉也太浪费时间做这些工作吧:-),解密代码:
003735CF 8BE7 MOV ESP, EDI
003735D1 E8 51000000 CALL <Fuck_Int3_3627> ; 这里还有好玩的东西
003735D6 8B4C24 0C MOV ECX, DWORD PTR SS:[ESP+C]
003735DA 8B81 B0000000 MOV EAX, DWORD PTR DS:[ECX+B0] ; regEAX
003735E0 8B51 04 MOV EDX, DWORD PTR DS:[ECX+4]
003735E3 F6D0 NOT AL
003735E5 32C2 XOR AL, DL
003735E7 66:25 FF00 AND AX, 0FF
003735EB 66:03D0 ADD DX, AX
003735EE 66:C1CA 03 ROR DX, 3
003735F2 66:8951 04 MOV WORD PTR DS:[ECX+4], DX ; 运算后改变Dr0的值
003735F6 66:3151 08 XOR WORD PTR DS:[ECX+8], DX
003735FA 66:8B51 08 MOV DX, WORD PTR DS:[ECX+8] ; 再把值和Dr1进行运算
003735FE 66:C1CA 02 ROR DX, 2
00373602 66:0151 0C ADD WORD PTR DS:[ECX+C], DX ; 和Dr2进行运算
00373606 66:8B51 0C MOV DX, WORD PTR DS:[ECX+C]
0037360A 66:F7D2 NOT DX
0037360D 66:2B51 10 SUB DX, WORD PTR DS:[ECX+10] ; 和Dr3进行运算
00373611 66:D1CA ROR DX, 1
00373614 66:3151 04 XOR WORD PTR DS:[ECX+4], DX ; 运算后的值再保存回Dr0
00373618 8981 B0000000 MOV DWORD PTR DS:[ECX+B0], EAX ; 写回regEAX
0037361E FF81 B8000000 INC DWORD PTR DS:[ECX+B8] ; inc regEIP
00373624 33C0 XOR EAX, EAX
00373626 C3 RETN
00373627 > 64:FF35 0000000>PUSH DWORD PTR FS:[0] ; Fuck_Int3_3627
0037362E 64:8925 0000000>MOV DWORD PTR FS:[0], ESP
00373635 8DB5 33204000 LEA ESI, DWORD PTR SS:[EBP+402033] ; 准备解开373717处的代码
0037363B B9 C6000000 MOV ECX, 0C6 ; 解压大小0c6
00373640 > 8A0431 MOV AL, BYTE PTR DS:[ECX+ESI] ; loop_Decode_373717
00373643 CC INT3
00373644 90 NOP
00373645 880431 MOV BYTE PTR DS:[ECX+ESI], AL ; 同样是倒序解压
00373648 ^ E2 F6 LOOPD SHORT <loop_Decode_373717> ; 可以看出Drx的值是多么重要了吧:-)
0037364A 64:8F05 0000000>POP DWORD PTR FS:[0] ; 恢复现场
00373651 58 POP EAX ; 0012FFE0
00373652 8D05 6B424000 LEA EAX, DWORD PTR DS:[40426B]
00373658 03C5 ADD EAX, EBP ; 计算出MyGetProcAddress函数的地址
0037365A 8985 9E434000 MOV DWORD PTR SS:[EBP+<MyGetProcAddress>], EAX
;______________________________________________________________________________________________________________________________________
;
; 下面开始壳获取壳所需的相关API函数,先判断DLL有没有载入,如果没有则Load dll,载入后循环的解出API的名字,再用MyGetProcAddress
; 获取相关API的名字,获取到再检测API第一个字节有没有下CC断点
00373660 8DB5 A1444000 LEA ESI, DWORD PTR SS:[EBP+<strDllKernel32>]
00373666 56 PUSH ESI
00373667 8D85 961F4000 LEA EAX, DWORD PTR SS:[EBP+401F96]
0037366D 50 PUSH EAX ; 获取Kernel32.dll的句柄
0037366E 8B85 A6434000 MOV EAX, DWORD PTR SS:[EBP+<GetModhandle>] ; kernel32.GetModuleHandleA
00373674 E9 61130000 JMP <proc_Run_FUN>
00373679 90 NOP
0037367A 8BF0 MOV ESI, EAX
0037367C 8DBD AF444000 LEA EDI, DWORD PTR SS:[EBP+<APIVirtualFree>]
00373682 B9 1B000000 MOV ECX, 1B
00373687 > 57 PUSH EDI ; Fill_Packer_API
00373688 8A07 MOV AL, BYTE PTR DS:[EDI]
0037368A EB 05 JMP SHORT 00373691
0037368C F6D0 NOT AL
0037368E AA STOS BYTE PTR ES:[EDI] ; 解压出API名称
0037368F 8A07 MOV AL, BYTE PTR DS:[EDI]
00373691 0AC0 OR AL, AL
00373693 ^ 75 F7 JNZ SHORT 0037368C
00373695 5F POP EDI ; 0012FFE0
00373696 51 PUSH ECX
00373697 57 PUSH EDI
00373698 56 PUSH ESI
00373699 8D85 C81F4000 LEA EAX, DWORD PTR SS:[EBP+401FC8]
0037369F 50 PUSH EAX
003736A0 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>] ; 获取VirtualFree的地址
003736A6 E9 2F130000 JMP <proc_Run_FUN>
003736AB 90 NOP
003736AC E8 8D150000 CALL <proc_check_CC> ; 检测是否下了CC断点
003736B1 50 PUSH EAX
003736B2 57 PUSH EDI
003736B3 56 PUSH ESI
003736B4 8D85 E31F4000 LEA EAX, DWORD PTR SS:[EBP+401FE3]
003736BA 50 PUSH EAX
003736BB 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>]
003736C1 E9 14130000 JMP <proc_Run_FUN>
003736C6 90 NOP
003736C7 59 POP ECX ; 0012FFE0
003736C8 2BC8 SUB ECX, EAX
003736CA 2BC1 SUB EAX, ECX
003736CC 0FB64F FF MOVZX ECX, BYTE PTR DS:[EDI-1]
003736D0 8907 MOV DWORD PTR DS:[EDI], EAX
003736D2 03F9 ADD EDI, ECX
003736D4 47 INC EDI
003736D5 59 POP ECX ; 0012FFE0
003736D6 ^ E2 AF LOOPD SHORT <Fill_Packer_API> ; 跳回去循环获取KERNEL32.DLL中的相关函数
003736D8 8DB5 1E444000 LEA ESI, DWORD PTR SS:[EBP+<strDllUsr32>]
003736DE 56 PUSH ESI
003736DF 8D85 0E204000 LEA EAX, DWORD PTR SS:[EBP+40200E]
003736E5 50 PUSH EAX
003736E6 8B85 A6434000 MOV EAX, DWORD PTR SS:[EBP+<GetModhandle>] ; kernel32.GetModuleHandleA
003736EC E9 E9120000 JMP <proc_Run_FUN>
003736F1 90 NOP
003736F2 0BC0 OR EAX, EAX
003736F4 75 15 JNZ SHORT 0037370B
003736F6 56 PUSH ESI
003736F7 8D85 27204000 LEA EAX, DWORD PTR SS:[EBP+<strDllUsr32>]
003736FD 50 PUSH EAX
003736FE 8B85 AA434000 MOV EAX, DWORD PTR SS:[EBP+<APILoadLib>] ; kernel32.LoadLibraryA
00373704 E9 D1120000 JMP <proc_Run_FUN>
00373709 90 NOP
0037370A 90 NOP
0037370B 8BF0 MOV ESI, EAX
0037370D 8DBD 2A444000 LEA EDI, DWORD PTR SS:[EBP+<APIwsPrintfA>]
00373713 B9 07000000 MOV ECX, 7
00373718 > 57 PUSH EDI ; De_dllusr32_api
00373719 8A07 MOV AL, BYTE PTR DS:[EDI]
0037371B EB 05 JMP SHORT 00373722
0037371D F6D0 NOT AL
0037371F AA STOS BYTE PTR ES:[EDI] ; 解压出api name
00373720 8A07 MOV AL, BYTE PTR DS:[EDI]
00373722 0AC0 OR AL, AL
00373724 ^ 75 F7 JNZ SHORT 0037371D
00373726 5F POP EDI ; 0012FFE0
00373727 51 PUSH ECX
00373728 57 PUSH EDI
00373729 56 PUSH ESI
0037372A 8D85 5A204000 LEA EAX, DWORD PTR SS:[EBP+40205A]
00373730 50 PUSH EAX
00373731 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>]
00373737 E9 9E120000 JMP <proc_Run_FUN>
0037373C 90 NOP
0037373D 90 NOP
0037373E E8 FB140000 CALL <proc_check_CC>
00373743 50 PUSH EAX
00373744 57 PUSH EDI
00373745 56 PUSH ESI
00373746 8D85 75204000 LEA EAX, DWORD PTR SS:[EBP+402075]
0037374C 50 PUSH EAX
0037374D 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>]
00373753 E9 82120000 JMP <proc_Run_FUN>
00373758 90 NOP
00373759 59 POP ECX ; 0012FFE0
0037375A 2BC8 SUB ECX, EAX
0037375C 2BC1 SUB EAX, ECX
0037375E 0FB64F FF MOVZX ECX, BYTE PTR DS:[EDI-1]
00373762 8907 MOV DWORD PTR DS:[EDI], EAX
00373764 03F9 ADD EDI, ECX
00373766 47 INC EDI
00373767 59 POP ECX ; 0012FFE0
00373768 ^ E2 AE LOOPD SHORT <De_dllusr32_api> ; 循环获取user32.dll的相关函数
0037376A 8DB5 58464000 LEA ESI, DWORD PTR SS:[EBP+<strDllws32_32>]
00373770 56 PUSH ESI
00373771 8D85 A0204000 LEA EAX, DWORD PTR SS:[EBP+4020A0]
00373777 50 PUSH EAX ; 载入dll
00373778 8B85 A6434000 MOV EAX, DWORD PTR SS:[EBP+<GetModhandle>] ; kernel32.GetModuleHandleA
0037377E E9 57120000 JMP <proc_Run_FUN>
00373783 90 NOP
00373784 0BC0 OR EAX, EAX
00373786 75 15 JNZ SHORT 0037379D
00373788 56 PUSH ESI
00373789 8D85 B9204000 LEA EAX, DWORD PTR SS:[EBP+4020B9]
0037378F 50 PUSH EAX
00373790 8B85 AA434000 MOV EAX, DWORD PTR SS:[EBP+<APILoadLib>] ; kernel32.LoadLibraryA
00373796 E9 3F120000 JMP <proc_Run_FUN>
0037379B 90 NOP
0037379C 90 NOP
0037379D 8BF0 MOV ESI, EAX
0037379F 8DBD 64464000 LEA EDI, DWORD PTR SS:[EBP+<APIwsASend>]
003737A5 B9 04000000 MOV ECX, 4
003737AA > 57 PUSH EDI ; De_ws2_32_apis
003737AB 8A07 MOV AL, BYTE PTR DS:[EDI]
003737AD EB 05 JMP SHORT 003737B4
003737AF F6D0 NOT AL
003737B1 AA STOS BYTE PTR ES:[EDI]
003737B2 8A07 MOV AL, BYTE PTR DS:[EDI]
003737B4 0AC0 OR AL, AL
003737B6 ^ 75 F7 JNZ SHORT 003737AF
003737B8 5F POP EDI ; 0012FFE0
003737B9 51 PUSH ECX
003737BA 57 PUSH EDI
003737BB 56 PUSH ESI
003737BC 8D85 EC204000 LEA EAX, DWORD PTR SS:[EBP+4020EC]
003737C2 50 PUSH EAX
003737C3 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>]
003737C9 E9 0C120000 JMP <proc_Run_FUN>
003737CE 90 NOP
003737CF 90 NOP
003737D0 E8 69140000 CALL <proc_check_CC>
003737D5 50 PUSH EAX
003737D6 57 PUSH EDI
003737D7 56 PUSH ESI
003737D8 8D85 07214000 LEA EAX, DWORD PTR SS:[EBP+402107]
003737DE 50 PUSH EAX
003737DF 8B85 9E434000 MOV EAX, DWORD PTR SS:[EBP+<MyGetProcAddress>]
003737E5 E9 F0110000 JMP <proc_Run_FUN>
003737EA 90 NOP
003737EB 59 POP ECX ; 0012FFE0
003737EC 2BC8 SUB ECX, EAX
003737EE 2BC1 SUB EAX, ECX
003737F0 0FB64F FF MOVZX ECX, BYTE PTR DS:[EDI-1]
003737F4 8907 MOV DWORD PTR DS:[EDI], EAX
003737F6 03F9 ADD EDI, ECX
003737F8 47 INC EDI
003737F9 59 POP ECX ; 0012FFE0
003737FA ^ E2 AE LOOPD SHORT <De_ws2_32_apis> ; 循环处理ws2_32的相关函数
; 获取完毕
;______________________________________________________________________________________________________________________________________
获取完壳的相关API后,壳先对文件进行一次检测,判断文件大小是否被改变了,如果改变了则OVER.
003737FC 8B85 B2434000 MOV EAX, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373802 0340 3C ADD EAX, DWORD PTR DS:[EAX+3C] ; pe header
00373805 8B40 50 MOV EAX, DWORD PTR DS:[EAX+50] ; 取出SizofImage
00373808 3385 C6434000 XOR EAX, DWORD PTR SS:[EBP+<xorsizeimg_Key>] ; 取出的SizeofImage和key01a334f8异或
0037380E 8B8D A2434000 MOV ECX, DWORD PTR SS:[EBP+<xorkeyimag>]
00373814 3BC1 CMP EAX, ECX ; 很简单的判断,sizeimg xor 01a334f8=01A6CC88就ok 了
00373816 0F85 222A0000 JNZ <Game_Over> ; 如果文件大小改变了就over了
;★★★★★★★★★★★★★★★★★★★★★★★★★★检测调试器★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
利用CreateFileA进行ANTI检测 \\.\NTICE,\\.\SICE,\\.\TWX2002 \\.\filemon,\\.\regmon,\\.\FILEVXD \\.\REGVXD,\\.\ICEDUMP,\\.\BW2K
这些检测对OD没有作用的:-)
0037381C 8DB5 9C474000 LEA ESI, DWORD PTR SS:[EBP+<Anti_str>]
00373822 46 INC ESI
00373823 B9 09000000 MOV ECX, 9
00373828 EB 58 JMP SHORT 00373882
0037382A > 51 PUSH ECX ; Loop_Check_DBG
0037382B 56 PUSH ESI
0037382C AC LODS BYTE PTR DS:[ESI]
0037382D EB 06 JMP SHORT 00373835
0037382F > F6D0 NOT AL ; De_Str
00373831 8846 FF MOV BYTE PTR DS:[ESI-1], AL ; 解密出\\.\xxxx
00373834 AC LODS BYTE PTR DS:[ESI]
00373835 0AC0 OR AL, AL
00373837 ^ 75 F6 JNZ SHORT <De_Str>
00373839 5E POP ESI ; 0012FFE0
0037383A 6A 00 PUSH 0
0037383C 68 80000000 PUSH 80
00373841 6A 03 PUSH 3
00373843 6A 00 PUSH 0
00373845 6A 03 PUSH 3
00373847 68 000000C0 PUSH C0000000
0037384C 56 PUSH ESI
0037384D 8D85 7C214000 LEA EAX, DWORD PTR SS:[EBP+40217C]
00373853 50 PUSH EAX
00373854 8B85 BC444000 MOV EAX, DWORD PTR SS:[EBP+<APICreateFileA>] ; kernel32.CreateFileA
0037385A E9 7B110000 JMP <proc_Run_FUN>
0037385F 90 NOP
00373860 83F8 FF CMP EAX, -1
00373863 74 05 JE SHORT <No_DBG>
00373865 E9 D4290000 JMP <Game_Over> ; 检测到调试器就over了
0037386A > 56 PUSH ESI ; No_DBG
0037386B AC LODS BYTE PTR DS:[ESI]
0037386C EB 06 JMP SHORT 00373874
0037386E > F6D0 NOT AL ; Crypt_Str
00373870 8846 FF MOV BYTE PTR DS:[ESI-1], AL
00373873 AC LODS BYTE PTR DS:[ESI]
00373874 0AC0 OR AL, AL
00373876 ^ 75 F6 JNZ SHORT <Crypt_Str>
00373878 5E POP ESI ; 0012FFE0
00373879 59 POP ECX ; 0012FFE0
0037387A 0FB646 FF MOVZX EAX, BYTE PTR DS:[ESI-1]
0037387E 03F0 ADD ESI, EAX
00373880 46 INC ESI
00373881 49 DEC ECX
00373882 0BC9 OR ECX, ECX
00373884 ^ 75 A4 JNZ SHORT <Loop_Check_DBG>
;★★★★★★★★★★★★★★★★★★★★★★★★★★结束检测★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
00373886 83BD EA434000 0>CMP DWORD PTR SS:[EBP+<flg_Hook9xDump>], 1 ; 判断是否选择了Hook_Win9x_DUMP
0037388D 0F85 60010000 JNZ <no_Hook_DUMP>
00373893 8CC9 MOV CX, CS
00373895 32C9 XOR CL, CL
00373897 0BC9 OR ECX, ECX ; 检测OS版本
00373899 0F84 A4000000 JE <isWinNT> ; 如果是WinNT则跳
0037389F 6A 40 PUSH 40 ; 这里一段不明代码:-(
003738A1 68 00100008 PUSH 8001000 ; 因为我没有Win9x,所以这里没有办法测试:-(
003738A6 68 81000000 PUSH 81
003738AB 6A 00 PUSH 0
003738AD FF95 AE434000 CALL DWORD PTR SS:[EBP+<APIVirtualAlloc>] ; kernel32.VirtualAlloc
003738B3 8985 F9494000 MOV DWORD PTR SS:[EBP+4049F9], EAX
003738B9 8BF8 MOV EDI, EAX
003738BB 8DB5 8E224000 LEA ESI, DWORD PTR SS:[EBP+40228E]
003738C1 B9 81000000 MOV ECX, 81
003738C6 F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
003738C8 8BD8 MOV EBX, EAX
003738CA 55 PUSH EBP
003738CB 8F83 79000000 POP DWORD PTR DS:[EBX+79] ; 0012FFE0
003738D1 FFB5 D6444000 PUSH DWORD PTR SS:[EBP+4044D6] ; kernel32.ExitProcess
003738D7 8F83 7D000000 POP DWORD PTR DS:[EBX+7D] ; 0012FFE0
003738DD 8B85 46464000 MOV EAX, DWORD PTR SS:[EBP+404646] ; kernel32.ReadProcessMemory
003738E3 83C0 05 ADD EAX, 5
003738E6 8983 6B000000 MOV DWORD PTR DS:[EBX+6B], EAX
003738EC 8DBB 65000000 LEA EDI, DWORD PTR DS:[EBX+65]
003738F2 8BB5 46464000 MOV ESI, DWORD PTR SS:[EBP+404646] ; kernel32.ReadProcessMemory
003738F8 803E E9 CMP BYTE PTR DS:[ESI], 0E9
003738FB 74 09 JE SHORT 00373906
003738FD B9 05000000 MOV ECX, 5
00373902 F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
00373904 EB 0D JMP SHORT 00373913
00373906 8B46 01 MOV EAX, DWORD PTR DS:[ESI+1]
00373909 03C6 ADD EAX, ESI
0037390B 2BC7 SUB EAX, EDI
0037390D 8947 01 MOV DWORD PTR DS:[EDI+1], EAX
00373910 C607 E9 MOV BYTE PTR DS:[EDI], 0E9
00373913 50 PUSH EAX
00373914 0F014C24 FE SIDT FWORD PTR SS:[ESP-2]
00373919 5F POP EDI ; 0012FFE0
0037391A 83C7 20 ADD EDI, 20
0037391D 8B4F 04 MOV ECX, DWORD PTR DS:[EDI+4]
00373920 66:8B0F MOV CX, WORD PTR DS:[EDI]
00373923 FA CLI
00373924 8DB5 64224000 LEA ESI, DWORD PTR SS:[EBP+402264]
0037392A 66:8937 MOV WORD PTR DS:[EDI], SI
0037392D C1EE 10 SHR ESI, 10
00373930 66:8977 06 MOV WORD PTR DS:[EDI+6], SI
00373934 FB STI
00373935 CD 04 INT 4
00373937 FA CLI
00373938 66:890F MOV WORD PTR DS:[EDI], CX
0037393B C1E9 10 SHR ECX, 10
0037393E 66:894F 06 MOV WORD PTR DS:[EDI+6], CX
00373942 FB STI
00373943 > E9 AB000000 JMP <no_Hook_DUMP> ; isWinNT
00373948 60 PUSHAD
00373949 E8 00000000 CALL 0037394E
0037394E 5D POP EBP ; 0012FFE0
0037394F 81ED 6A224000 SUB EBP, 40226A
00373955 8B85 F9494000 MOV EAX, DWORD PTR SS:[EBP+4049F9]
0037395B 2B85 46464000 SUB EAX, DWORD PTR SS:[EBP+404646] ; kernel32.ReadProcessMemory
00373961 83E8 05 SUB EAX, 5
00373964 8B8D 46464000 MOV ECX, DWORD PTR SS:[EBP+404646] ; kernel32.ReadProcessMemory
0037396A C601 E9 MOV BYTE PTR DS:[ECX], 0E9
0037396D 8941 01 MOV DWORD PTR DS:[ECX+1], EAX
00373970 61 POPAD
00373971 CF IRETD
00373972 9C PUSHFD
00373973 60 PUSHAD
00373974 E8 00000000 CALL 00373979
00373979 5D POP EBP ; 0012FFE0
0037397A 81ED 95224000 SUB EBP, 402295
00373980 8B7424 28 MOV ESI, DWORD PTR SS:[ESP+28] ; kernel32.7C816D4F
00373984 8D85 03234000 LEA EAX, DWORD PTR SS:[EBP+402303]
0037398A 50 PUSH EAX
0037398B 6A 04 PUSH 4
0037398D 8D85 FF224000 LEA EAX, DWORD PTR SS:[EBP+4022FF]
00373993 50 PUSH EAX
00373994 B8 57484000 MOV EAX, 404857
00373999 0385 07234000 ADD EAX, DWORD PTR SS:[EBP+402307]
0037399F 50 PUSH EAX
003739A0 56 PUSH ESI
003739A1 E8 31000000 CALL 003739D7
003739A6 0BC0 OR EAX, EAX
003739A8 74 2B JE SHORT 003739D5
003739AA B8 2635B204 MOV EAX, 4B23526
003739AF 3985 FF224000 CMP DWORD PTR SS:[EBP+4022FF], EAX
003739B5 75 1E JNZ SHORT 003739D5
003739B7 8B7C24 30 MOV EDI, DWORD PTR SS:[ESP+30]
003739BB 8B4C24 34 MOV ECX, DWORD PTR SS:[ESP+34]
003739BF 33C0 XOR EAX, EAX
003739C1 F3:AA REP STOS BYTE PTR ES:[EDI]
003739C3 8B4424 34 MOV EAX, DWORD PTR SS:[ESP+34]
003739C7 8B4C24 38 MOV ECX, DWORD PTR SS:[ESP+38]
003739CB 8901 MOV DWORD PTR DS:[ECX], EAX
003739CD 61 POPAD
003739CE 9D POPFD
003739CF 33C0 XOR EAX, EAX
003739D1 40 INC EAX
003739D2 C2 1400 RETN 14
003739D5 61 POPAD
003739D6 9D POPFD
003739D7 55 PUSH EBP
003739D8 8BEC MOV EBP, ESP
003739DA 56 PUSH ESI
003739DB 57 PUSH EDI
003739DC B8 00000000 MOV EAX, 0
003739E1 FFE0 JMP EAX
003739E3 0000 ADD BYTE PTR DS:[EAX], AL
003739E5 0000 ADD BYTE PTR DS:[EAX], AL
003739E7 0000 ADD BYTE PTR DS:[EAX], AL
003739E9 0000 ADD BYTE PTR DS:[EAX], AL
003739EB 0000 ADD BYTE PTR DS:[EAX], AL
003739ED 0000 ADD BYTE PTR DS:[EAX], AL
003739EF 0000 ADD BYTE PTR DS:[EAX], AL
003739F1 0000 ADD BYTE PTR DS:[EAX], AL
跳过上面一段对WIN9X_hook_anti_dump的处理后来到这里,准备对文件进行解密操作.
003739F3 > 8D1D 65494000 LEA EBX, DWORD PTR DS:[404965] ; no_Hook_DUMP
003739F9 > 833C2B 00 CMP DWORD PTR DS:[EBX+EBP], 0 ; Loop_De_Code
003739FD 0F84 7B010000 JE <Unpacked_Section_DONE> ; 判断节的大小是否为0,是否解压完相关的段
00373A03 8D042B LEA EAX, DWORD PTR DS:[EBX+EBP]
00373A06 8B48 08 MOV ECX, DWORD PTR DS:[EAX+8]
00373A09 8B70 04 MOV ESI, DWORD PTR DS:[EAX+4]
00373A0C 03B5 B2434000 ADD ESI, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373A12 8BFE MOV EDI, ESI
00373A14 BA 2635B204 MOV EDX, 4B23526
00373A19 EB 1F JMP SHORT 00373A3A
00373A1B AC LODS BYTE PTR DS:[ESI] ; 比较简单的第一次解压出代码
00373A1C D2C8 ROR AL, CL
00373A1E 32C1 XOR AL, CL
00373A20 04 66 ADD AL, 66
00373A22 32C5 XOR AL, CH
00373A24 02C6 ADD AL, DH
00373A26 2AC2 SUB AL, DL
00373A28 02C1 ADD AL, CL
00373A2A 2AC5 SUB AL, CH
00373A2C 32C2 XOR AL, DL
00373A2E 04 23 ADD AL, 23
00373A30 32C6 XOR AL, DH
00373A32 F6D0 NOT AL
00373A34 D2C8 ROR AL, CL
00373A36 D3CA ROR EDX, CL
00373A38 AA STOS BYTE PTR ES:[EDI]
00373A39 49 DEC ECX
00373A3A 0BC9 OR ECX, ECX
00373A3C ^ 75 DD JNZ SHORT 00373A1B
00373A3E 53 PUSH EBX
00373A3F 6A 04 PUSH 4
00373A41 68 00100000 PUSH 1000
00373A46 FF342B PUSH DWORD PTR DS:[EBX+EBP]
00373A49 6A 00 PUSH 0
00373A4B 8D85 42244000 LEA EAX, DWORD PTR SS:[EBP+402442]
00373A51 50 PUSH EAX
00373A52 8B85 AE434000 MOV EAX, DWORD PTR SS:[EBP+<APIVirtualAlloc>] ; kernel32.VirtualAlloc
00373A58 E9 7D0F0000 JMP <proc_Run_FUN>
00373A5D 90 NOP
这里有有一个远的返回地址了,不再向前面的那样返回地址就在3行代码之内.
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆跳去OEP的代码☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
我是直接按壳的代码一直COPY,然后再做标记的,那样对全面分析可能会更好看些吧,当然这样看了也就会有点乱,
00373A5E 8B85 0E444000 MOV EAX, DWORD PTR SS:[EBP+<OEP(RVA)>] ; 处理完输入表和加密块后经过8个异常后来到这里
00373A64 0385 B2434000 ADD EAX, DWORD PTR SS:[EBP+<IMGBASE>] ; 准备跳去oep的处理
00373A6A 90 NOP
......
00373A71 894424 EC MOV DWORD PTR SS:[ESP-14], EAX
00373A75 90 NOP
00373A76 90 NOP
00373A77 90 NOP
00373A78 90 NOP
00373A79 90 NOP
00373A7A 90 NOP
00373A7B 90 NOP
00373A7C 90 NOP
00373A7D 90 NOP
00373A7E 90 NOP
00373A7F 90 NOP
00373A80 896C24 E8 MOV DWORD PTR SS:[ESP-18], EBP
00373A84 90 NOP
00373A85 90 NOP
00373A86 90 NOP
00373A87 90 NOP
00373A88 FF85 C2434000 INC DWORD PTR SS:[EBP+4043C2]
00373A8E 90 NOP
00373A8F 90 NOP
00373A90 90 NOP
00373A91 90 NOP
00373A92 90 NOP
00373A93 90 NOP
00373A94 90 NOP
00373A95 90 NOP
00373A96 90 NOP
00373A97 90 NOP
00373A98 90 NOP
00373A99 8B9D EE434000 MOV EBX, DWORD PTR SS:[EBP+4043EE]
00373A9F 90 NOP
00373AA0 90 NOP
00373AA1 90 NOP
00373AA2 90 NOP
00373AA3 90 NOP
00373AA4 83FB 01 CMP EBX, 1 ; EBX=1表示是push ebp, mov ebp,esp的方式
00373AA7 75 33 JNZ SHORT <isVBOEP_MODE?>
00373AA9 61 POPAD ; is Push ebp mode
00373AAA 90 NOP
00373AAB 90 NOP
00373AAC 90 NOP
00373AAD 90 NOP
00373AAE 90 NOP
00373AAF 8B4424 CC MOV EAX, DWORD PTR SS:[ESP-34]
00373AB3 90 NOP
00373AB4 90 NOP
00373AB5 90 NOP
00373AB6 90 NOP
00373AB7 90 NOP
00373AB8 90 NOP
00373AB9 90 NOP
00373ABA 90 NOP
00373ABB 90 NOP
00373ABC 90 NOP
00373ABD 90 NOP
00373ABE 8D78 02 LEA EDI, DWORD PTR DS:[EAX+2]
00373AC1 90 NOP
00373AC2 90 NOP
00373AC3 90 NOP
00373AC4 90 NOP
00373AC5 90 NOP
00373AC6 55 PUSH EBP
00373AC7 90 NOP
00373AC8 90 NOP
00373AC9 90 NOP
00373ACA 90 NOP
00373ACB 90 NOP
00373ACC 8BEC MOV EBP, ESP
00373ACE 90 NOP
00373ACF 90 NOP
00373AD0 90 NOP
00373AD1 90 NOP
00373AD2 90 NOP
00373AD3 90 NOP
00373AD4 90 NOP
00373AD5 90 NOP
00373AD6 90 NOP
00373AD7 90 NOP
00373AD8 90 NOP
00373AD9 50 PUSH EAX
00373ADA EB 45 JMP SHORT 00373B21
00373ADC > 83FB 02 CMP EBX, 2 ; isVBOEP_MODE?
00373ADF 75 2E JNZ SHORT 00373B0F ; EBX==2表示是VB的程序 push address
00373AE1 61 POPAD
00373AE2 90 NOP
00373AE3 90 NOP
00373AE4 90 NOP
00373AE5 90 NOP
00373AE6 90 NOP
00373AE7 90 NOP
00373AE8 90 NOP
00373AE9 8B4424 C8 MOV EAX, DWORD PTR SS:[ESP-38]
00373AED 90 NOP
00373AEE 90 NOP
00373AEF 90 NOP
00373AF0 90 NOP
00373AF1 FFB0 F2434000 PUSH DWORD PTR DS:[EAX+4043F2]
00373AF7 90 NOP
00373AF8 90 NOP
00373AF9 90 NOP
00373AFA 90 NOP
00373AFB 90 NOP
00373AFC 8B4424 D0 MOV EAX, DWORD PTR SS:[ESP-30] ; ntdll.7C930551
00373B00 90 NOP
00373B01 90 NOP
00373B02 90 NOP
00373B03 90 NOP
00373B04 90 NOP
00373B05 50 PUSH EAX
00373B06 90 NOP
00373B07 90 NOP
00373B08 90 NOP
00373B09 90 NOP
00373B0A 8D78 02 LEA EDI, DWORD PTR DS:[EAX+2]
00373B0D EB 12 JMP SHORT 00373B21
00373B0F 61 POPAD ; 如果不是push ebp mov ebp,esp的方式
00373B10 90 NOP ; 也不是push address call address的方式则直接跳去oep
00373B11 90 NOP
00373B12 90 NOP
00373B13 90 NOP
00373B14 90 NOP
00373B15 90 NOP
00373B16 90 NOP
00373B17 8B4424 CC MOV EAX, DWORD PTR SS:[ESP-34]
00373B1B 90 NOP
00373B1C 90 NOP
00373B1D 90 NOP
00373B1E 90 NOP
00373B1F 90 NOP
00373B20 50 PUSH EAX
00373B21 90 NOP
00373B22 90 NOP
00373B23 90 NOP
00373B24 90 NOP
00373B25 C3 RETN ; 返回到程序OEP
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆跳去OEP代码结束☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
上面申请空间后直接返回到这里,继续分析下去:
00373B26 5B POP EBX ; 0012FFE0
00373B27 8BF0 MOV ESI, EAX
00373B29 8BC3 MOV EAX, EBX
00373B2B 03C5 ADD EAX, EBP
00373B2D 8B78 04 MOV EDI, DWORD PTR DS:[EAX+4]
00373B30 03BD B2434000 ADD EDI, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373B36 56 PUSH ESI
00373B37 57 PUSH EDI
00373B38 8D85 64244000 LEA EAX, DWORD PTR SS:[EBP+402464]
00373B3E 50 PUSH EAX
00373B3F 8B85 12444000 MOV EAX, DWORD PTR SS:[EBP+404412] ; <aplib_Unpack>
00373B45 FFE0 JMP EAX ; 跳去aplib解压代码
00373B48 8B0C2B MOV ECX, DWORD PTR DS:[EBX+EBP] ; 解压大小59000
00373B4B 56 PUSH ESI
00373B4C 51 PUSH ECX
00373B4D C1E9 02 SHR ECX, 2
00373B50 F3:A5 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI] ; 解压代码到相关位置
00373B52 59 POP ECX ; 0012FFE0
00373B53 83E1 03 AND ECX, 3
00373B56 F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
00373B58 5E POP ESI ; 0012FFE0
00373B59 53 PUSH EBX
00373B5A 68 00800000 PUSH 8000
00373B5F 6A 00 PUSH 0
00373B61 56 PUSH ESI
00373B62 8D85 91244000 LEA EAX, DWORD PTR SS:[EBP+402491]
00373B68 50 PUSH EAX
00373B69 8B85 AF444000 MOV EAX, DWORD PTR SS:[EBP+<APIVirtualFree>] ; kernel32.VirtualFree
00373B6F E9 660E0000 JMP <proc_Run_FUN>
00373B74 90 NOP
00373B75 5B POP EBX ; 0012FFE0
00373B76 83C3 0C ADD EBX, 0C
00373B79 ^ E9 7BFEFFFF JMP <Loop_De_Code> ; 循环解压出相关代码
;══════════════════════还原CALL和相关跳转═════════════════════════
00373B7E > 8BB5 DD484000 MOV ESI, DWORD PTR SS:[EBP+4048DD] ; Unpacked_Section_DONE
00373B84 03B5 B2434000 ADD ESI, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373B8A 8B8D E1484000 MOV ECX, DWORD PTR SS:[EBP+4048E1]
00373B90 83E9 05 SUB ECX, 5
00373B93 EB 5B JMP SHORT 00373BF0
00373B95 > 66:8B06 MOV AX, WORD PTR DS:[ESI] ; De_JMP_CALL
00373B98 3C E8 CMP AL, 0E8 ; jmp address
00373B9A 75 16 JNZ SHORT 00373BB2 ; 和远程跳转
00373B9C 8BC6 MOV EAX, ESI
00373B9E 2B85 B2434000 SUB EAX, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373BA4 83C0 05 ADD EAX, 5
00373BA7 2946 01 SUB DWORD PTR DS:[ESI+1], EAX
00373BAA 83C6 04 ADD ESI, 4
00373BAD 83E9 04 SUB ECX, 4
00373BB0 EB 3C JMP SHORT 00373BEE
00373BB2 3C E9 CMP AL, 0E9
00373BB4 75 16 JNZ SHORT 00373BCC
00373BB6 8BC6 MOV EAX, ESI
00373BB8 2B85 B2434000 SUB EAX, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373BBE 83C0 05 ADD EAX, 5
00373BC1 2946 01 SUB DWORD PTR DS:[ESI+1], EAX
00373BC4 83C6 04 ADD ESI, 4
00373BC7 83E9 04 SUB ECX, 4
00373BCA EB 22 JMP SHORT 00373BEE
00373BCC 3C 0F CMP AL, 0F
00373BCE 75 1E JNZ SHORT 00373BEE
00373BD0 80FC 7F CMP AH, 7F
00373BD3 76 19 JBE SHORT 00373BEE
00373BD5 80FC 90 CMP AH, 90
00373BD8 73 14 JNB SHORT 00373BEE
00373BDA 8BC6 MOV EAX, ESI
00373BDC 2B85 B2434000 SUB EAX, DWORD PTR SS:[EBP+<IMGBASE>] ; 00400000
00373BE2 83C0 06 ADD EAX, 6
00373BE5 2946 02 SUB DWORD PTR DS:[ESI+2], EAX
00373BE8 83C6 05 ADD ESI, 5
00373BEB 83E9 05 SUB ECX, 5
00373BEE 46 INC ESI
00373BEF 49 DEC ECX
00373BF0 81F9 00000080 CMP ECX, 80000000
00373BF6 ^ 72 9D JB SHORT <De_JMP_CALL>
;══════════════════════END══════════════════════