好友
阅读权限10
听众
最后登录1970-1-1
|
jomin
发表于 2009-9-30 08:26
Enigma主程序脱壳破解系列之一 -----DLL解捆绑[全面开放]
之前发脱壳版的时候,我说过Enigma这个壳的核心是一个dll文件。所有的解码和处理过程都是在这个dll里面完成的。本片文章就来讨论一下如何把捆绑在里面dll文件提取出来。
对于所有用Enigma保护的程序来说,捆绑DLL_Loader.dll这个文件是必须的。而对于Enigma 1.65的主程序来说,这里面还另外捆绑了两个dll,这两个dll也是Enigma运行的时候必须的。
开始讨论。
PS:对于想学脱壳的初学者来说,下面的代码一定要仔细看,弄明白。因为这段代码里面几乎包含了一个壳的所有功能。如果你能完全弄懂下面这段代码。相信你的水平很上升一个新台阶的。
OD载入主程序。
x
00000: 0061A767 > 55 push ebp<------停在这里
00001: 0061A768 8BEC mov ebp,esp
00002: 0061A76A 83C4 F0 add esp,-10
00003: 0061A76D B8 00104000 mov eax,Enigma.00401000
00004: 0061A772 E8 01000000 call Enigma.0061A778<----近call F7
00005: 0061A777 9A 83C4108B E55D call far 5DE5:8B10C483
00006: 0061A77E - E9 3D6F4400 jmp Enigma.00A616C0
00007:
00008:
00009: 0061A778 83C4 10 add esp,10
00010: 0061A77B 8BE5 mov esp,ebp
00011: 0061A77D 5D pop ebp
00012: 0061A77E - E9 3D6F4400 jmp Enigma.00A616C0-----跳到下面去了
00013:
00014: 00A616C0 60 pushad
00015: 00A616C1 E8 00000000 call Enigma.00A616C6
00016: 00A616C6 5D pop ebp-----------------代码自定位,在dll中才有效果
00017: 00A616C7 81ED 06000000 sub ebp,6
00018: 00A616CD 81ED C0166600 sub ebp,Enigma.006616C0-
00019: 00A616D3 E9 4C000000 jmp Enigma.00A61724
00020:
00021: 解码
00022: 00A6172D B8 C0166600 mov eax,Enigma.006616C0
00023: 00A61732 03C5 add eax,ebp
00024: 00A61734 81C0 93000000 add eax,93
00025: 00A6173A B9 0C060000 mov ecx,60C
00026: 00A6173F BA F24D8F45 mov edx,458F4DF2
00027: 00A61744 3010 xor byte ptr ds:[eax],dl
00028: 00A61746 40 inc eax
00029: 00A61747 49 dec ecx
00030: 00A61748 ^ 0F85 F6FFFFFF jnz Enigma.00A61744
00031: 00A6174E E9 04000000 jmp Enigma.00A61757
00032:
00033: 00A61757 6A 40 push 40
00034: 00A61759 68 00100000 push 1000
00035: 00A6175E 68 00EE0B00 push 0BEE00
00036: 00A61763 81F0 4DE6FA2A xor eax,2AFAE64D
00037: 00A61769 81F0 4DE6FA2A xor eax,2AFAE64D
00038: 00A6176F 33C0 xor eax,eax
00039: 00A61771 50 push eax
00040: 00A61772 FF95 80015F00 call dword ptr ss:[ebp+5F0180] ; 申请一段内存,用来解压dll的代码
00041: 00A61778 50 push eax
00042: 00A61779 8BCD mov ecx,ebp
00043: 00A6177B 8B89 3C000000 mov ecx,dword ptr ds:[ecx+3C]
00044: 00A61781 81C1 F8000000 add ecx,0F8
00045: 00A61787 03CD add ecx,ebp
00046: 00A61789 B8 0A000000 mov eax,0A
00047: 00A6178E BA 28000000 mov edx,28
00048: 00A61793 F7E2 mul edx
00049: 00A61795 03C8 add ecx,eax
00050: 00A61797 8B81 0C000000 mov eax,dword ptr ds:[ecx+C]
00051: 00A6179D 03C5 add eax,ebp
00052: 00A6179F 50 push eax
00053: 00A617A0 68 01DA0400 push 4DA01
00054: 00A617A5 68 BE3C6100 push Enigma.00613CBE
00055: 00A617AA 012C24 add dword ptr ss:[esp],ebp
00056: 00A617AD 68 00000000 push 0
00057: 00A617B2 E8 05000000 call Enigma.00A617BC ; 异或解密压缩后的dll数据
00058: 00A617B7 E9 28000000 jmp Enigma.00A617E4
00059: 00A617BC 55 push ebp
00060: 00A617BD 8BEC mov ebp,esp
00061: 00A617BF 8B85 08000000 mov eax,dword ptr ss:[ebp+8]
00062: 00A617C5 8B95 0C000000 mov edx,dword ptr ss:[ebp+C]
00063: 00A617CB 8B8D 10000000 mov ecx,dword ptr ss:[ebp+10]
00064: 00A617D1 C1E9 02 shr ecx,2
00065: 00A617D4 3102 xor dword ptr ds:[edx],eax
00066: 00A617D6 83C2 04 add edx,4
00067: 00A617D9 49 dec ecx
00068: 00A617DA ^ 0F85 F4FFFFFF jnz Enigma.00A617D4
00069: 00A617E0 5D pop ebp
00070: 00A617E1 C2 0C00 retn 0C
00071: 00A617E4 8B8C24 04000000 mov ecx,dword ptr ss:[esp+4]
00072: 00A617EB 68 01DA0400 push 4DA01
00073: 00A617F0 68 BE3C6100 push Enigma.00613CBE
00074: 00A617F5 012C24 add dword ptr ss:[esp],ebp
00075: 00A617F8 51 push ecx
00076: 00A617F9 E8 05000000 call Enigma.00A61803
00077: 00A617FE E9 27020000 jmp Enigma.00A61A2A
00078: 00A61803 55 push ebp
00079: 00A61804 54 push esp
00080: 00A61805 5D pop ebp
00081: 00A61806 FF75 0C push dword ptr ss:[ebp+C]
00082: 00A61809 FF75 08 push dword ptr ss:[ebp+8]
00083: 00A6180C E8 66000000 call Enigma.00A61877 ; 调用APlib的解压函数解码dll代码,压缩后的数据放在A13CBE里,解压的代码放在申请的内存中-----1
00084: 00A61811 8BBD 08000000 mov edi,dword ptr ss:[ebp+8] ; 这里是用来修正由于磁盘文件和内存镜像之前的差异.
00085: 00A61817 33C9 xor ecx,ecx
00086: 00A61819 33D2 xor edx,edx
00087: 00A6181B 83E8 05 sub eax,5
00088: 00A6181E 48 dec eax
00089: 00A6181F 0F84 4E000000 je Enigma.00A61873
00090: 00A61825 0F88 48000000 js Enigma.00A61873
00091: 00A6182B 66:8B1C39 mov bx,word ptr ds:[ecx+edi]
00092: 00A6182F 80FB E8 cmp bl,0E8
00093: 00A61832 0F84 1A000000 je Enigma.00A61852
00094: 00A61838 80FB E9 cmp bl,0E9
00095: 00A6183B 0F84 11000000 je Enigma.00A61852
00096: 00A61841 66:81FB FF25 cmp bx,25FF
00097: 00A61846 0F84 15000000 je Enigma.00A61861
00098: 00A6184C 41 inc ecx
00099: 00A6184D ^ E9 CCFFFFFF jmp Enigma.00A6181E
00100: 00A61852 294C39 01 sub dword ptr ds:[ecx+edi+1],ecx
00101: 00A61856 83C1 05 add ecx,5
00102: 00A61859 83E8 04 sub eax,4
00103: 00A6185C ^ E9 BDFFFFFF jmp Enigma.00A6181E
00104: 00A61861 295439 02 sub dword ptr ds:[ecx+edi+2],edx
00105: 00A61865 83C1 06 add ecx,6
00106: 00A61868 83EA 04 sub edx,4
00107: 00A6186B 83E8 05 sub eax,5
00108: 00A6186E ^ E9 ABFFFFFF jmp Enigma.00A6181E
00109: 00A61873 5D pop ebp
00110: 00A61874 C2 0C00 retn 0C
00111:
00112:
00113: 00A61A2A 5F pop edi
00114: 00A61A2B 5E pop esi
00115: 00A61A2C E9 04000000 jmp Enigma.00A61A35
00116: 00A61A31 0D 60169AB8 or eax,B89A1660
00117: 00A61A36 C016 66 rcl byte ptr ds:[esi],66
00118: 00A61A39 0003 add byte ptr ds:[ebx],al
00119: 00A61A3B C581 C09B0300 lds eax,fword ptr ds:[ecx+39BC0]
00120: 00A61A41 00B9 04030000 add byte ptr ds:[ecx+304],bh
00121: 00A61A47 BA 6315C010 mov edx,10C01563
00122: 00A61A4C 3010 xor byte ptr ds:[eax],dl ; 继续异或解码
00123: 00A61A4E 40 inc eax
00124: 00A61A4F 49 dec ecx
00125: 00A61A50 ^ 0F85 F6FFFFFF jnz Enigma.00A61A4C
00126: 00A61A56 E9 04000000 jmp Enigma.00A61A5F
00127: 00A61A5B 46 inc esi
00128: 00A61A5C 1867 FC sbb byte ptr ds:[edi-4],ah
00129: 00A61A5F 56 push esi
00130: 00A61A60 57 push edi
00131: 00A61A61 8B8E 54010000 mov ecx,dword ptr ds:[esi+154]
00132: 00A61A67 C1E9 02 shr ecx,2
00133: 00A61A6A F2:A5 repne movs dword ptr es:[edi],dword ptr>; 复制DLL的PE头到A630000,就是加壳文件的最后一个区段
00134: 00A61A6C 5F pop edi
00135: 00A61A6D 5E pop esi
00136: 00A61A6E 8B9E 3C000000 mov ebx,dword ptr ds:[esi+3C]
00137: 00A61A74 53 push ebx
00138: 00A61A75 0FBF5C33 06 movsx ebx,word ptr ds:[ebx+esi+6]
00139: 00A61A7A 5A pop edx
00140: 00A61A7B 81C2 F8000000 add edx,0F8
00141: 00A61A81 03D6 add edx,esi
00142: 00A61A83 81FB 00000000 cmp ebx,0 ; 比较是否复制完
00143: 00A61A89 0F84 1B000000 je Enigma.00A61AAA
00144: 00A61A8F 56 push esi
00145: 00A61A90 57 push edi
00146: 00A61A91 8B4A 10 mov ecx,dword ptr ds:[edx+10]
00147: 00A61A94 037A 0C add edi,dword ptr ds:[edx+C]
00148: 00A61A97 0372 14 add esi,dword ptr ds:[edx+14]
00149: 00A61A9A F2:A4 repne movs byte ptr es:[edi],byte ptr d>; 按区段复制DLL的到A63000去----------------2
00150: 00A61A9C 5F pop edi
00151: 00A61A9D 5E pop esi
00152: 00A61A9E 81C2 28000000 add edx,28
00153: 00A61AA4 4B dec ebx
00154: 00A61AA5 ^ E9 D9FFFFFF jmp Enigma.00A61A83
00155: 00A61AAA 68 00400000 push 4000
00156: 00A61AAF 68 00EE0B00 push 0BEE00
00157: 00A61AB4 56 push esi
00158: 00A61AB5 FF95 84015F00 call dword ptr ss:[ebp+5F0184] ; 释放申请的内存
00159: 00A61ABB 87FE xchg esi,edi
00160: 00A61ABD 87F7 xchg edi,esi
00161: 00A61ABF 8B77 3C mov esi,dword ptr ds:[edi+3C]
00162: 00A61AC2 87F7 xchg edi,esi
00163: 00A61AC4 8BBC37 A0000000 mov edi,dword ptr ds:[edi+esi+A0] ; 获取重定位表的位置
00164: 00A61ACB 03FE add edi,esi
00165: 00A61ACD 56 push esi
00166: 00A61ACE 5B pop ebx
00167: 00A61ACF 81EB 00004000 sub ebx,Enigma.00400000 ; 下面的代码用来把dll代码重定位到A63000
00168: 00A61AD5 87FA xchg edx,edi
00169: 00A61AD7 8B7A 00 mov edi,dword ptr ds:[edx]
00170: 00A61ADA 87FA xchg edx,edi
00171: 00A61ADC 87F9 xchg ecx,edi
00172: 00A61ADE 8B79 04 mov edi,dword ptr ds:[ecx+4]
00173: 00A61AE1 87F9 xchg ecx,edi
00174: 00A61AE3 81FA 00000000 cmp edx,0
00175: 00A61AE9 0F84 46000000 je Enigma.00A61B35
00176: 00A61AEF 03D6 add edx,esi
00177: 00A61AF1 81C7 08000000 add edi,8
00178: 00A61AF7 81E9 08000000 sub ecx,8
00179: 00A61AFD 81F9 00000000 cmp ecx,0
00180: 00A61B03 ^ 0F84 CCFFFFFF je Enigma.00A61AD5
00181: 00A61B09 66:8B07 mov ax,word ptr ds:[edi]
00182: 00A61B0C C1E8 0C shr eax,0C
00183: 00A61B0F 83E0 0F and eax,0F
00184: 00A61B12 81F8 03000000 cmp eax,3
00185: 00A61B18 0F85 0D000000 jnz Enigma.00A61B2B
00186: 00A61B1E 66:8B07 mov ax,word ptr ds:[edi]
00187: 00A61B21 81E0 FF0F0000 and eax,0FFF
00188: 00A61B27 03C2 add eax,edx
00189: 00A61B29 0118 add dword ptr ds:[eax],ebx ; 修改指令,重定位-------------------3
00190: 00A61B2B 49 dec ecx
00191: 00A61B2C 49 dec ecx
00192: 00A61B2D 83C7 02 add edi,2
00193: 00A61B30 ^ E9 C8FFFFFF jmp Enigma.00A61AFD
00194: 00A61B35 E9 04000000 jmp Enigma.00A61B3E
00195: 00A61B3A DAC9 fcmove st,st(1)
00196: 00A61B3C 51 push ecx
00197: 00A61B3D AD lods dword ptr ds:[esi]
00198: 00A61B3E B8 C0166600 mov eax,Enigma.006616C0
00199: 00A61B43 03C5 add eax,ebp
00200: 00A61B45 81C0 A4040000 add eax,4A4
00201: 00A61B4B B9 FB010000 mov ecx,1FB
00202: 00A61B50 BA 6872F6BB mov edx,BBF67268
00203: 00A61B55 3010 xor byte ptr ds:[eax],dl ; 继续向下解码
00204: 00A61B57 40 inc eax
00205: 00A61B58 49 dec ecx
00206: 00A61B59 ^ 0F85 F6FFFFFF jnz Enigma.00A61B55
00207: 00A61B5F E9 04000000 jmp Enigma.00A61B68
00208: 00A61B64 47 inc edi
00209: 00A61B65 DD85 B58B7E3C fld qword ptr ss:[ebp+3C7E8BB5]
00210: 00A61B6B 8BBC37 80000000 mov edi,dword ptr ds:[edi+esi+80] ; 获取输入表位置
00211: 00A61B72 03FE add edi,esi
00212: 00A61B74 837F 0C 00 cmp dword ptr ds:[edi+C],0
00213: 00A61B78 0F84 9A000000 je Enigma.00A61C18
00214: 00A61B7E 97 xchg eax,edi ; 这里开始填充IAT-----------------4
00215: 00A61B7F 8B78 0C mov edi,dword ptr ds:[eax+C]
00216: 00A61B82 97 xchg eax,edi
00217: 00A61B83 03C6 add eax,esi
00218: 00A61B85 50 push eax
00219: 00A61B86 FF95 88015F00 call dword ptr ss:[ebp+5F0188] ; 调用GetModuleHandleA,载入需要的dll文件的基址
00220: 00A61B8C 81F8 00000000 cmp eax,0
00221: 00A61B92 0F85 0C000000 jnz Enigma.00A61BA4 ; 没有载入的话就用下面的函数载入
00222: 00A61B98 8B47 0C mov eax,dword ptr ds:[edi+C]
00223: 00A61B9B 03C6 add eax,esi
00224: 00A61B9D 50 push eax
00225: 00A61B9E FF95 94015F00 call dword ptr ss:[ebp+5F0194] ; 调用LoadLibraryA,载入需要的dll文件
00226: 00A61BA4 837F 0C 00 cmp dword ptr ds:[edi+C],0
00227: 00A61BA8 0F84 6A000000 je Enigma.00A61C18
00228: 00A61BAE 837F 00 00 cmp dword ptr ds:[edi],0
00229: 00A61BB2 0F85 0A000000 jnz Enigma.00A61BC2
00230: 00A61BB8 837F 10 00 cmp dword ptr ds:[edi+10],0
00231: 00A61BBC 0F84 4A000000 je Enigma.00A61C0C
00232: 00A61BC2 55 push ebp
00233: 00A61BC3 8D55 00 lea edx,dword ptr ss:[ebp]
00234: 00A61BC6 87FD xchg ebp,edi
00235: 00A61BC8 8B7D 10 mov edi,dword ptr ss:[ebp+10]
00236: 00A61BCB 87FD xchg ebp,edi
00237: 00A61BCD 03EE add ebp,esi
00238: 00A61BCF 837D 00 00 cmp dword ptr ss:[ebp],0
00239: 00A61BD3 0F84 33000000 je Enigma.00A61C0C
00240: 00A61BD9 8B4D 00 mov ecx,dword ptr ss:[ebp]
00241: 00A61BDC 50 push eax
00242: 00A61BDD 52 push edx
00243: 00A61BDE 0BC9 or ecx,ecx
00244: 00A61BE0 0F89 06000000 jns Enigma.00A61BEC
00245: 00A61BE6 51 push ecx
00246: 00A61BE7 E9 09000000 jmp Enigma.00A61BF5
00247: 00A61BEC 03CE add ecx,esi
00248: 00A61BEE 81C1 02000000 add ecx,2
00249: 00A61BF4 51 push ecx
00250: 00A61BF5 50 push eax
00251: 00A61BF6 FF92 8C015F00 call dword ptr ds:[edx+5F018C] ; 调用GetProAddress获取API地址
00252: 00A61BFC 5A pop edx
00253: 00A61BFD 8945 00 mov dword ptr ss:[ebp],eax
00254: 00A61C00 58 pop eax
00255: 00A61C01 81C5 04000000 add ebp,4
00256: 00A61C07 ^ E9 C3FFFFFF jmp Enigma.00A61BCF
00257: 00A61C0C 5D pop ebp
00258: 00A61C0D 81C7 14000000 add edi,14
00259: 00A61C13 ^ E9 5CFFFFFF jmp Enigma.00A61B74
00260: 00A61C18 54 push esp ; 到此dll载入过程已基本完成.
00261: 00A61C19 64:FF35 00000000 push dword ptr fs:[0] ; 还差一步,就是为DLL的初始化提供适当的环境,这步骤由dll自己完成
00262: 00A61C20 68 601D6600 push Enigma.00661D60
00263: 00A61C25 56 push esi
00264: 00A61C26 55 push ebp
00265: 00A61C27 8B46 3C mov eax,dword ptr ds:[esi+3C]
00266: 00A61C2A 8B8430 78000000 mov eax,dword ptr ds:[eax+esi+78]
00267: 00A61C31 03C6 add eax,esi
00268: 00A61C33 81C0 28000000 add eax,28
00269: 00A61C39 60 pushad
00270: 00A61C3A 8B40 04 mov eax,dword ptr ds:[eax+4]
00271: 00A61C3D 56 push esi
00272: 00A61C3E 03C6 add eax,esi
00273: 00A61C40 FFD0 call eax ; 调用dll自身的initial函数 为自己提供初始化环境
00274: 00A61C42 61 popad
00275: 00A61C43 90 nop
00276: 00A61C44 8B40 00 mov eax,dword ptr ds:[eax]
00277: 00A61C47 90 nop
00278: 00A61C48 03C6 add eax,esi
00279: 00A61C4A 56 push esi
00280: 00A61C4B 6A 00 push 0
00281: 00A61C4D 6A 01 push 1
00282: 00A61C4F 55 push ebp
00283: 00A61C50 50 push eax---------------------------------这里有玄机,留在下篇再讲。
00284: 00A61C51 8B46 3C mov eax,dword ptr ds:[esi+3C]
00285: 00A61C54 8B8430 28000000 mov eax,dword ptr ds:[eax+esi+28]
00286: 00A61C5B 03C6 add eax,esi
00287: 00A61C5D 50 push eax ; 这里就会去dll的入口点了
00288: 00A61C5E C3 retn
从上面的分析可以看出,我们有四处可以提取代码的地方:
1,在壳代码刚刚调用完Aplib的解压函数的时候,这个时候的dll文件直接提取出来就可以用,不用做任何修正.因为这个时候的代码对齐值是0x200,即正常磁盘中PE文件的对齐值.
2,在把代码复制到A63000中以后.这个过程其实是壳模仿PE加载器把文件按照0x1000的对齐值映射到内存中的过程.这个时候提取文件的话,需要修正文件对齐值为0x1000,并修正PE头中的RAW=RVA。
3,在处理完重定位以后.这个是壳代码仿照加载器重定位dll的代码和数据到A63000.如果在重定位以后提取文件的话,除了修正上面提到的数据外.还要修正代码基址.
4,填充IAT以后.这个时候IAT表已经被填充完毕.抓取文件后 需要修正的部分没有增加.
来评价一下四处抓取文件的优劣.
1,这个时候的代码是最原始的.也就是说这个时候的代码跟原始文件是一模一样的,是最完美的.但是用于内存对齐值跟文件对齐值不相同,RAW和RVA存在一个换算的问题.所以有的时候比较麻烦.个人不推荐
2,这个时候的文件就相当于磁盘文件刚刚被映射到内存中一样,RVA=RAW.其他的数据都没有被动过.算比较完美的了.个人比较推荐在这时提取.
3,这个时候的文件相比上一处的文件,就差了一个重定位,这时文件的基址被重定位到了A63000.就多了一个修复代码基址的步骤.不过实践证明,这个时候提取的文件,如果把代码基址修正为00A63000的话会出现无法载入的问题,大概是因为这个基址被保留了吧。这时候可以用LordPE重建一下镜像基址就可以了。同样不推荐在这里。
4,这个时候是最不好的.输入表的中的整个IAT都被修改了。个人不喜欢(偶是完美主义者)。
看完上面的分析,相信你应该能按自己喜好提取出Dll_Loader.dll文件了。
OK。下面开始提取下面剩下的两个文件。
刚才说了DLL_Loader.dll是整个壳保护的核心。所有的解码 代码处理都在这个dll里面进行。当然剩下两个dll的解码也是这里完成的。
说句预先得到的结论,这个版本的Enigma会把剩下两个释放在DLL_Loader.dll后面紧接着它的内存中。---------怎么获得这个结论的呢?让程序运行,然后dump进程,用exeinfoPE提取其中的PE文件。
复制内容到剪贴板代码:
00663000 4D5A MZ 00000100 ( PE )
发现 Exe PE 在偏移 : 00663000
保存文件为 : G:\破解工具箱\加壳工具\Enigma\The Enigma Protector 1.65_20090406_cn\dumped1~Rip.exe
006F650D 4D5A MZ 0000F88B ( ? )
006FABE0 4D5A MZ 0000D88B ( ? )
0071310C 4D5A MZ 00005AFB ( ?)
007177B1 4D5A MZ 00005537 ( 舿 )
0074B000 4D5A MZ 00000100 ( PE )
发现 Exe PE 在偏移 : 0074B000
保存文件为 : G:\破解工具箱\加壳工具\Enigma\The Enigma Protector 1.65_20090406_cn\dumped2~Rip.exe
0076DDAA 4D5A MZ 000048C0 ( ? )
0076DF6A 4D5A MZ 0000F8E0 ( ?? )
0076E15E 4D5A MZ 0000F300 ( ?? )
0076E1DE 4D5A MZ 0000F8D0 ( ?? )
0076E312 4D5A MZ 000000B7 ( 亄 )
00788000 4D5A MZ 000000D8 ( PE )
发现 Exe PE 在偏移 : 00788000
保存文件为 : G:\破解工具箱\加壳工具\Enigma\The Enigma Protector 1.65_20090406_cn\dumped3~Rip.exe
007906B7 4D5A MZ 0000D233 ( ?? )
--- 文件末尾 ---
发现 : 3
发现最后一个区段中有三个PE文件,第一个就是DLL_Loader.dll。剩下那两个就是我们的目标。
再说一句,1.55版本不会这样,而是把剩下的两个文件释放在申请的内存中。但是没关系,我们后面说的提起方法对这种方式同样有效。
闲话不多说了。开始!
既然知道了壳会把剩下的两个dll释放的位置,就先在00B4B000处下个硬件访问断点或内存访问断点。我们知道这里会写入一个'M'。然后运行程序。(一般来说硬件断点很难断下来,内存断点也有的时候也断不下来,这时考虑使用双断点法,即在某些频繁调用的系统API代码中间下Int3断点。这样中断几次就可以在目标位置断下来了。)
x
00000: 00A658E8 56 push esi
00001: 00A658E9 57 push edi
00002: 00A658EA 89C6 mov esi,eax
00003: 00A658EC 89D7 mov edi,edx
00004: 00A658EE 89C8 mov eax,ecx
00005: 00A658F0 39F7 cmp edi,esi
00006: 00A658F2 77 13 ja short Enigma.00A65907
00007: 00A658F4 74 2F je short Enigma.00A65925
00008: 00A658F6 C1F9 02 sar ecx,2
00009: 00A658F9 78 2A js short Enigma.00A65925
00010: 00A658FB F3:A5 rep movs dword ptr es:[edi],dword ptr d>---断在这里。
00011: 00A658FD 89C1 mov ecx,eax
00012: 00A658FF 83E1 03 and ecx,3
00013: 00A65902 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:>
00014: 00A65904 5F pop edi
00015: 00A65905 5E pop esi
00016: 00A65906 C3 retn
这是DLL_Loader.dll中比较频繁调用的写代码的地方。不特征 我们返回到上一层去。
x
00000: 00AF74BE 6A 40 push 40
00001: 00AF74C0 68 00100000 push 1000
00002: 00AF74C5 8B45 F4 mov eax,dword ptr ss:[ebp-C]
00003: 00AF74C8 8B40 50 mov eax,dword ptr ds:[eax+50]
00004: 00AF74CB 50 push eax
00005: 00AF74CC 6A 00 push 0
00006: 00AF74CE E8 4923F7FF call Enigma.00A6981C---------------这里修改内存属性
00007: 00AF74D3 8945 F0 mov dword ptr ss:[ebp-10],eax
00008: 00AF74D6 EB 03 jmp short Enigma.00AF74DB
00009: 00AF74D8 894D F0 mov dword ptr ss:[ebp-10],ecx
00010: 00AF74DB 8B45 F4 mov eax,dword ptr ss:[ebp-C]
00011: 00AF74DE 8B40 50 mov eax,dword ptr ds:[eax+50]
00012: 00AF74E1 8903 mov dword ptr ds:[ebx],eax
00013: 00AF74E3 8B45 F4 mov eax,dword ptr ss:[ebp-C]
00014: 00AF74E6 8B48 54 mov ecx,dword ptr ds:[eax+54]
00015: 00AF74E9 8B55 FC mov edx,dword ptr ss:[ebp-4]
00016: 00AF74EC 8B45 F0 mov eax,dword ptr ss:[ebp-10]
00017: 00AF74EF E8 E42AF7FF call Enigma.00A69FD8------------------写代码的地方
00018: 00AF74F4 8B45 F4 mov eax,dword ptr ss:[ebp-C]
00019: 00AF74F7 0FB770 06 movzx esi,word ptr ds:[eax+6]
00020: 00AF74FB 4E dec esi
00021: 00AF74FC 85F6 test esi,esi
00022: 00AF74FE 7C 35 jl short Enigma.00AF7535-----------这个循环是用来复制PE头的
00023: 00AF7500 46 inc esi
00024: 00AF7501 33DB xor ebx,ebx
00025: 00AF7503 8D049B lea eax,dword ptr ds:[ebx+ebx*4]
00026: 00AF7506 8B55 F4 mov edx,dword ptr ss:[ebp-C]
00027: 00AF7509 8B8CC2 08010000 mov ecx,dword ptr ds:[edx+eax*8+108]
00028: 00AF7510 8B55 F4 mov edx,dword ptr ss:[ebp-C]
00029: 00AF7513 8B94C2 0C010000 mov edx,dword ptr ds:[edx+eax*8+10C]
00030: 00AF751A 0355 FC add edx,dword ptr ss:[ebp-4]
00031: 00AF751D 52 push edx
00032: 00AF751E 8B55 F4 mov edx,dword ptr ss:[ebp-C]
00033: 00AF7521 8B84C2 04010000 mov eax,dword ptr ds:[edx+eax*8+104]
00034: 00AF7528 0345 F0 add eax,dword ptr ss:[ebp-10]
00035: 00AF752B 5A pop edx
00036: 00AF752C E8 A72AF7FF call Enigma.00A69FD8
00037: 00AF7531 43 inc ebx
00038: 00AF7532 4E dec esi--------------------------esi表示的区段数
00039: 00AF7533 ^ 75 CE jnz short Enigma.00AF7503--------------这个循环是用来按0x1000对齐复制代码的。
00040: 00AF7535 8B45 F4 mov eax,dword ptr ss:[ebp-C]----------执行到这里就可以提取文件了
00041: 00AF7538 8B80 A0000000 mov eax,dword ptr ds:[eax+A0]
00042: 00AF753E 85C0 test eax,eax
这段代码就是写入dll代码的特征代码。从1.5x-1.6x都没有什么变化。走出这个循环,就表示代码已经完全复制完了。文件对齐是0x1000。提取文件,然后修正OK了!
还有一个文件。这回选择一个快捷的方法。直接在这里“00AF74BE 6A 40 push 40”下硬件执行断点。然后运行。再断下来的时候就是写入下一个dll的地方了。
好了。这样所有的dll就提取完了。
结束语:在实际应用中,如果发现有捆绑的其他dll的话,可以在进入dll入口点以后 在上面的代码中找几条比较特征的,搜索一下就很容易找到这个地方了。
不知道有没有人注意到,后面两个dll的解码方式也是从一个地方按0x1000对齐复制过来的。其实捆绑的dll也跟DLL_Loader.dll一样 是用APlib的算法压缩的。DLL_Loader.dll里面有对这个函数的调用。而且很频繁。下一讲将讲一下如何从这里入手解码dll,以及APlib算法与脱壳的关系。
下一讲:Enigma主程序脱壳破解系列之二 -----主程序脱壳,敬请期待。
附件是修改的DLL_Loader.dll 解决脱壳后文件退出时的问题。
To Be Continued...
HyperChem
17/04/09 |
|