【标 题】菜鸟对13.8.2 ASPack外壳分析
【作 者】guhegu
【日 期】2008-11-119
【使用工具】OllyDBG
【平 台】WinXP sp2
【目标程序】加密与解密映像光盘13.8.2EdrLib.dll
【作者声明】只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
看书两个月了请教了很多大侠,终于有一点心得希望能跟大家分享
第一次写这样的文章 不足之处请指正
003ED001 > 60 pushad
003ED002 E8 03000000 call 003ED00A 没有003ED00A所以为花指令,F7进入
003ED007 - E9 EB045D45 jmp 459BD4F7
003ED00C 55 push ebp
003ED00D C3 retn
003ED00A 5D pop ebp ; EdrLib.003ED007
003ED00B 45 inc ebp
003ED00C 55 push ebp
003ED00D C3 retn
003ED00E E8 01000000 call 003ED014 F7进入
003ED014 5D pop ebp ; EdrLib.003ED013
003ED015 BB EDFFFFFF mov ebx, -13
003ED01A 03DD add ebx, ebp EBX值为3ED000
003ED01C 81EB 00D00000 sub ebx, 0D000 得到实际基址 3E0000
003ED022 83BD 22040000 0>cmp dword ptr [ebp+422], 0 改地址数据为0
003ED029 899D 22040000 mov dword ptr [ebp+422], ebx
003ED02F 0F85 65030000 jnz 003ED39A 这里不跳
003ED035 8D85 2E040000 lea eax, dword ptr [ebp+42E]
地址=003ED441, (ASCII "kernel32.dll")
003ED03B 50 push eax
003ED03C FF95 4D0F0000 call dword ptr [ebp+F4D]
调用ss:[003EDF60]=7C80B6A1 (kernel32.GetModuleHandleA) 取得kernel32.dll的句柄
003ED042 8985 26040000 mov dword ptr [ebp+426], eax
KERNEL32.DLL的句柄存入地址中去,方便下次调用
003ED048 8BF8 mov edi, eax
003ED04A 8D5D 5E lea ebx, dword ptr [ebp+5E]
地址=003ED071, (ASCII "VirtualAlloc") 为获得Virtualalloc函数地址做准备
003ED04D 53 push ebx 函数名进栈
003ED04E 50 push eax DLL文件句柄进栈
003ED04F FF95 490F0000 call dword ptr [ebp+F49]
调用ss:[003EDF5C]=7C80ADA0 (kernel32.GetProcAddress)获得函数地址
003ED055 8985 4D050000 mov dword ptr [ebp+54D], eax 存入该地址方便下次调用
003ED05B 8D5D 6B lea ebx, dword ptr [ebp+6B]
地址=003ED07E, (ASCII "VirtualFree")
003ED05E 53 push ebx 函数名地址进栈
003ED05F 57 push edi DLL文件句柄进栈
003ED060 FF95 490F0000 call dword ptr [ebp+F49]
调用ss:[003EDF5C]=7C80ADA0 (kernel32.GetProcAddress)获得函数地址
003ED066 8985 51050000 mov dword ptr [ebp+551], eax
函数地址存入内存中去,方便调用
003ED06C 8D45 77 lea eax, dword ptr [ebp+77]
调用ss:[003EDF5C]=7C80ADA0 (kernel32.GetProcAddress)获得函数地址
地址=003ED08A
003ED06F FFE0 jmp eax == jmp 003ed08A
003ED08A 8B9D 31050000 mov ebx, dword ptr [ebp+531] ebx=0
003ED090 0BDB or ebx, ebx
003ED092 74 0A je short 003ED09E 跳转实现
003ED094 8B03 mov eax, dword ptr [ebx]
003ED096 8785 35050000 xchg dword ptr [ebp+535], eax
003ED09C 8903 mov dword ptr [ebx], eax
003ED09E 8DB5 69050000 lea esi, dword ptr [ebp+569]
ESI=003ED57C
003ED0A4 833E 00 cmp dword ptr [esi], 0
DS:[003ED57C]=1000
003ED0A7 0F84 21010000 je 003ED1CE 不跳
003ED0AD 6A 04 push 4
003ED0AF 68 00100000 push 1000
003ED0B4 68 00180000 push 1800
003ED0B9 6A 00 push 0
003ED0BB FF95 4D050000 call dword ptr [ebp+54D]前面保存了的VIRTUALALLOC 函数的地址 意思是分配一个大小为1000的空间
003ED0C1 8985 56010000 mov dword ptr [ebp+156], eax
EAX为函数返回的值即系统分配的基址 我这里为3F0000 每台机器应该不一样
003ED0C7 8B46 04 mov eax, dword ptr [esi+4] EAX=6000
003ED0CA 05 0E010000 add eax, 10E EAX=610E
003ED0CF 6A 04 push 4
003ED0D1 68 00100000 push 1000
003ED0D6 50 push eax
003ED0D7 6A 00 push 0
003ED0D9 FF95 4D050000 call dword ptr [ebp+54D]
继续分配一个空间
003ED0DF 8985 52010000 mov dword ptr [ebp+152], eax
EAX=870000
003ED0E5 56 push esi
003ED0E6 8B1E mov ebx, dword ptr [esi] EBX=1000
003ED0E8 039D 22040000 add ebx, dword ptr [ebp+422]
1000+3E0000(上面一段语句保存的基址)3E1000
003ED0EE FFB5 56010000 push dword ptr [ebp+156]
003ED0F4 FF76 04 push dword ptr [esi+4] 6000
003ED0F7 50 push eax 870000
003ED0F8 53 push ebx 3E1000
003ED0F9 E8 6E050000 call 003ED66C 解压代码到3F0000中去
003ED0FE B3 00 mov bl, 0
003ED100 80FB 00 cmp bl, 0
003ED103 75 5E jnz short 003ED163 不跳
003ED105 FE85 EC000000 inc byte ptr [ebp+EC]
003ED10B 8B3E mov edi, dword ptr [esi] EDI=1000
003ED10D 03BD 22040000 add edi, dword ptr [ebp+422] EDI=3E1000
003ED113 FF37 push dword ptr [edi] AA424320进栈
003ED115 C607 C3 mov byte ptr [edi], 0C3
003ED118 FFD7 call edi 垃圾调用
003ED11A 8F07 pop dword ptr [edi] 实际就是把AA424320写到3E1000处
003ED11C 50 push eax
003ED11D 51 push ecx
003ED11E 56 push esi
003ED11F 53 push ebx
003ED120 8BC8 mov ecx, eax
003ED122 83E9 06 sub ecx, 6
003ED125 8BB5 52010000 mov esi, dword ptr [ebp+152] ESI=870000
003ED12B 33DB xor ebx, ebx EBX清0
003ED12D 0BC9 or ecx, ecx
003ED12F 74 2E je short 003ED15F
003ED131 78 2C js short 003ED15F 两个都不跳
003ED133 AC lods byte ptr [esi] 0B8送到AL中去 SI++
003ED134 3C E8 cmp al, 0E8
003ED136 74 0A je short 003ED142
003ED138 EB 00 jmp short 003ED13A
003ED13A 3C E9 cmp al, 0E9
003ED13C 74 04 je short 003ED142
003ED13E 43 inc ebx
003ED13F 49 dec ecx
003ED140 ^ EB EB jmp short 003ED12D
003ED142 8B06 mov eax, dword ptr [esi]
003ED144 EB 00 jmp short 003ED146
003ED146 803E 01 cmp byte ptr [esi], 1
003ED149 ^ 75 F3 jnz short 003ED13E
003ED14B 24 00 and al, 0
003ED14D C1C0 18 rol eax, 18
003ED150 2BC3 sub eax, ebx
003ED152 8906 mov dword ptr [esi], eax
003ED154 83C3 05 add ebx, 5
003ED157 83C6 04 add esi, 4
003ED15A 83E9 05 sub ecx, 5
003ED15D ^ EB CE jmp short 003ED12D
003ED12D 到这里都是在解码 放到870000中去
003ED15F 5B pop ebx
003ED160 5E pop esi
003ED161 59 pop ecx
003ED162 58 pop eax
003ED163 EB 08 jmp short 003ED16D
003ED16D 8BC8 mov ecx, eax
003ED16F 8B3E mov edi, dword ptr [esi]
003ED171 03BD 22040000 add edi, dword ptr [ebp+422] EDI=3E1000
003ED177 8BB5 52010000 mov esi, dword ptr [ebp+152] ESI=870000
003ED17D C1F9 02 sar ecx, 2
003ED180 F3:A5 rep movs dword ptr es:[edi], dword p>
解码ING
003ED182 8BC8 mov ecx, eax
003ED184 83E1 03 and ecx, 3
003ED187 F3:A4 rep movs byte ptr es:[edi], byte ptr>
003ED189 5E pop esi
003ED18A 68 00800000 push 8000
003ED18F 6A 00 push 0
003ED191 FFB5 52010000 push dword ptr [ebp+152] 870000
003ED197 FF95 51050000 call dword ptr [ebp+551]
Virtualfree释放870000的空间
003ED19D 83C6 08 add esi, 8
003ED1A0 833E 00 cmp dword ptr [esi], 0
003ED1A3 ^ 0F85 1EFFFFFF jnz 003ED0C7 整个大循环就是在解码
003ED1A9 68 00800000 push 8000
003ED1AE 6A 00 push 0
003ED1B0 FFB5 56010000 push dword ptr [ebp+156]
003ED1B6 FF95 51050000 call dword ptr [ebp+551]
释放370000的空间
003ED1BC 8B9D 31050000 mov ebx, dword ptr [ebp+531]
003ED1C2 0BDB or ebx, ebx
003ED1C4 74 08 je short 003ED1CE 跳
003ED1C6 8B03 mov eax, dword ptr [ebx]
003ED1C8 8785 35050000 xchg dword ptr [ebp+535], eax
接下来就是开始重定位了
003ED1CE 8B95 22040000 mov edx, dword ptr [ebp+422] 实际基址
003ED1D4 8B85 2D050000 mov eax, dword ptr [ebp+52D] 默认基址
003ED1DA 2BD0 sub edx, eax 实际基址-默认基址不等于0所以要进行重定位 差值保存到EDX
003ED1DC 74 79 je short 003ED257
003ED1DE 8BC2 mov eax, edx EDX差值放到EAX
003ED1E0 C1E8 10 shr eax, 10 右移10位
003ED1E3 33DB xor ebx, ebx ebx 清0
003ED1E5 8BB5 39050000 mov esi, dword ptr [ebp+539] 取重定位表RVA这里是C000
003ED1EB 03B5 22040000 add esi, dword ptr [ebp+422] 得到实际重定位表地址
003ED1F1 833E 00 cmp dword ptr [esi], 0
003ED1F4 74 61 je short 003ED257 不跳
下面两个嵌套循环完成重定位
003ED1F6 8B4E 04 mov ecx, dword ptr [esi+4] 重定位表指向下一位(重定位单元的大小)
003ED1F9 83E9 08 sub ecx, 8
003ED1FC D1E9 shr ecx, 1 ECX=8A
003ED1FE 8B3E mov edi, dword ptr [esi]
003ED200 03BD 22040000 add edi, dword ptr [ebp+422] edi=3e1000
003ED206 83C6 08 add esi, 8 源操作数+8
003ED209 66:8B1E mov bx, word ptr [esi] BX=301D
003ED20C C1EB 0C shr ebx, 0C EBX=3 这里应该是用EBX分类
003ED20F 83FB 01 cmp ebx, 1
003ED212 74 0C je short 003ED220
003ED214 83FB 02 cmp ebx, 2
003ED217 74 16 je short 003ED22F
003ED219 83FB 03 cmp ebx, 3
003ED21C 74 20 je short 003ED23E 跳转实现
003ED21E EB 2C jmp short 003ED24C
003ED220 66:8B1E mov bx, word ptr [esi]
003ED223 81E3 FF0F0000 and ebx, 0FFF
003ED229 66:01041F add word ptr [edi+ebx], ax
003ED22D EB 1D jmp short 003ED24C
003ED22F 66:8B1E mov bx, word ptr [esi]
003ED232 81E3 FF0F0000 and ebx, 0FFF
003ED238 66:01141F add word ptr [edi+ebx], dx
003ED23C EB 0E jmp short 003ED24C
003ED23E 66:8B1E mov bx, word ptr [esi]
003ED241 81E3 FF0F0000 and ebx, 0FFF EBX=1D
003ED247 01141F add dword ptr [edi+ebx], edx
这里就是重定位了EDX保存的差值
003ED24A EB 00 jmp short 003ED24C
003ED24C 66:830E FF or word ptr [esi], 0FFFF
003ED250 83C6 02 add esi, 2 指向下一个
003ED253 ^ E2 B4 loopd short 003ED209
003ED255 ^ EB 9A jmp short 003ED1F1
开始处理输入表
003ED257 8B95 22040000 mov edx, dword ptr [ebp+422]实际基址
003ED25D 8BB5 41050000 mov esi, dword ptr [ebp+541]
003ED263 0BF6 or esi, esi
003ED265 74 11 je short 003ED278 跳转实现
003ED267 03F2 add esi, edx
003ED269 AD lods dword ptr [esi]
003ED26A 0BC0 or eax, eax
003ED26C 74 0A je short 003ED278
003ED26E 03C2 add eax, edx
003ED270 8BF8 mov edi, eax
003ED272 66:AD lods word ptr [esi]
003ED274 66:AB stos word ptr es:[edi]
003ED276 ^ EB F1 jmp short 003ED269
003ED278 BE 94760000 mov esi, 7694 输入表RVA
003ED27D 8B95 22040000 mov edx, dword ptr [ebp+422]
003ED283 03F2 add esi, edx 得到实际的输入表地址
003ED285 8B46 0C mov eax, dword ptr [esi+C] IID的RVA
003ED288 85C0 test eax, eax
003ED28A 0F84 0A010000 je 003ED39A 不跳转
003ED290 03C2 add eax, edx 得到实际IID地址
003ED292 8BD8 mov ebx, eax
003ED294 50 push eax
003ED295 FF95 4D0F0000 call dword ptr [ebp+F4D]
调用ss:[003EDF60]=7C80B6A1 (kernel32.GetModuleHandleA)得到KERNEL32.DLL句柄
003ED29B 85C0 test eax, eax
003ED29D 75 07 jnz short 003ED2A6 跳转实现
003ED29F 53 push ebx
003ED2A0 FF95 510F0000 call dword ptr [ebp+F51]
003ED2A6 8985 45050000 mov dword ptr [ebp+545], eax 句柄存入
003ED2AC C785 49050000 0>mov dword ptr [ebp+549], 0 加个0表示结尾
003ED2B6 8B95 22040000 mov edx, dword ptr [ebp+422]
003ED2BC 8B06 mov eax, dword ptr [esi] 第一个IID的RVA
003ED2BE 85C0 test eax, eax
003ED2C0 75 03 jnz short 003ED2C5 跳
003ED2C2 8B46 10 mov eax, dword ptr [esi+10] 下一个IID 76E4
003ED2C5 03C2 add eax, edx
003ED2C7 0385 49050000 add eax, dword ptr [ebp+549]
003ED2CD 8B18 mov ebx, dword ptr [eax] 7B66
003ED2CF 8B7E 10 mov edi, dword ptr [esi+10] 7014
003ED2D2 03FA add edi, edx
003ED2D4 03BD 49050000 add edi, dword ptr [ebp+549]
003ED2DA 85DB test ebx, ebx
003ED2DC 0F84 A2000000 je 003ED384
003ED2E2 F7C3 00000080 test ebx, 80000000
003ED2E8 75 04 jnz short 003ED2EE
003ED2EA 03DA add ebx, edx
003ED2EC 43 inc ebx
003ED2ED 43 inc ebx 找到第一个函数名地址
003ED2EE 53 push ebx
003ED2EF 81E3 FFFFFF7F and ebx, 7FFFFFFF
003ED2F5 53 push ebx
003ED2F6 FFB5 45050000 push dword ptr [ebp+545]
003ED2FC FF95 490F0000 call dword ptr [ebp+F49]
ss:[003EDF5C]=7C80ADA0 (kernel32.GetProcAddress) 得到 第一个函数的地址
003ED302 85C0 test eax, eax 函数地址
003ED304 5B pop ebx 函数名
003ED305 75 6F jnz short 003ED376 跳
003ED307 F7C3 00000080 test ebx, 80000000
003ED30D 75 19 jnz short 003ED328
003ED30F 57 push edi
003ED310 8B46 0C mov eax, dword ptr [esi+C]
003ED313 0385 22040000 add eax, dword ptr [ebp+422]
003ED319 50 push eax
003ED31A 53 push ebx
003ED31B 8D85 75040000 lea eax, dword ptr [ebp+475]
003ED321 50 push eax
003ED322 57 push edi
003ED323 E9 98000000 jmp 003ED3C0
003ED376 8907 mov dword ptr [edi], eax ; kernel32.GetStringTypeA 存入IAT
003ED378 8385 49050000 0>add dword ptr [ebp+549], 4 指向下一个函数名
003ED37F ^ E9 32FFFFFF jmp 003ED2B6 循环第一层
003ED384 8906 mov dword ptr [esi], eax 完成IID的填写
003ED386 8946 0C mov dword ptr [esi+C], eax 完成IID的填写
003ED389 8946 10 mov dword ptr [esi+10], eax完成IID的填写
003ED38C 83C6 14 add esi, 14 指向下一个IID
003ED38F 8B95 22040000 mov edx, dword ptr [ebp+422]
003ED395 ^ E9 EBFEFFFF jmp 003ED285
003ED39A B8 40120000 mov eax, 1240
003ED39F 50 push eax
003ED3A0 0385 22040000 add eax, dword ptr [ebp+422]
003ED3A6 59 pop ecx
003ED3A7 0BC9 or ecx, ecx
003ED3A9 8985 A8030000 mov dword ptr [ebp+3A8], eax
003ED3AF 61 popad
003ED3B0 75 08 jnz short 003ED3BA
003ED3B2 B8 01000000 mov eax, 1
003ED3B7 C2 0C00 retn 0C
003ED3BA 68 00000000 push 0
003ED3BF C3 retn 回到OEP
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!