[转载]Polycrypt PE2.1.5外壳分析
本帖最后由 smallyou93 于 2009-10-28 18:30 编辑作者:bugmans
博客:http://hi.baidu.com/bugmans
一、开始3段数据解密:
1.第一段
0040D00D > 60 pushad
0040D00E E8 EDFFFFFF call NotePad_.0040D000 //解密1
0040D013 - EB 80 jmp short NotePad_.0040CF95
0040D015 F5 cmc
0040D016 3E:F5 cmc
0040D018 A0 50F53891 mov al,byte ptr ds:
解密函数1:
0040D000 91 xchg eax,ecx
0040D001 8BF4 mov esi,esp
0040D003 AD lods dword ptr ds:
0040D004 FEC9 dec cl
0040D006 803408 93 xor byte ptr ds:,93
0040D00A ^ E2 FA loopd short NotePad_.0040D006
0040D00C C3 retn
解密函数很简单,就简单的XOR加密,密匙为0x93
2.第二段
0040D028 91 xchg eax,ecx
0040D029 9C pushfd
0040D02A 55 push ebp
0040D02B C141 02 00 rol dword ptr ds:,0
0040D02F C141 11 00 rol dword ptr ds:,0
0040D033 81E9 0F624000 sub ecx,NotePad_.0040620F
0040D039 51 push ecx
0040D03A 8BE9 mov ebp,ecx
0040D03C 8DB5 52624000 lea esi,dword ptr ss:
0040D042 8BFE mov edi,esi
0040D044 B9 11000000 mov ecx,11
0040D049 66:8B9D 636E4000 mov bx,word ptr ss:
0040D050 E8 C0FFFFFF call NotePad_.0040D015 //解密2
0040D055 90 nop
解密函数2:
0040D015 66:AD lods word ptr ds:
0040D017 66:33C3 xor ax,bx
0040D01A 66:AB stos word ptr es:
0040D01C 02DF add bl,bh
0040D01E 86DF xchg bh,bl
0040D020 66:D1CB ror bx,1
0040D023 66:43 inc bx
0040D025 ^ E2 EE loopd short NotePad_.0040D015
0040D027 C3 retn
解密函数也很简单,也是简单的XOR加密,但是密匙不是固定的,都是计算后再进行解密的
3.第三段
0040D055 90 nop
0040D056 8DBD 24624000 lea edi,dword ptr ss:
0040D05C 32C0 xor al,al
0040D05E B9 3B000000 mov ecx,3B
0040D063 F3:AA rep stos byte ptr es:
0040D065 8DB5 74624000 lea esi,dword ptr ss:
0040D06B 8BFE mov edi,esi
0040D06D B9 F7050000 mov ecx,5F7
0040D072 E8 9EFFFFFF call NotePad_.0040D015 //解密3
0040D077 90 nop
解密函数同解密函数2
3段解密后,外壳的代码已经全部解密了,下面开始真正的外壳段
二、SEH的大量应用,构造内存访问异常,以改变调试流程
这个壳大量的利用了SEH异常,后面还会看见大量的int3异常,使得程序在调试器里运行显得很卡
0040D078 8D85 90624000 lea eax,dword ptr ss:
0040D07E 50 push eax
0040D07F 8DBD AD664000 lea edi,dword ptr ss:
0040D085 57 push edi ; SEH Handler入栈,回调地址为0040D4B1
0040D086 64:8B11 mov edx,dword ptr fs:
0040D089 52 push edx
0040D08A 64:8921 mov dword ptr fs:,esp
0040D08D 8909 mov dword ptr ds:,ecx ; 由于ecx=0,故构造个内存访问异常
0040D08F E9 5B010000 jmp NotePad_.0040D1EF
0040D094 5D pop ebp ; 第一个SEH出口地址
0040D095 8DBD BC664000 lea edi,dword ptr ss:
0040D09B 57 push edi
0040D09C 33C0 xor eax,eax
0040D09E 64:FF30 push dword ptr fs: ; SEH Handler入栈,回调地址为0040D4C0
0040D0A1 64:8920 mov dword ptr fs:,esp
0040D0A4 8B10 mov edx,dword ptr ds: ; 再次构造内存访问异常
0040D0A6 33C0 xor eax,eax ; 第二个SEH的出口地址
看下第二个回调函数:
下面的异常都是这个地址做为异常的回调地址,然后在这个函数里,对不同的SEH进行不同的处理
0040D4C0 64:67:A1 3000 mov eax,dword ptr fs:
0040D4C5 0FB658 02 movzx ebx,byte ptr ds:
0040D4C9 0ADB or bl,bl
0040D4CB ^ 75 9D jnz short NotePad_.0040D46A
0040D4CD 8B45 10 mov eax,dword ptr ss:
0040D4D0 8B90 B8000000 mov edx,dword ptr ds: ; edx保存异常地址
0040D4D6 2B90 B4000000 sub edx,dword ptr ds:
0040D4DC 81FA A0624000 cmp edx,NotePad_.004062A0
0040D4E2 74 19 je short NotePad_.0040D4FD ; 对不同的异常,进行不同的处理
0040D4E4 81FA AA644000 cmp edx,NotePad_.004064AA
0040D4EA 74 21 je short NotePad_.0040D50D
0040D4EC 8B90 B8000000 mov edx,dword ptr ds:
0040D4F2 803A CC cmp byte ptr ds:,0CC
0040D4F5 74 3F je short NotePad_.0040D536 ; 判断异常处的指令是否为OxCC,也就是int3
0040D4F7 B8 01000000 mov eax,1
0040D4FC C3 retn
0040D4FD C780 B0000000 001040>mov dword ptr ds:,NotePad_.00401000
0040D507 B8 00000000 mov eax,0
0040D50C C3 retn
0040D50D 8BF8 mov edi,eax
0040D50F 8B9F A4000000 mov ebx,dword ptr ds:
0040D515 8B8F B0000000 mov ecx,dword ptr ds:
0040D51B 86CD xchg ch,cl
0040D51D 66:D1C9 ror cx,1
0040D520 66:2BCB sub cx,bx
0040D523 66:C1C1 02 rol cx,2
0040D527 66:33CB xor cx,bx
0040D52A 899F A4000000 mov dword ptr ds:,ebx
0040D530 898F B0000000 mov dword ptr ds:,ecx
0040D536 FF80 B8000000 inc dword ptr ds: ; 把出口地址改为EIP+1
0040D53C B8 00000000 mov eax,0
0040D541 C3 retn
三、获取外壳所要的API函数的地址
0040D0A8 64:8B40 30 mov eax,dword ptr fs:
0040D0AC 0FB658 02 movzx ebx,byte ptr ds:
0040D0B0 0ADB or bl,bl
0040D0B2 0F85 B2030000 jnz NotePad_.0040D46A
0040D0B8 8B40 0C mov eax,dword ptr ds:
0040D0BB 8B70 1C mov esi,dword ptr ds:
0040D0BE AD lods dword ptr ds:
0040D0BF 8B40 08 mov eax,dword ptr ds: ; kernel32.dll地址的基址的获取
0040D0C2 8985 256E4000 mov dword ptr ss:,eax ; kernel32.7C800000
0040D0C8 E8 E7080000 call NotePad_.0040D9B4 //获取地址函数
0040D0CD 64:67:A1 3000 mov eax,dword ptr fs:
0040D0D2 0FB658 02 movzx ebx,byte ptr ds:
0040D0D6 0ADB or bl,bl
0040D0D8 0F85 8C030000 jnz NotePad_.0040D46A
0040D0DE 6A 00 push 0
0040D0E0 FF95 D16B4000 call dword ptr ss:
获取壳所需要的API函数地址:
0040D9B4 8DB5 D16B4000 lea esi,dword ptr ss:
0040D9BA 8BFE mov edi,esi
0040D9BC AD lods dword ptr ds:
0040D9BD 83F8 00 cmp eax,0
0040D9C0 74 12 je short NotePad_.0040D9D4 ; 判断是否解密完毕,是则跳出
0040D9C2 03C5 add eax,ebp
0040D9C4 50 push eax ; eax中保存着所要获取地址的字符串信息
0040D9C5 FFB5 256E4000 push dword ptr ss:
0040D9CB FF95 C26E4000 call dword ptr ss: ; GetProcAddress
0040D9D1 AB stos dword ptr es:
0040D9D2 ^ EB E8 jmp short NotePad_.0040D9BC
0040D9D4 C3 retn
所获取的的函数如下:
0040D9D5 7C80B6A1 kernel32.GetModuleHandleA
0040D9D9 7C802442 kernel32.Sleep
0040D9DD 7C801D77 kernel32.LoadLibraryA
0040D9E1 7C801AD0 kernel32.VirtualProtect
0040D9E5 7C810637 kernel32.CreateThread
0040D9E9 7C80C058 kernel32.ExitThread
0040D9ED 7C81CDDA kernel32.ExitProcess
0040D9F1 7C801A24 kernel32.CreateFileA
0040D9F5 7C80B4CF kernel32.GetModuleFileNameA
0040D9F9 7C831EAB kernel32.DeleteFileA
0040D9FD 7C809B47 kernel32.CloseHandle
0040DA01 7C80180E kernel32.ReadFile
0040DA05 7C80BAA1 kernel32.lstrcmpiA
0040DA09 7C80FD2D kernel32.GlobalAlloc
0040DA0D 7C80FC2F kernel32.GlobalFree
0040DA11 7C8286EE kernel32.CopyFileA
0040DA15 7C810A77 kernel32.GetFileSize
0040DA19 7C810D87 kernel32.WriteFile
0040DA1D 7C80929C kernel32.GetTickCount
0040DA21 7C821982 kernel32.OpenFile
0040DA25 7C810B8E kernel32.SetFilePointer
四、虚拟机检测
0040D0E6 8985 696E4000 mov dword ptr ss:,eax ; NotePad_.00400000
0040D0EC 8D85 CC6E4000 lea eax,dword ptr ss:
0040D0F2 0F0108 sidt fword ptr ds: ; 获取idt的特征值,用来判断是否在虚拟机环境
0040D0F5 81BD CE6E4000 000000>cmp dword ptr ss:,D0000000
0040D0FF 7C 20 jl short NotePad_.0040D121
0040D101 81BD CE6E4000 000000>cmp dword ptr ss:,F0000000
0040D10B 0F8E 59030000 jle NotePad_.0040D46A ; 检测到在虚拟机,则做关机处理
0040D111 81BD CE6E4000 000000>cmp dword ptr ss:,FF000000
0040D11B 0F8F 49030000 jg NotePad_.0040D46A ; 检测到在虚拟机,则做关机处理
0040D121 8DBD 5F624000 lea edi,dword ptr ss:
看下0040D46A:
0040D46A E8 0B000000 call NotePad_.0040D47A //变形CALL,F7进
0040D46F 55 push ebp
0040D470 53 push ebx
0040D471 45 inc ebp
0040D472 52 push edx
0040D473 3332 xor esi,dword ptr ds:
0040D475 2E:44 inc esp
0040D477 4C dec esp
0040D47A FF95 D96B4000 call dword ptr ss: ; hUDll=eax=LoadLibraryA("USER32.dll")
0040D480 E8 0E000000 call NotePad_.0040D493 ; 继续变形CALL,F7
0040D485 45 inc ebp
0040D486 78 69 js short NotePad_.0040D4F1
0040D488 74 57 je short NotePad_.0040D4E1
0040D48A 696E 64 6F777345 imul ebp,dword ptr ds:,4573776F
0040D491 78 00 js short NotePad_.0040D493
0040D493 50 push eax ; user32.77D10000
0040D494 FF95 C26E4000 call dword ptr ss: ; eax=GetProcAddress(hUDll,"ExitWindowsEx")
0040D49A 8985 A9664000 mov dword ptr ss:,eax
0040D4A0 6A 04 push 4
0040D4A2 FF95 A9664000 call dword ptr ss: ; 执行ExitWindowsEx,关机
0040D4A8 E9 23080000 jmp NotePad_.0040DCD0
0040D4AD 45 inc ebp
五、破坏PE头,使之无法正常的dump,anti-dump
0040D142 8B9D 696E4000 mov ebx,dword ptr ss:
0040D148 8D8D 296E4000 lea ecx,dword ptr ss:
0040D14E 51 push ecx
0040D14F 6A 40 push 40
0040D151 6A 01 push 1
0040D153 53 push ebx
0040D154 FF95 DD6B4000 call dword ptr ss: ; 修改PE头的属性为可读写,为下面的破坏PE头行为做准备
0040D15A 8B95 3F6E4000 mov edx,dword ptr ss:
0040D160 03D3 add edx,ebx
0040D162 66:C742 06 FFFF mov word ptr ds:,0FFFF ; 1,修改取段数,NOP
0040D168 C742 20 00000000 mov dword ptr ds:,0 ; 2,修改SizeOfInitializeData数,NOP
0040D16F C742 28 00000000 mov dword ptr ds:,0 ; 3,修改AddressOfEntryPoint,NOP
0040D176 C742 2C FFFFFF0F mov dword ptr ds:,0FFFFFFF ; 4,BaseOfCode,NOP
0040D17D C742 34 FFFFFF0F mov dword ptr ds:,0FFFFFFF ; 5,ImageBase,NOP
0040D184 039D 376E4000 add ebx,dword ptr ss: ; 定位到第一个区段的起始RVA处
0040D18A 8BFB mov edi,ebx ; EDI中为全部区段的信息
0040D18C 8B8D 3B6E4000 mov ecx,dword ptr ss: ; ecx=0x0F0,填充的长度
0040D192 B0 FF mov al,0FF
0040D194 F3:AA rep stos byte ptr es: ; 6,EDI处填充垃圾数据FF,长度为F0,NOP
0040D196 83BD 656E4000 01 cmp dword ptr ss:,1
0040D19D 74 50 je short NotePad_.0040D1EF
0040D19F 80BD 316E4000 00 cmp byte ptr ss:,0
0040D1A6 74 47 je short NotePad_.0040D1EF
0040D1A8 68 04010000 push 104
0040D1AD 6A 40 push 40
0040D1AF FF95 056C4000 call dword ptr ss: ; GlobalAlloc,分配个全局堆
0040D1B5 8985 336E4000 mov dword ptr ss:,eax
0040D1BB 68 04010000 push 104
0040D1C0 FFB5 336E4000 push dword ptr ss:
0040D1C6 6A 00 push 0
0040D1C8 FF95 F16B4000 call dword ptr ss: ; GetModuleFileNameA,获取完整的路径,放新申请的全局堆中
0040D1CE 6A 00 push 0
0040D1D0 6A 00 push 0
0040D1D2 6A 04 push 4
0040D1D4 6A 00 push 0
0040D1D6 6A 00 push 0
0040D1D8 68 00000080 push 80000000
0040D1DD FFB5 336E4000 push dword ptr ss:
0040D1E3 FF95 ED6B4000 call dword ptr ss: ; CreateFileA,读取本身文件,eax放获得的句柄。
; 目的是占用该文件的句柄,使得dump跟修复的时候,无法获得该文件的句柄
上面填充垃圾数据的处理方法,只要全NOP掉即可,对于占文件句柄来anti-dump,可这样处理:
方法一:
0040D1CE 6A 00 push 0
0040D1D0 6A 00 push 0
0040D1D2 6A 04 push 4
0040D1D4 6A 00 push 0
0040D1D6 6A 00 push 0
0040D1D8 68 00000080 push 80000000
0040D1DD FFB5 336E4000 push dword ptr ss:
0040D1E3 FF95 ED6B4000 call dword ptr ss: ;CreateFileA
把这些代码全NOP掉,或者把push 0处的机器码6A 00修改为EB 19
方法二:
把CreateFileA的第三个参数ShareMode修改为FILE_SHARE_READ|FILE_SHARE_WRITE,数值为3
0040D1CE 6A 00 push 0
0040D1D0 6A 00 push 0
0040D1D2 6A 04 push 4
0040D1D4 6A 00 push 0
0040D1D6 6A 00 push 3
0040D1D8 68 00000080 push 80000000
0040D1DD FFB5 336E4000 push dword ptr ss:
0040D1E3 FF95 ED6B4000 call dword ptr ss: ;CreateFileA
六、再次大量的SEH(int3)
0040D239 CC int3
0040D23A 8D85 0F624000 lea eax,dword ptr ss:
0040D240 2B85 4D6D4000 sub eax,dword ptr ss:
0040D246 83E8 13 sub eax,13
0040D249 8985 516D4000 mov dword ptr ss:,eax
0040D24F 8BB5 556D4000 mov esi,dword ptr ss:
0040D255 8BFD mov edi,ebp
0040D257 83FE 00 cmp esi,0
0040D25A 0F84 8D000000 je NotePad_.0040D2ED
0040D260 CC int3
0040D261 8B9D 516D4000 mov ebx,dword ptr ss:
0040D267 8B87 596D4000 mov eax,dword ptr ds:
0040D26D 03D8 add ebx,eax
0040D26F 8B8F 5D6D4000 mov ecx,dword ptr ds:
0040D275 B8 40000000 mov eax,40
0040D27A E8 A7FFFFFF call NotePad_.0040D226
0040D27F D1E9 shr ecx,1
0040D281 56 push esi
0040D282 57 push edi
0040D283 8BF3 mov esi,ebx
0040D285 8BFE mov edi,esi
0040D287 60 pushad
0040D288 66:8B9D 636E4000 mov bx,word ptr ss:
0040D28F E8 81FDFFFF call NotePad_.0040D015
0040D294 61 popad
0040D295 33D2 xor edx,edx
0040D297 66:8B9C2A 4F6E4000 mov bx,word ptr ds:
0040D29F E8 94010000 call NotePad_.0040D438
0040D2A4 66:899C2A 4F6E4000 mov word ptr ds:,bx
0040D2AC 66:AD lods word ptr ds:
0040D2AE CC int3 //这个SEH处理得小心
0040D2AF 66:AB stos word ptr es:
这个处理流程在上面各SEH处理分支的第二个,需手动置EIP+1,直接NOP掉会导致出错
后面还有很多,由于这些SEH的出口地址都在异常下面,也就是EIP+1处,故处理方法只要全NOP掉这些int3指令即可
七、跳过输入表的加密
0040D371 FFB5 356D4000 push dword ptr ss:
0040D377 FF95 C26E4000 call dword ptr ss: ; GetProcAddress
0040D37D 80BD 326E4000 01 cmp byte ptr ss:,1 ; 是否加密标志,把下面的跳直接改JMP,即可跳过加密
0040D384 75 5E jnz short NotePad_.0040D3E4
0040D386 3B85 0D6C4000 cmp eax,dword ptr ss: ; CopyFileA
0040D38C 75 08 jnz short NotePad_.0040D396
0040D38E 8D85 40674000 lea eax,dword ptr ss: ; 填充加密的地址,下面同
0040D394 EB 4E jmp short NotePad_.0040D3E4
0040D396 3B85 1D6C4000 cmp eax,dword ptr ss: ; OpenFile
0040D39C 75 08 jnz short NotePad_.0040D3A6
0040D39E 8D85 026A4000 lea eax,dword ptr ss:
0040D3A4 EB 3E jmp short NotePad_.0040D3E4
0040D3A6 3B85 ED6B4000 cmp eax,dword ptr ss: ; CreateFileA
0040D3AC 75 08 jnz short NotePad_.0040D3B6
0040D3AE 8D85 726A4000 lea eax,dword ptr ss:
0040D3B4 EB 2E jmp short NotePad_.0040D3E4
0040D3B6 3B85 D16B4000 cmp eax,dword ptr ss: ; GetModuleHandleA
0040D3BC 75 08 jnz short NotePad_.0040D3C6
0040D3BE 8D85 256B4000 lea eax,dword ptr ss:
0040D3C4 EB 1E jmp short NotePad_.0040D3E4
0040D3C6 3B85 F16B4000 cmp eax,dword ptr ss: ; GetModuleFileNameA
0040D3CC 75 08 jnz short NotePad_.0040D3D6
0040D3CE 8D85 566B4000 lea eax,dword ptr ss:
0040D3D4 EB 0E jmp short NotePad_.0040D3E4
0040D3D6 3B85 F96B4000 cmp eax,dword ptr ss: ; CloseHandle
0040D3DC 75 06 jnz short NotePad_.0040D3E4
0040D3DE 8D85 F26A4000 lea eax,dword ptr ss:
0040D3E4 8907 mov dword ptr ds:,eax
0040D3E6 8385 3D6D4000 04 add dword ptr ss:,4
0040D3ED ^ E9 3CFFFFFF jmp NotePad_.0040D32E
0040D3F2 CC int3
0040D3F3 83C6 14 add esi,14
0040D3F6 8B95 516D4000 mov edx,dword ptr ss:
0040D3FC ^ E9 FBFEFFFF jmp NotePad_.0040D2FC
0040D401 8DBD D7644000 lea edi,dword ptr ss: ; 处理完毕
0040D407 32C0 xor al,al
事实上,该壳仅仅处理了以上列出的几个函数。处理方法:
0040D384 75 5E jnz short NotePad_.0040D3E4改JMP
或者把填充加密地址的lea指令全NOP,也或者把是否处理的跳转全修改了。
事实上,也就是对特定的函数,进行的IAT HOOK
以GetModuleHandleA为例,看下HOOK函数:
0040D929 C8 000000 enter 0,0
0040D92D 56 push esi
0040D92E E8 00000000 call NotePad_.0040D933
0040D933 812C24 2F6B4000 sub dword ptr ss:,NotePad_.00406B2F ; ASCII "DlgCtrlID"
0040D93A 5E pop esi
0040D93B 8B45 08 mov eax,dword ptr ss:
0040D93E 83F8 00 cmp eax,0
0040D941 75 0B jnz short NotePad_.0040D94E
0040D943 8B86 696E4000 mov eax,dword ptr ds:
0040D949 5E pop esi
0040D94A C9 leave
0040D94B C2 0400 retn 4
0040D94E 50 push eax
0040D94F FF96 D16B4000 call dword ptr ds: ; kernel32.GetModuleHandleA
0040D955 5E pop esi
0040D956 C9 leave
0040D957 C2 0400 retn 4
0040D95A C8 000000 enter 0,0
0040D95E 52 push edx
0040D95F E8 00000000 call NotePad_.0040D964
0040D964 812C24 606B4000 sub dword ptr ss:,NotePad_.00406B60 ; ASCII "nt"
八、革命完成,跳到OEP
0040D407 32C0 xor al,al
0040D409 B9 33010000 mov ecx,133
0040D40E 8B85 396D4000 mov eax,dword ptr ss: ; 取出OEP
0040D414 0385 516D4000 add eax,dword ptr ss: ; OEP RVA+ImageBase
0040D41A 8985 2B664000 mov dword ptr ss:,eax ; 修改指令,把下面retn前的push地址改为了OEP地址
0040D420 8B0424 mov eax,dword ptr ss:
0040D423 64:67:A3 0000 mov dword ptr fs:,eax
0040D428 83C4 08 add esp,8
0040D42B 5D pop ebp
0040D42C 9D popfd
0040D42D 61 popad
0040D42E 68 00000000 push 0
0040D433 C3 retn ; 跳去OEP
后被修改为:
0040D42E 68 CC104000 push NotePad_.004010CC ; 修改为OEP的值
0040D433 C3 retn ; 跳去
至此,脱壳完毕。 能否上传附件呢
页:
[1]