-
-
[原创]第一次亲密接触壳 简单分析仙剑
-
发表于: 2009-3-22 21:57 7866
-
【作者声明】:刚接触壳,打算从看雪精华6看起,主要是看脱壳技术里的加密保护,前面的壳太强,就从后面看起了,刚学习脱壳,对大牛们的操作很是不解,想知道个为什么于是就自己跟了一下,没什么技术含量,只是希望能给像我这样的菜鸟提供些学习脱壳的思路。失误之处敬请诸位大侠赐教!
【软件名称】: 看雪精华6的仙剑第二篇
【调试环境】:WinXP、OD、PEiD、LordPE、ImportREC
【分析过程】:
用IsDebug 1.4插件去掉Ollydbg的调试器标志。
00412060 > /EB 20 jmp short 00412082 ;程序入口
00412062 |0000 add byte ptr [eax], al
00412064 |40 inc eax
00412065 |0000 add byte ptr [eax], al
00412067 |0040 00 add byte ptr [eax], al
0041206A |0000 add byte ptr [eax], al
0041206C |0000 add byte ptr [eax], al
0041206E |0000 add byte ptr [eax], al
00412070 |0000 add byte ptr [eax], al
00412072 |0000 add byte ptr [eax], al
00412074 |0000 add byte ptr [eax], al
00412076 |0000 add byte ptr [eax], al
00412078 |0000 add byte ptr [eax], al
0041207A |0000 add byte ptr [eax], al
0041207C |0000 add byte ptr [eax], al
0041207E |0000 add byte ptr [eax], al
00412080 |0000 add byte ptr [eax], al
00412082 \9C pushfd ;保存标志寄存器
00412083 55 push ebp
00412084 57 push edi
00412085 56 push esi
00412086 52 push edx
00412087 51 push ecx
00412088 53 push ebx
00412089 9C pushfd
0041208A E8 00000000 call 0041208F ;F7
0041208F 5D pop ebp ; Main.0041208F
00412090 81ED 00000000 sub ebp, 0
00412096 9D popfd
00412097 83C4 14 add esp, 14
0041209A 5D pop ebp
0041209B 9D popfd
0041209C 60 pushad
0041209D E8 01000000 call 004120A3 ;F7
004120A3 83C4 04 add esp, 4
004120A6 E8 01000000 call 004120AC ;F7
004120AC 5D pop ebp ; Main.004120AB
004120AD 81ED 681E4000 sub ebp, 00401E68
004120B3 /EB 02 jmp short 004120B7
004120B7 8D85 D71E4000 lea eax, dword ptr [ebp+401ED7]
004120BD 50 push eax
004120BE EB 03 jmp short 004120C3
004120C3 C3 retn
0041211A 8D85 851E4000 lea eax, dword ptr [ebp+401E85] 返回到这儿
00412120 50 push eax
00412121 33C0 xor eax, eax
00412123 64:FF30 push dword ptr fs:[eax] ;构造seh链表
00412126 64:8920 mov dword ptr fs:[eax], esp
00412129 B9 570B0000 mov ecx, 0B57
0041212E 8DBD 421F4000 lea edi, dword ptr [ebp+401F42]
00412134 8BF7 mov esi, edi
00412136 AC lods byte ptr [esi] ;循环解码开始 esi= 00412186,ecx = b57 即对00412186开始的b57个字节进行解码
00412137 /EB 01 jmp short 0041213A
0041213A 2AC1 sub al, cl
0041213C C0C0 D8 rol al, 0D8
0041213F 34 21 xor al, 21
00412141 2AC1 sub al, cl
00412143 EB 01 jmp short 00412146
00412146 /EB 01 jmp short 00412149
00412149 FEC8 dec al
0041214B 90 nop
0041214C FEC8 dec al
0041214E C0C0 C9 rol al, 0C9
00412151 02C1 add al, cl
00412153 EB 01 jmp short 00412156
00412156 04 13 add al, 13
00412158 EB 01 jmp short 0041215B
0041215B 02C1 add al, cl
0041215D 2AC1 sub al, cl
0041215F 90 nop
00412160 02C1 add al, cl
00412162 2AC1 sub al, cl
00412164 F9 stc
00412165 34 6F xor al, 6F
00412167 F0:0FC7C8 lock cmpxchg8b eax
; Illegal use of register 仔细看了一下这段代码, 这个异常除了让OD不断提示外好
像还没有其他附加功能,索性NOP掉,彻底让其清净下来
0041216B AA stos byte ptr es:[edi] ;此时 edi = 00412186 发现00412185处的代码变红了
0041216C EB 02 jmp short 00412170
00412170 ^\E2 C4 loopd short 00412136
00412172 64:8F00 pop dword ptr fs:[eax] ;光标移到此处F4
00412175 58 pop eax
00412176 8B85 811E4000 mov eax, dword ptr [ebp+401E81]
0041217C 3D 570B0000 cmp eax, 0B57 ;比较
00412181 74 02 je short 00412185 ;看堆栈不相等则返回到系统的领空 通过改标志位让其跳转 若不跳则会通过exitthread结束 此处为校验
00412183 61 popad
00412184 C3 retn
00412185 8B4424 20 mov eax, dword ptr [esp+20] ;跳到此处
00412189 40 inc eax
0041218A 78 0A js short 00412196
0041218C C785 4A284000 0>mov dword ptr [ebp+40284A], 1
00412196 8D85 1D1E4000 lea eax, dword ptr [ebp+401E1D]
0041219C B9 AA070000 mov ecx, 7AA
004121A1 E8 3A020000 call 004123E0 ;估计是个校验函数 此时 eax为模块ep ecx为大小 F7跟进
『
004123E0 8BF8 mov edi, eax ; Main.<ModuleEntryPoint>
004123E2 33C0 xor eax, eax
004123E4 33DB xor ebx, ebx
004123E6 33D2 xor edx, edx
004123E8 8A07 mov al, byte ptr [edi]
004123EA F7E2 mul edx
004123EC 03D8 add ebx, eax
004123EE 42 inc edx
004123EF 47 inc edi
004123F0 ^ E2 F6 loopd short 004123E8
004123F2 93 xchg eax, ebx ;算出来的值放入eax
004123F3 C3 retn
』
004121A6 8985 46284000 mov dword ptr [ebp+402846], eax ;求出来的值放入[ebp+402846]处
004121AC 8B85 3E284000 mov eax, dword ptr [ebp+40283E]
004121B2 83E0 01 and eax, 1
004121B5 /74 40 je short 004121F7 ;没跳
004121B7 |8DB5 B6294000 lea esi, dword ptr [ebp+4029B6]
004121BD |8D85 A11F4000 lea eax, dword ptr [ebp+401FA1]
004121C3 |8946 08 mov dword ptr [esi+8], eax
004121C6 |8BFD mov edi, ebp
004121C8 |8D85 D4274000 lea eax, dword ptr [ebp+4027D4]
004121CE |33DB xor ebx, ebx
004121D0 |50 push eax
004121D1 |64:FF33 push dword ptr fs:[ebx] ;构造seh链表
004121D4 |64:8923 mov dword ptr fs:[ebx], esp
004121D7 |BD 4B484342 mov ebp, 4243484B
004121DC |66:B8 0400 mov ax, 4
004121E0 |EB 01 jmp short 004121E3
004121E3 CC int3 ;跳到此处 看堆栈第二句 在转存中跟随下内存访问断点 shift+F9
00412A17 55 push ebp ;来到此处
00412A18 8BEC mov ebp, esp
00412A1A 57 push edi
00412A1B 8B45 10 mov eax, dword ptr [ebp+10] ;context结构地址放入eax
00412A1E 8BB8 9C000000 mov edi, dword ptr [eax+9C] ;context 结构的regEdi放入edi
00412A24 FFB7 BE294000 push dword ptr [edi+4029BE]
00412A2A 8F80 B8000000 pop dword ptr [eax+B8] ;改变context结构中的regeip 通过此句改变程序的执行
00412A30 89B8 B4000000 mov dword ptr [eax+B4], edi ;改变context结构中的regebp
00412A36 C780 B0000000 0>mov dword ptr [eax+B0], 4 ;改变context结构中的regeax
00412A40 B8 00000000 mov eax, 0
00412A45 5F pop edi
00412A46 C9 leave
00412A47 C3 retn ;返回系统的领空 显然我们跟丢了 其实应该在 改变后的regeip处下断点 shift+F9 哈哈 不如我们直接将
004123e3处的断点nop掉,记住这个地址重新来过 将其nop掉
004121E3 90 nop
004121E4 8BEF mov ebp, edi
004121E6 33DB xor ebx, ebx
004121E8 64:8F03 pop dword ptr fs:[ebx]
004121EB 83C4 04 add esp, 4
004121EE 3C 04 cmp al, 4
004121F0 /74 05 je short 004121F7 ;跳了
004121F7 8B85 36284000 mov eax, dword ptr [ebp+402836] ; 跳到此处,获取壳的pe结构的一些基本信息
004121FD 0340 3C add eax, dword ptr [eax+3C] ;pe文件头
00412200 05 80000000 add eax, 80 ;eax指向外壳的输入表
00412205 8B08 mov ecx, dword ptr [eax] ;输入表rva放入ecx
00412207 038D 36284000 add ecx, dword ptr [ebp+402836]
0041220D 83C1 10 add ecx, 10
00412210 8B01 mov eax, dword ptr [ecx]
00412212 0385 36284000 add eax, dword ptr [ebp+402836]
00412218 8B18 mov ebx, dword ptr [eax] ; 取loadlibrarya 放入ebx
0041221A 899D C2294000 mov dword ptr [ebp+4029C2], ebx
00412220 83C0 04 add eax, 4
00412223 8B18 mov ebx, dword ptr [eax] ;取getprocaddress放入ebx
00412225 899D C6294000 mov dword ptr [ebp+4029C6], ebx
0041222B 8D85 CA294000 lea eax, dword ptr [ebp+4029CA] ;kernel32.dll
00412231 50 push eax
00412232 FF95 C2294000 call dword ptr [ebp+4029C2] ;加载kernel32.dll00412232 , kernel32.LoadLibraryA
00412238 8BF0 mov esi, eax ; kernel32.7C800000
0041223A 8985 D7294000 mov dword ptr [ebp+4029D7], eax ; kernel32.7C800000
00412240 8DBD 97204000 lea edi, dword ptr [ebp+402097]
00412246 8D85 DB294000 lea eax, dword ptr [ebp+4029DB] ;getmodulehandlea
0041224C FFD7 call edi ; Main.004122DA F7跟进 其实就是GetProcAddress
『
004122DA 50 push eax
004122DB 56 push esi
004122DC FF95 C6294000 call dword ptr [ebp+4029C6] ; kernel32.GetProcAddress
004122E2 C3 retn
』
0041224E 8985 EC294000 mov dword ptr [ebp+4029EC], eax ; kernel32.GetModuleHandleA
00412254 8D85 F0294000 lea eax, dword ptr [ebp+4029F0]
0041225A FFD7 call edi ; Main.004122DA
0041225C 8985 FF294000 mov dword ptr [ebp+4029FF], eax ; kernel32.VirtualProtect
00412262 8D85 032A4000 lea eax, dword ptr [ebp+402A03]
00412268 FFD7 call edi
0041226A 8985 162A4000 mov dword ptr [ebp+402A16], eax ; kernel32.GetModuleFileNameA
00412270 8D85 1A2A4000 lea eax, dword ptr [ebp+402A1A]
00412276 FFD7 call edi
00412278 8985 262A4000 mov dword ptr [ebp+402A26], eax ; kernel32.CreateFileA
0041227E 8D85 2A2A4000 lea eax, dword ptr [ebp+402A2A]
00412284 FFD7 call edi
00412286 8985 362A4000 mov dword ptr [ebp+402A36], eax ; kernel32.GlobalAlloc
0041228C 8D85 3A2A4000 lea eax, dword ptr [ebp+402A3A]
00412292 FFD7 call edi
00412294 8985 452A4000 mov dword ptr [ebp+402A45], eax ; kernel32.GlobalFree
0041229A 8D85 492A4000 lea eax, dword ptr [ebp+402A49]
004122A0 FFD7 call edi
004122A2 8985 522A4000 mov dword ptr [ebp+402A52], eax ; kernel32.ReadFile
004122A8 8D85 562A4000 lea eax, dword ptr [ebp+402A56]
004122AE FFD7 call edi
004122B0 8985 622A4000 mov dword ptr [ebp+402A62], eax ; kernel32.GetFileSize
004122B6 8D85 662A4000 lea eax, dword ptr [ebp+402A66]
004122BC FFD7 call edi
004122BE 8985 722A4000 mov dword ptr [ebp+402A72], eax ; kernel32.CloseHandle
004122C4 8D85 7A2A4000 lea eax, dword ptr [ebp+402A7A]
004122CA FFD7 call edi
004122CC 8985 762A4000 mov dword ptr [ebp+402A76], eax ; kernel32.CreateEventA
004122D2 8D85 A0204000 lea eax, dword ptr [ebp+4020A0]
004122D8 50 push eax
004122D9 C3 retn
004122E3 F785 3E284000 1>test dword ptr [ebp+40283E], 10 ;返回到这儿
004122ED /74 37 je short 00412326 ;没跳
004122EF 64:FF35 3000000>push dword ptr fs:[30] ;进程环境快入栈
004122F6 58 pop eax ; 放入eax中
004122F7 85C0 test eax, eax
004122F9 /78 0F js short 0041230A ;没跳
004122FB |8B40 0C mov eax, dword ptr [eax+C]
004122FE |8B40 0C mov eax, dword ptr [eax+C]
00412301 |C740 20 0010000>mov dword ptr [eax+20], 1000 ;以上几句实现反dump 这就是有的壳我们要纠正映像大小的原因
00412308 |EB 1C jmp short 00412326
00412326 8BBD 36284000 mov edi, dword ptr [ebp+402836] ; Main.00400000
0041232C 037F 3C add edi, dword ptr [edi+3C] ;获取pe文件头
0041232F 8BB5 36284000 mov esi, dword ptr [ebp+402836] ; Main.00400000
00412335 8B4F 54 mov ecx, dword ptr [edi+54] ;获取dos头,pe头部,区块表总大小
00412338 8D85 B52A4000 lea eax, dword ptr [ebp+402AB5]
0041233E 50 push eax
0041233F 6A 04 push 4
00412341 51 push ecx
00412342 FFB5 36284000 push dword ptr [ebp+402836]
00412348 FF95 FF294000 call dword ptr [ebp+4029FF] ; kernel32.VirtualProtect,改变400000开始的ecx大小的属性 为读写做准备
0041234E F785 3E284000 0>test dword ptr [ebp+40283E], 8
00412358 0F84 A7000000 je 00412405 ;没跳
0041235E 68 04010000 push 104
00412363 8DBD B52A4000 lea edi, dword ptr [ebp+402AB5]
00412369 57 push edi
0041236A 6A 00 push 0
0041236C FF95 162A4000 call dword ptr [ebp+402A16] ; kernel32.GetModuleFileNameA,
00412372 6A 00 push 0
00412374 68 80000000 push 80
00412379 6A 03 push 3
0041237B 6A 00 push 0
0041237D 6A 01 push 1
0041237F 68 00000080 push 80000000
00412384 57 push edi
00412385 FF95 262A4000 call dword ptr [ebp+402A26] ; kernel32.CreateFileA
0041238B 83F8 FF cmp eax, -1
0041238E 75 04 jnz short 00412394 ;跳了
00412394 8BF8 mov edi, eax
00412396 6A 00 push 0
00412398 57 push edi
00412399 FF95 622A4000 call dword ptr [ebp+402A62] ; kernel32.GetFileSize
0041239F 83E8 05 sub eax, 5
004123A2 96 xchg eax, esi
004123A3 56 push esi
004123A4 6A 40 push 40
004123A6 FF95 362A4000 call dword ptr [ebp+402A36] ; kernel32.GlobalAlloc
004123AC 0BC0 or eax, eax ;判断是否分配内存成功
004123AE 75 02 jnz short 004123B2 ;跳了
004123B2 93 xchg eax, ebx ; kernel32.GetProcAddress
004123B3 6A 00 push 0
004123B5 8D85 B52A4000 lea eax, dword ptr [ebp+402AB5]
004123BB 50 push eax
004123BC 56 push esi
004123BD 53 push ebx
004123BE 57 push edi
004123BF FF95 522A4000 call dword ptr [ebp+402A52] ; kernel32.ReadFile
004123C5 8BC3 mov eax, ebx
004123C7 8BCE mov ecx, esi
004123C9 53 push ebx
004123CA 57 push edi
004123CB E8 10000000 call 004123E0 ;进行一些运算 可能是校验
004123D0 8985 42284000 mov dword ptr [ebp+402842], eax
004123D6 5F pop edi
004123D7 5B pop ebx
004123D8 8D85 B1214000 lea eax, dword ptr [ebp+4021B1]
004123DE 50 push eax
004123DF C3 retn
004123F4 53 push ebx ;返回到此
004123F5 FF95 452A4000 call dword ptr [ebp+402A45] ; kernel32.GlobalFree,释放申请的内存
004123FB 96 xchg eax, esi
004123FC 50 push eax
004123FD 57 push edi
004123FE FF95 722A4000 call dword ptr [ebp+402A72] ; kernel32.CloseHandle
00412404 58 pop eax
00412405 8B85 36284000 mov eax, dword ptr [ebp+402836] ; Main.00400000
0041240B BB 01000000 mov ebx, 1
00412410 E8 08000000 call 0041241D ;F7 跟进
0041241D 8BF8 mov edi, eax
0041241F 037F 3C add edi, dword ptr [edi+3C] ;取pe文件头
00412422 8BF7 mov esi, edi ; Main.004000C0
00412424 81C6 F8000000 add esi, 0F8
0041242A 33D2 xor edx, edx
0041242C 813E 72737263 cmp dword ptr [esi], 63727372 ;比较区段名为后面做准备
00412432 75 05 jnz short 00412439 ;跳了
00412439 813E 2E727372 cmp dword ptr [esi], 7273722E ;跳到此处,同样是比较区段
0041243F 75 05 jnz short 00412446 ;跳了
00412446 813E 72656C6F cmp dword ptr [esi], 6F6C6572 ;
0041244C 75 05 jnz short 00412453 ;跳
00412453 813E 2E72656C cmp dword ptr [esi], 6C65722E
00412459 75 05 jnz short 00412460 ;跳
00412460 813E 2E656461 cmp dword ptr [esi], 6164652E
00412466 75 02 jnz short 0041246A ;跳
0041246A 833E 00 cmp dword ptr [esi], 0
0041246D 75 02 jnz short 00412471 ;跳
00412471 837E 14 00 cmp dword ptr [esi+14], 0
00412475 74 06 je short 0041247D ;没跳
00412477 837E 10 00 cmp dword ptr [esi+10], 0
0041247B 75 02 jnz short 0041247F ;跳
0041247F 8136 13088919 xor dword ptr [esi], 19890813
00412485 8176 04 1308891>xor dword ptr [esi+4], 19890813
0041248C 60 pushad
0041248D 8B4E 10 mov ecx, dword ptr [esi+10] ;区段大小放入ecx
00412490 0BDB or ebx, ebx
00412492 /75 0C jnz short 004124A0 ;跳
004124A0 8B76 0C mov esi, dword ptr [esi+C] ;跳到此处
004124A3 03F0 add esi, eax ; Main.00400000
004124A5 E8 02000000 call 004124AC
004124AC 8BFE mov edi, esi ; Main.00401000
004124AE AC lods byte ptr [esi]
004124AF FEC8 dec al
004124B1 FEC8 dec al
004124B3 C0C8 F4 ror al, 0F4
004124B6 EB 01 jmp short 004124B9
004124B9 /EB 01 jmp short 004124BC
004124BC 2AC1 sub al, cl
004124BE C0C0 D8 rol al, 0D8
004124C1 34 21 xor al, 21
004124C3 2AC1 sub al, cl
004124C5 EB 01 jmp short 004124C8
004124C8 /EB 01 jmp short 004124CB
004124CB FEC8 dec al
004124CD 90 nop
004124CE FEC8 dec al
004124D0 C0C0 C9 rol al, 0C9
004124D3 02C1 add al, cl
004124D5 /EB 01 jmp short 004124D8
004124D8 04 13 add al, 13
004124DA /EB 01 jmp short 004124DD
004124DF AA stos byte ptr es:[edi]
004124E0 ^\E2 CC loopd short 004124AE ;对00401000开始大小为2000的部分进行解密
004124E2 C3 retn ;F4
004124AA /EB 37 jmp short 004124E3 ;返回到这儿
004124E3 61 popad ;跳到此处
004124E4 83C6 28 add esi, 28 ;此时esi指向.txt 然后是 .rsrc
004124E7 42 inc edx
004124E8 66:3B57 06 cmp dx, word ptr [edi+6] ;edi+6的内容为3
004124EC ^ 0F85 3AFFFFFF jnz 0041242C
004124F2 C3 retn ;在此F4
00412415 8D85 B0224000 lea eax, dword ptr [ebp+4022B0] ;返回到这儿
0041241B 50 push eax
0041241C C3 retn
004124F3 8B85 36284000 mov eax, dword ptr [ebp+402836] ; Main.00400000 返回到这儿
004124F9 0385 3A284000 add eax, dword ptr [ebp+40283A] ; eax的值就是oep
004124FF EB 02 jmp short 00412503
00412503 C1C8 07 ror eax, 7
00412506 894424 1C mov dword ptr [esp+1C], eax
0041250A 8BBD 36284000 mov edi, dword ptr [ebp+402836]
00412510 037F 3C add edi, dword ptr [edi+3C]
00412513 8B9F C0000000 mov ebx, dword ptr [edi+C0]
00412519 83FB 00 cmp ebx, 0
0041251C 74 0F je short 0041252D ;跳了
0041252D 8B85 42284000 mov eax, dword ptr [ebp+402842]
00412533 0BC0 or eax, eax
00412535 74 0D je short 00412544 ;没有跳
00412537 3B85 B12A4000 cmp eax, dword ptr [ebp+402AB1]
0041253D 74 05 je short 00412544 ;跳了
00412544 8DB5 4E284000 lea esi, dword ptr [ebp+40284E]
0041254A F785 3E284000 2>test dword ptr [ebp+40283E], 20
00412554 74 47 je short 0041259D ;没跳
00412556 56 push esi ; Main.00412A91
00412557 8DBD B52A4000 lea edi, dword ptr [ebp+402AB5]
0041255D 33C9 xor ecx, ecx
0041255F EB 17 jmp short 00412578
00412578 837E 04 00 cmp dword ptr [esi+4], 0
0041257C ^ 75 E3 jnz short 00412561
00412561 8B56 04 mov edx, dword ptr [esi+4]
00412564 0395 36284000 add edx, dword ptr [ebp+402836]
0041256A EB 04 jmp short 00412570
0041256C 41 inc ecx
0041256D 83C2 04 add edx, 4
00412570 833A 00 cmp dword ptr [edx], 0
00412573 ^ 75 F7 jnz short 0041256C
00412575 83C6 0C add esi, 0C
00412578 837E 04 00 cmp dword ptr [esi+4], 0
0041257C ^ 75 E3 jnz short 00412561
0041257E 33D2 xor edx, edx
00412580 B8 0D000000 mov eax, 0D
00412585 F7E1 mul ecx
00412587 50 push eax
00412588 6A 00 push 0
0041258A FF95 362A4000 call dword ptr [ebp+402A36] ; kernel32.GlobalAlloc 计算处理输入表所需要的内存大小
00412590 0BC0 or eax, eax
00412592 75 03 jnz short 00412597 ;跳了
00412597 8907 mov dword ptr [edi], eax ;eax存放的是申请的地址起始位置
00412599 8947 04 mov dword ptr [edi+4], eax
0041259C 5E pop esi
0041259D /E9 88010000 jmp 0041272A
0041272A 837E 04 00 cmp dword ptr [esi+4], 0
0041272E ^ 0F85 6EFEFFFF jnz 004125A2 ;跳了
004125A2 8B1E mov ebx, dword ptr [esi] ;rva放入ebx
004125A4 039D 36284000 add ebx, dword ptr [ebp+402836] ;加上400000
004125AA 8BC3 mov eax, ebx
004125AC E8 08000000 call 004125B9 ;F7跟进 函数的作用就是最rva进行解密
『
004125B9 56 push esi ; Main.00412A91
004125BA 57 push edi
004125BB 8BF0 mov esi, eax
004125BD 8BF8 mov edi, eax
004125BF AC lods byte ptr [esi]
004125C0 C0C8 04 ror al, 4
004125C3 AA stos byte ptr es:[edi]
004125C4 803F 00 cmp byte ptr [edi], 0
004125C7 ^ 75 F6 jnz short 004125BF
004125C9 5F pop edi
004125CA 5E pop esi
004125CB C3 retn
』
004125B1 8D85 89234000 lea eax, dword ptr [ebp+402389]
004125B7 50 push eax
004125B8 C3 retn
004125CC 53 push ebx ; Main.004013D2 返回到此 ebx存放的是kernel32.dll
004125CD FF95 C2294000 call dword ptr [ebp+4029C2] ; kernel32.LoadLibraryA
004125D3 85C0 test eax, eax ; kernel32.7C800000
004125D5 0F84 5C010000 je 00412737 ;没有跳
004125DB 50 push eax ; kernel32.7C800000
004125DC F785 3E284000 0>test dword ptr [ebp+40283E], 4
004125E6 74 0E je short 004125F6 ; 没有跳
004125E8 8D85 B3234000 lea eax, dword ptr [ebp+4023B3]
004125EE 50 push eax
004125EF 8BC3 mov eax, ebx
004125F1 /E9 F0030000 jmp 004129E6
004129E6 /EB 04 jmp short 004129EC
004129EC 8038 00 cmp byte ptr [eax], 0
004129EF ^\75 F7 jnz short 004129E8 ;跳了
004129E8 C600 00 mov byte ptr [eax], 0 ;eax存放的是kernel32.dll
004129EB 40 inc eax
004129EC 8038 00 cmp byte ptr [eax], 0
004129EF ^ 75 F7 jnz short 004129E8
004129F1 C3 retn
004125F6 5B pop ebx ; kernel32.7C800000 返回至此
004125F7 8B4E 08 mov ecx, dword ptr [esi+8]
004125FA 0BC9 or ecx, ecx
004125FC 75 03 jnz short 00412601 ;跳了
00412601 038D 36284000 add ecx, dword ptr [ebp+402836] ; Main.00400000
00412607 8B56 04 mov edx, dword ptr [esi+4]
0041260A 0395 36284000 add edx, dword ptr [ebp+402836]
00412610 E9 09010000 jmp 0041271E
0041271E 8339 00 cmp dword ptr [ecx], 0
00412721 ^ 0F85 EEFEFFFF jnz 00412615 ; 跳了
00412615 F701 00000080 test dword ptr [ecx], 80000000
0041261B 75 4B jnz short 00412668 ;没有跳
0041261D 8B01 mov eax, dword ptr [ecx] ;
0041261F 83C0 02 add eax, 2
00412622 0385 36284000 add eax, dword ptr [ebp+402836]
00412628 50 push eax
00412629 E8 8BFFFFFF call 004125B9 ;F8过 对rva进行解密
0041262E 58 pop eax
0041262F 8BF8 mov edi, eax
00412631 52 push edx
00412632 51 push ecx
00412633 50 push eax
00412634 53 push ebx
00412635 FF95 C6294000 call dword ptr [ebp+4029C6] ; kernel32.GetProcAddress 获取函数地址
0041263B 0BC0 or eax, eax ; kernel32.CloseHandle
0041263D 75 07 jnz short 00412646 ;跳了
00412646 59 pop ecx ; Main.00401218
00412647 5A pop edx
00412648 60 pushad
00412649 F785 3E284000 0>test dword ptr [ebp+40283E], 4
00412653 74 0E je short 00412663 ;没有跳
00412655 8D85 20244000 lea eax, dword ptr [ebp+402420]
0041265B 50 push eax
0041265C 8BC7 mov eax, edi
0041265E E9 83030000 jmp 004129E6
004129EC 8038 00 cmp byte ptr [eax], 0
004129EF ^ 75 F7 jnz short 004129E8
00412663 61 popad
00412664 8902 mov dword ptr [edx], eax ;将正确的函数地址放入edx内
00412666 /EB 1D jmp short 00412685
00412685 F785 3E284000 2>test dword ptr [ebp+40283E], 20
0041268F 0F84 83000000 je 00412718 ;没有跳
00412695 /EB 02 jmp short 00412699
00412699 /EB 03 jmp short 0041269E
0041269E 83BD 4A284000 0>cmp dword ptr [ebp+40284A], 0
004126A5 74 1E je short 004126C5 ;没有跳
004126A7 /EB 03 jmp short 004126AC
004126AC 81FB 00000070 cmp ebx, 70000000
004126B2 72 08 jb short 004126BC ;没有跳
004126B4 81FB FFFFFF77 cmp ebx, 77FFFFFF
004126BA 76 1B jbe short 004126D7 ;没有跳
004126BC /EB 03 jmp short 004126C1
004126C1 /EB 55 jmp short 00412718
00412718 83C1 04 add ecx, 4
0041271B 83C2 04 add edx, 4
0041271E 8339 00 cmp dword ptr [ecx], 0
00412721 ^ 0F85 EEFEFFFF jnz 00412615 ;循环处理单个dll
00412727 83C6 0C add esi, 0C
0041272A 837E 04 00 cmp dword ptr [esi+4], 0
0041272E ^ 0F85 6EFEFFFF jnz 004125A2 ;循环处理每个dll
由于00412664处是将正确的函数地址放入到正确的位置 而00412718是循环处理的地方 我们可以知道0041268F 0F84 83000000 je 00412718 只要让它跳转我们就可以
得到完整的输入表 当然如果你想看看输入表是怎样加密的 你可以在0041268F 处没有跳的地方下硬件执行断点, 直到发现跳转就可以发现输入表加密的过程
00412734 33C0 xor eax, eax ;此处按F4
00412736 40 inc eax
00412737 83F8 01 cmp eax, 1
0041273A 74 02 je short 0041273E ;跳了
0041273C 61 popad
0041273D C3 retn
0041273E 60 pushad
0041273F F785 3E284000 1>test dword ptr [ebp+40283E], 10
00412749 74 0D je short 00412758 ;没有跳
0041274B 8B85 36284000 mov eax, dword ptr [ebp+402836]
00412751 0340 3C add eax, dword ptr [eax+3C]
00412754 66:0960 06 or word ptr [eax+6], sp
00412758 61 popad
00412759 60 pushad
0041275A F785 3E284000 0>test dword ptr [ebp+40283E], 2
00412764 74 17 je short 0041277D ;跳了
0041277D 61 popad
0041277E 60 pushad
0041277F 83BD 4A284000 0>cmp dword ptr [ebp+40284A], 0
00412786 74 15 je short 0041279D ;没有跳
00412788 64:FF35 3000000>push dword ptr fs:[30] ;取的peb
0041278F 58 pop eax
00412790 0FB658 02 movzx ebx, byte ptr [eax+2] ;检测调试标志
00412794 0ADB or bl, bl
00412796 74 2E je short 004127C6 ;是否发现调试器 由于隐藏了 所以跳了
004127C6 61 popad
004127C7 8D85 1D1E4000 lea eax, dword ptr [ebp+401E1D] ;模块开始的值放入eax
004127CD B9 AA070000 mov ecx, 7AA ;大小
004127D2 EB 01 jmp short 004127D5
004127D5 E8 06FCFFFF call 004123E0 ;F7跟进 计算一个自校验值
『
004123E0 8BF8 mov edi, eax
004123E2 33C0 xor eax, eax
004123E4 33DB xor ebx, ebx
004123E6 33D2 xor edx, edx
004123E8 8A07 mov al, byte ptr [edi]
004123EA F7E2 mul edx
004123EC 03D8 add ebx, eax
004123EE 42 inc edx
004123EF 47 inc edi
004123F0 ^ E2 F6 loopd short 004123E8
004123F2 93 xchg eax, ebx
004123F3 C3 retn
』
004127DA /EB 01 jmp short 004127DD
004127DD 8B9D 46284000 mov ebx, dword ptr [ebp+402846] ;将开始算出来的自校验值放入ebx
004127E3 33C3 xor eax, ebx ;比较是否有改动
004127E5 74 08 je short 004127EF ;这里我们应该改标志位让它强行跳转
004127EF 8DBD C7254000 lea edi, dword ptr [ebp+4025C7] ;来到此处
004127F5 8BF7 mov esi, edi
004127F7 B9 DC010000 mov ecx, 1DC
004127FC 33DB xor ebx, ebx
004127FE AC lods byte ptr [esi]
004127FF 34 58 xor al, 58
00412801 2AC3 sub al, bl
00412803 C0C0 02 rol al, 2
00412806 AA stos byte ptr es:[edi]
00412807 43 inc ebx
00412808 ^ E2 F4 loopd short 004127FE 对从00412808开始的字节进行动态解码
0041280A ^\EB 99 jmp short 004127A5 ;在此行F4
0041280F 60 pushad ;跳到此处
00412810 F785 3E284000 2>test dword ptr [ebp+40283E], 20
0041281A EB 02 jmp short 0041281E
0041281E /0F84 DA000000 je 004128FE ;没有跳
00412824 /EB 02 jmp short 00412828
00412828 /EB 02 jmp short 0041282C
0041282C 8B4424 3C mov eax, dword ptr [esp+3C]
00412830 /EB 02 jmp short 00412834
00412834 C1C0 07 rol eax, 7 ;算出oep 放入eax
00412837 8BF0 mov esi, eax ; Main.00402E45
00412839 66:8B06 mov ax, word ptr [esi] ;将oep开始的字节放入ax中 等待操作
0041283C 3C 50 cmp al, 50
0041283E 72 07 jb short 00412847
00412840 3C 57 cmp al, 57
00412842 77 03 ja short 00412847
00412844 46 inc esi
00412845 ^ EB F2 jmp short 00412839
00412847 3C 6A cmp al, 6A
00412849 75 04 jnz short 0041284F
0041284B 46 inc esi
0041284C 46 inc esi
0041284D ^ EB EA jmp short 00412839
0041284F 3C 68 cmp al, 68
00412851 75 05 jnz short 00412858
00412853 83C6 05 add esi, 5
00412856 ^ EB E1 jmp short 00412839
00412858 3C A1 cmp al, 0A1
0041285A 75 05 jnz short 00412861
0041285C 83C6 05 add esi, 5
0041285F ^ EB D8 jmp short 00412839
00412861 66:3D 2BD2 cmp ax, 0D22B
00412865 75 04 jnz short 0041286B
00412867 46 inc esi
00412868 46 inc esi
00412869 ^ EB CE jmp short 00412839
0041286B 66:3D FF74 cmp ax, 74FF
0041286F 75 05 jnz short 00412876
00412871 83C6 04 add esi, 4
00412874 ^ EB C3 jmp short 00412839
00412876 66:3D 8BEC cmp ax, 0EC8B
0041287A 75 04 jnz short 00412880
0041287C 46 inc esi
0041287D 46 inc esi
0041287E ^ EB B9 jmp short 00412839
00412880 3C E8 cmp al, 0E8
00412882 75 05 jnz short 00412889
00412884 83C6 05 add esi, 5
00412887 ^ EB B0 jmp short 00412839
00412889 66:3D 64FF cmp ax, 0FF64
0041288D 75 1A jnz short 004128A9
0041288F 807E 02 32 cmp byte ptr [esi+2], 32
00412893 75 05 jnz short 0041289A
00412895 83C6 03 add esi, 3
00412898 EB 0D jmp short 004128A7
0041289A 807E 02 35 cmp byte ptr [esi+2], 35
0041289E 75 05 jnz short 004128A5
004128A0 83C6 07 add esi, 7
004128A3 EB 02 jmp short 004128A7
004128A5 EB 3F jmp short 004128E6
004128A7 ^ EB 90 jmp short 00412839
004128A9 66:3D 6489 cmp ax, 8964
004128AD 75 1D jnz short 004128CC
004128AF 807E 02 22 cmp byte ptr [esi+2], 22
004128B3 75 05 jnz short 004128BA
004128B5 83C6 03 add esi, 3
004128B8 EB 0D jmp short 004128C7
004128BA 807E 02 25 cmp byte ptr [esi+2], 25
004128BE 75 05 jnz short 004128C5
004128C0 83C6 07 add esi, 7
004128C3 EB 02 jmp short 004128C7
004128C5 EB 1F jmp short 004128E6
004128C7 ^ E9 6DFFFFFF jmp 00412839
004128CC 66:3D 83EC cmp ax, 0EC83
004128D0 75 08 jnz short 004128DA
004128D2 83C6 03 add esi, 3
004128D5 ^ E9 5FFFFFFF jmp 00412839
004128DA 3C A3 cmp al, 0A3
004128DC 75 08 jnz short 004128E6
004128DE 83C6 05 add esi, 5
004128E1 ^ E9 53FFFFFF jmp 00412839
004128E6 3C CC cmp al, 0CC
004128E8 75 06 jnz short 004128F0
004128EA 46 inc esi
004128EB ^ E9 49FFFFFF jmp 00412839 ;以上代码就是找到程序开始的call 然后对其进行处理
004128F0 66:3D FF25 cmp ax, 25FF ;直接在此F4
004128F4 75 08 jnz short 004128FE
004128F6 8D85 AF274000 lea eax, dword ptr [ebp+4027AF]
004128FC FFD0 call eax ;F7跟进
『
004129F2 /EB 03 jmp short 004129F7
004129F7 /EB 16 jmp short 00412A0F
00412A0F 66:813E FF25 cmp word ptr [esi], 25FF
00412A14 ^\74 E3 je short 004129F9
004129F9 /EB 02 jmp short 004129FD
004129FD 8B46 02 mov eax, dword ptr [esi+2] ; Main.0040129C
00412A00 C606 68 mov byte ptr [esi], 68
00412A03 46 inc esi
00412A04 8B00 mov eax, dword ptr [eax]
00412A06 8906 mov dword ptr [esi], eax
00412A08 83C6 04 add esi, 4
00412A0B C606 C3 mov byte ptr [esi], 0C3
00412A0E 46 inc esi
00412A0F 66:813E FF25 cmp word ptr [esi], 25FF
00412A14 ^ 74 E3 je short 004129F9
00412A16 C3 retn
』
004128FE 61 popad
004128FF 8D85 872A4000 lea eax, dword ptr [ebp+402A87]
00412905 50 push eax
00412906 FFB5 D7294000 push dword ptr [ebp+4029D7]
0041290C FF95 C6294000 call dword ptr [ebp+4029C6] ; kernel32.GetProcAddress 获取isdubuggerpresent的地址
00412912 0BC0 or eax, eax ; kernel32.IsDebuggerPresent
00412914 74 08 je short 0041291E
00412916 FFD0 call eax ; kernel32.IsDebuggerPresent
00412918 0BC0 or eax, eax
0041291A 74 02 je short 0041291E ;由于我们隐藏了所以此处跳转
0041291E F785 3E284000 0>test dword ptr [ebp+40283E], 1
00412928 74 4F je short 00412979 ;没有跳
0041292A 8DB5 B6294000 lea esi, dword ptr [ebp+4029B6]
00412930 8D85 11274000 lea eax, dword ptr [ebp+402711]
00412936 8946 08 mov dword ptr [esi+8], eax ; Main.00412954
00412939 33DB xor ebx, ebx
0041293B 8D85 05284000 lea eax, dword ptr [ebp+402805]
00412941 50 push eax
00412942 64:FF33 push dword ptr fs:[ebx]
00412945 64:8923 mov dword ptr fs:[ebx], esp
00412948 8BFD mov edi, ebp
0041294A B8 00440000 mov eax, 4400
0041294F /EB 01 jmp short 00412952
00412952 CD 68 int 68
此时在转存窗口中跟随第二句 下内存访问断点 shift +F9
00412A48 55 push ebp ;断在此处
00412A49 8BEC mov ebp, esp
00412A4B 57 push edi
00412A4C 8B45 10 mov eax, dword ptr [ebp+10]
00412A4F 8BB8 9C000000 mov edi, dword ptr [eax+9C]
00412A55 FFB7 BE294000 push dword ptr [edi+4029BE]
00412A5B 8F80 B8000000 pop dword ptr [eax+B8] ;00412954 在此下载硬件执行断点 其实 也可以直接将int68 nop 效果是一样的
00412A61 89B8 B4000000 mov dword ptr [eax+B4], edi
00412A67 C780 9C000000 0>mov dword ptr [eax+9C], 0
00412A71 B8 00000000 mov eax, 0
00412A76 5F pop edi
00412A77 C9 leave
00412A78 C3 retn
00412954 33DB xor ebx,ebx ;在这里我直接将int68 nop掉了 来到此处
00412956 64:8F03 pop dword ptr fs:[ebx]
00412959 83C4 04 add esp,4
0041295C 66:81FF 9712 cmp di,1297
00412961 74 0E je short 00412971
00412963 66:81FF 7712 cmp di,1277
00412968 74 07 je short 00412971
0041296A 66:81FF 3013 cmp di,1330
0041296F 75 08 jnz short 00412979
00412979 32C0 xor al,al
0041297B 8DBD 1D1E4000 lea edi,dword ptr ss:[ebp+401E1D]
00412981 B9 19090000 mov ecx,919
00412986 AA stos byte ptr es:[edi]//清扫战场
00412987 E2 FD loopd short 00412986
00412989 8DBD A3274000 lea edi,dword ptr ss:[ebp+4027A3]
0041298F B9 F6020000 mov ecx,2F6
00412994 AA stos byte ptr es:[edi]
00412995 E2 FD loopd short 00412994
00412997 8B4424 1C mov eax,dword ptr ss:[esp+1C]
0041299B 894424 F0 mov dword ptr ss:[esp-10],eax
0041299F C14424 F0 07 rol dword ptr ss:[esp-10],7
004129A4 61 popad ;[esp-10]=00402E45
004129A5 EB 03 jmp short 004129AA
004129AA FF6424 D0 jmp dword ptr ss:[esp-30] ; Main.00402E45 ;到达oep
至于脱壳方法看雪精华6 已经说的很清楚了
总结:
在这里我想给像我这样的菜鸟们提供一种学习的方法, 大牛们的文章操作都很简练,我们很多时候都不知道为什么这样操作 ,最好的办法就是我们亲自跟一下这个壳 慢慢分析
遇到不懂的地方我们可以看看加密解密和大牛们的文章 不要灰心 不要放弃 任何想成为高手的人都会经历这一步
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创]码海迷踪-简单linux64下小虚拟机 6564
- python八进制字符串的转化 8660
- 各位大牛 下面是什么解压缩算法 5411
- 各位大侠 下面是什么算法 3413
- [求助]求解啊 求解 4616