|
Arm4.xx CopyMeM2 and Debug Blocker
-------------------------------------------------------------------------------- RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR KaGra 自豪之作:Armadillo 4.xx Public Build CopyMeM2 及 Debug Blocker 的脱壳 RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR 其实,如果不是为了 Richardo 的那篇教程的话,我也不会去写这篇教程。在持续几天的翻译之后,他们向我揭示了 Armadillo 那些所谓的保护。因此,非常感谢他写的那些教程。 我用 Armadillo 4.05 Public Build 来保护了一个程序(exe)。我使用的保护选项有 CopyMeM2+Debug Blocker 及 Memory patching protections。这个特性也包括了 Import table elimination,但是在这 个教程中,我将创建出一个有效的脱壳文件,但是没有重建 IAT。这部分会在稍后放出的这篇教程的第二部分完成。 在附带的 zip 文件中,有一个脱壳的文件(未修复 IAT),被保护的文件和一个未保护的文件。我也很清楚,未保护的文件和脱壳文件的唯一不同就是输入表。所以,如果你用OD载入未保护的文件,然后将区 段 405000 粘贴到脱壳文件中的相应的地方的话,脱壳文件在OD中也能很好的运行。当你读完这篇教程后,你也应该能创建出这样一个脱壳文件,唯一没做的也只剩 IAT 重建了。 使用的工具:OD v1.10,LordPE,OllyDump 插件及 HideOlly 插件。我也修改了OD来对抗 OutputDebugStringA 的使用。 我不会对对他的反调试措施做太多的说明,因为你已经修正了OD,还有隐藏OD的插件。 那么,所谓的 CopyMEM 保护,和 debugger blocking 究竟是些什么呢? 当一个被 Armadillo 保护的程序开始执行时,他会创建另一个进程。这个进程被称做子进程,而一开始的那个进程被称做父进程。所以当你在OD中运行他的时候你可以看看进程列表,你会发现有两个同名称但是 ID 却不同的进程。进程列表中那个红色的进程是当前OD正在调试的进程-父进程,黑色的那个则是子进程。 所以,debugger blocking 实际上是欺负OD这种 Ring-3 级的调试器,使其不能直接调试我们需要脱壳的子进程,导致子进程成为我们调试过程中一个独立的运行进程。 那么,在父进程决定创建子进程的时候,会自动给子进程分配内存。父进程会创建一个所有区段几乎与自己完全一样的子进程(因为他们实际上是同一个程序),但有两个区段不一样:Code section。当然 IAT section 也不会一样,因为父进程填充的是00,而在子进程中填充的是重定位的调用。 一开始的时候,子进程的代码段全是00。当子进程从 OEP 开始运行时,会引发一个异常并被父进程捕获,原因就象我说的那样,内存中代码段中全是00。父进程这时候意识到该把前 1000h 的字节复制给子进程了。所以在这个起始点,OEP 会位于父进程填充的原始的解密过的代码所在的内存区域中。父进程也将复制一段针对这段内存的加密解密程序到子进程中,所以当子进程的 EIP 超出这段内存区域时,这部分代码就会被重新加密。然后,父进程在复制下一段原始的 1000h 的字节给子进程,并且继续这样直到子进程的代码段都被填充过。现在子进程已经可以独立运行了。所以运行完第一块 1000h 的字节后(OEP 所在的那一块),其他部分的子进程还是被加密的。当 EIP 超出这段范围时(某个调用或跳转或仅仅是代码的执行),子进程将加密这 1000h 的字节块,然后解密需要的部分,EIP 所在的那一段。这样的过程会一直持续到子进程终止运行。因此,根据这种持续发生的内存复制,这种再版的保护被称为 CP2 或是 Copymem2。 Debug blocker 和 CP2 防止了子进程被调试器附加,被反汇编还有被脱壳。 现在是该做些什么东西的时候了。而我们要做的就是创建一个脱壳文件,然后在下篇教程中修复 IAT。 我们用OD载入被保护的文件,你会停在这个 EP 处: 00447000 > 60 PUSHAD 00447001 E8 00000000 CALL muna.00447006 00447006 5D POP EBP 00447007 50 PUSH EAX 00447008 51 PUSH ECX 00447009 0FCA BSWAP EDX 0044700B F7D2 NOT EDX 0044700D 9C PUSHFD 还记得我告诉过你父进程会复制包含 OEP 在内的 1000h 的字节给子进程吗?那么我们来看看他们是怎么被复制的。他们的复制是通过调用 API WriteProcessMemory 来完成的。在这个 API 上下个断点,但是不要下在第一个指令上,因为 Armadillo 会检测这些代码部分的软件断点(每个 API 调用的第一个指令)。所以,我们在OD中右击 code section 然后找出所有的 API 名称,下面是这个 API 的开始点: 77E61A94 > 55 PUSH EBP 77E61A95 8BEC MOV EBP,ESP 77E61A97 51 PUSH ECX 77E61A98 51 PUSH ECX 77E61A99 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C] 77E61A9C 53 PUSH EBX 77E61A9D 8B5D 14 MOV EBX,DWORD PTR SS:[EBP+14] 77E61AA0 56 PUSH ESI 77E61AA1 8B35 B012E677 MOV ESI,DWORD PTR DS:[<&ntdll.NtProtectV>; ntdll.ZwProtectVirtualMemory 77E61AA7 57 PUSH EDI 77E61AA8 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+8] 77E61AAB 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 77E61AAE 8D45 14 LEA EAX,DWORD PTR SS:[EBP+14] 现在,双击第二个 PUSH ECX 指令来下个断点。然后,忽略所有异常(并且在最后的复选框中要填入全部的范围)用 Shift+F9 开始执行。OD会停在我们下断点的地方的(如果出现什么异常的话,按 Shift+F9 通过): 77E61A94 > 55 PUSH EBP 77E61A95 8BEC MOV EBP,ESP 77E61A97 51 PUSH ECX 77E61A98 51 PUSH ECX <------- 断在了这里 77E61A99 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C] 77E61A9C 53 PUSH EBX 77E61A9D 8B5D 14 MOV EBX,DWORD PTR SS:[EBP+14] 77E61AA0 56 PUSH ESI 77E61AA1 8B35 B012E677 MOV ESI,DWORD PTR DS:[<&ntdll.NtProtectV>; ntdll.ZwProtectVirtualMemory 77E61AA7 57 PUSH EDI 77E61AA8 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+8] 在堆栈中,我们可以看到 0012B988 0000010C 0012B98C /0012BC88 0012B990 |00426E05 返回到 muna.00426E05 来自 kernel32.WriteProcessMemory 0012B994 |0000010C 0012B998 |00447000 OFFSET muna.<ModuleEntryPoint> 0012B99C |0012BC80 <-这里 0012B9A0 |00000002 <-这里 0012B9A4 |0012BC84 0012B9A8 |0012D220 0012B9AC |00002710 0012B9B0 |004327C3 muna.004327C3 看,现在已经有 2 个字节 (0012B9A0 ) 被从 0012BC80 复制到了子进程中的 00447000 (0012B998)。不过着并不是我们需要的,我们需要的是 1000h 个字节的复制。使用 F9 继续(不是 shift)两次,我们再次停在了这里,再看看堆栈会看见这些: 0012BB30 |004268D7 返回到 muna.004268D7 来自 kernel32.WriteProcessMemory 0012BB34 |0000009C 0012BB38 |00401000 muna.00401000 0012BB3C |00992158 0012BB40 |00001000 <-这里 不错,这就是复制到子进程代码段中的第一个块。父进程从 00992158 (他自己的内存段,我们可以在OD中看到)复制里了 1000h 的字节到子进程的 401000 处(这个我们在当前的OD中看不见)。所以,401000<OEP<402000。 再接下来的三次 F9 后我们也看见了这些,按次序列出: 第2次: 0012BB30 |004268D7 返回到 muna.004268D7 来自 kernel32.WriteProcessMemory 0012BB34 |0000009C 0012BB38 |00403000 muna.00403000 0012BB3C |00992158 0012BB40 |00001000 第3次: 0012BB30 |004268D7 返回到 muna.004268D7 来自 kernel32.WriteProcessMemory 0012BB34 |0000009C 0012BB38 |00402000 muna.00402000 0012BB3C |00992158 0012BB40 |00001000 第4次: 0012BB30 |004268D7 返回到 muna.004268D7 来自 kernel32.WriteProcessMemory 0012BB34 |0000009C 0012BB38 |00404000 muna.00404000 0012BB3C |00992158 0012BB40 |00001000 在这之后父进程就不再复制什么东西到子进程中了,他的任务完成了。如果你现在再按 F9 的话,子进程就会运行,而OD此时就显得爱莫能助,因为当前被调试的进程并不是子进程。 在那时,子进程的内存区域 401000-402000 是已解密的,其他几个部分也是的(记得他复制了三次吗?)。 所以,我们现在会想到先去脱下那四个已解密的部分,而且也只能在OD停在我们设置的断点的时候来做。那么按上面的步骤重来一次吧。当我们停在第一次复制 1000h 的地方的时候: 0012BB30 |004268D7 返回到 muna.004268D7 来自 kernel32.WriteProcessMemory 0012BB34 |0000009C 0012BB38 |00401000 muna.00401000 0012BB3C |00992158 0012BB40 |00001000 跳转到 992158 你会看见这些: 00992158 55 PUSH EBP 00992159 8BEC MOV EBP,ESP 0099215B 51 PUSH ECX 0099215C 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 0099215F 53 PUSH EBX 00992160 56 PUSH ESI 00992161 57 PUSH EDI 00992162 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 00992165 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0 0099216C 60 PUSHAD 0099216D 66:9C PUSHFW 0099216F 33C9 XOR ECX,ECX 00992171 33C0 XOR EAX,EAX 等等 有用的部分是下面的 1000h 的字节,到 993157 为止(993157 就是我们需要的最后一个字节)。那么,我们用鼠标选中这部分代码。然后打开另外一个OD,并载入被保护的文件,把刚才复制的字节粘贴到内存段 401000 中相同的地方,然后保存它。这样我们就有了 1000h 的字节。 对下面四部分也这样做。所以,我们现在有了从 401000 到 405000 之间的正确的代码。他的大小是 4000h 的字节。 那么现在我们来找 OEP。前面我们得知 401000<OEP<402000。但是你需要知道的是他们是在 EIP 不在他们所在的位置时才被完成的。我们可以在列表中看见父进程还保留着那些无效的 EIP 值,他们是父进程向子进程复制数据的引发器。 现在,我们重来并在 WaitForDebugEvent 上下个断点,但是同样不要下在第一条指令上。我们先来看看这个 API: 77EAF13C > 55 PUSH EBP 77EAF13D 8BEC MOV EBP,ESP 77EAF13F 83EC 68 SUB ESP,68 77EAF142 56 PUSH ESI 77EAF143 FF75 0C PUSH DWORD PTR SS:[EBP+C] 77EAF146 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8] 77EAF149 50 PUSH EAX 77EAF14A E8 5BB1FCFF CALL kernel32.77E7A2AA 77EAF14F 8BF0 MOV ESI,EAX 我们在 PUSH DWORD PTR SS:[EBP+C] 指令上设断点。还有不要忘了在 WriteProcessMemory 上设断点。运行,它会停在 WriteProcessMemory,不过我们继续,直到他停在了 WaitForDebugEvent。在堆栈中找找你会发现: 0012BC90 |0042293F 返回到 muna.0042293F 来自 kernel32.WaitForDebugEvent 0012BC94 |0012CD68 <---- 看见这个了? 0012BC98 |000003E8 这里是保留那些引发复制的 EIP 值的地方,是在 0012CD68。那么我们在数据窗口中追随他: 0012CD68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0012CD78 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0012CD88 3E 4B F5 77 C8 CD 12 00 9C 00 13 00 3E 4B F5 77 >K貅韧.?.>K貅 0012CD98 D4 CD 12 00 9C 00 13 00 02 00 00 00 8C 00 13 00 酝.?....?. 0012CDA8 00 00 13 00 EC CD 12 00 70 4D F5 77 D4 CD 12 00 ...焱.pM貅酝. 0012CDB8 3E 4B F5 77 F8 CD 12 00 08 06 13 00 70 CE 12 00 >K貅?..p?. 0012CDC8 01 05 13 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. 现在我们删除 WaitForDebugEvent 上的断点,并且不要碰数据窗口,这样你就能继续看见 0012CD68 处的数据的变化了。继续执行,然后OD会暂停在第一次 1000h 内存块的复制的时候(到 401000)。现在你再看看数据窗口你会看见: 0012CD68 01 00 00 00 B8 0F 00 00 C0 0F 00 00 01 00 00 80 ...?..?....? 0012CD78 00 00 00 00 00 00 00 00 16 14 40 00 02 00 00 00 ........@.... 0012CD88 00 00 00 00 16 14 40 00 16 14 40 00 00 00 00 00 ....@.@..... 0012CD98 01 E3 55 E1 00 00 00 00 18 3D DA F1 00 00 00 00 阏?...=隈.... 0012CDA8 13 00 00 00 DA 0E 51 00 64 3D DA F1 5E CC 4D 80 ...?Q.d=隈^掏? 0012CDB8 00 00 00 00 16 14 40 00 01 00 00 00 01 00 00 00 ....@....... 0012CDC8 01 05 13 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. 在这么多的数据中介于 401000 到 402000 之间的好象也只有 16 14 40 00 了,他就是引发第一次 1000h 的字节的复制的第一个无效的 EIP,那么反而言之(00401416)就是 OEP! 很好,让 401416 作为你前面保存的正确的代码的可执行文件的新的 OEP。LordPE 就可以完成。 现在,CP2 已经失效了。我们已经把父进程从子进程中去除,因为内存中的所有区段都只对子进程有效,对父进程则无效。父进程的数据段、代码段和原始输入表所应在的输入表段全是00。这个可以很容易的知道。例如,跳转到 401000 你会看见这个: 00401000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00401010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00401020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00401030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00401040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00401050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 跳转到数据段 406000 你会看见这个: 00406000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 跳转到输入表段 405000 你会看见这个: 00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00405070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 所以在OD中重新载入被保护的文件。仅设置在 WriteProcessMemory 上的断点。运行他后中断在第一次 1000h 的字节的复制,转到要复制的字节的来源的地方: 00992158 55 PUSH EBP 00992159 8BEC MOV EBP,ESP 0099215B 51 PUSH ECX 0099215C 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 0099215F 53 PUSH EBX 00992160 56 PUSH ESI 00992161 57 PUSH EDI 00992162 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 00992165 C745 08 00000000 MOV DWORD PTR SS:[EBP+8],0 0099216C 60 PUSHAD 0099216D 66:9C PUSHFW 0099216F 33C9 XOR ECX,ECX 00992171 33C0 XOR EAX,EAX 我们现在要做的是通过把 OEP 处的指令改为 JMP EIP,来解除子进程对父进程的依赖,所以要让他无限死循环。我们去要复制的 OEP 所在的地方(00401416h-00401000h+00992158h=0099256E): 0099256E 55 PUSH EBP 0099256F 8BEC MOV EBP,ESP 00992571 6A FF PUSH -1 00992573 68 E0504000 PUSH 4050E0 00992578 68 0C204000 PUSH 40200C 0099257D 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 00992583 50 PUSH EAX 00992584 64:8925 00000000 MOV DWORD PTR FS:[0],ESP 把 0099256E-0099256F 之间的字节从 55h,8Bh 改为 EBh,FEh后,我们按 Ctrl+F9 返回程序领空,这里: 004268D7 85C0 TEST EAX,EAX 004268D9 75 4B JNZ SHORT muna.00426926 004268DB 50 PUSH EAX 004268DC F7D0 NOT EAX 004268DE 0FC8 BSWAP EAX 004268E0 58 POP EAX 004268E1 73 00 JNB SHORT muna.004268E3 现在去进程列表中记下子进程的 ID(黑色的那个)。然后再在你的OD中找到 DebugActiveProcessStop API 的地址,并在 004268D7 写下这些代码: 004268D7 68 500C0000 PUSH 0C50 <--------------------------------- 这个可能与你的不同(译者:这东西可能是父进程的PID) 004268DC E8 5289A877 CALL kernel32.DebugActiveProcessStop 然后按 F8 单步执行两次。OD会崩溃,这时请不要关闭这个OD。暂时不要管那个崩溃信息的窗口,开启一个新的OD去附加子进程,然后你会停在这里: 77F767CE C3 RETN 77F767CF > CC INT3 77F767D0 C3 RETN 77F767D1 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] 77F767D5 CC INT3 77F767D6 C2 0400 RETN 4 现在按下错误消息窗口中的 不发送 按钮来关闭前一个OD。现在父进程挂了,但子进程在新的OD中留了下来。 现在在新的OD中(以后我就直接称他为OD,因为现在只有一个OD了),按下 "M" 键来看看子进程的内存映像。我们可以看见现在子进程的数据段和输入表段都有了数据,不象父进程那样全是00了: 00405000 90 64 A0 00 A5 8E A0 00 5A 8E A0 00 51 E3 E7 77 ????Z?.Q沌w 00405010 86 66 A0 00 6B 90 E6 77 95 D9 E7 77 F8 5C E7 77 ??k?w?琪?琪 00405020 C8 E0 E7 77 54 C9 E6 77 7E DE E7 77 31 A0 E7 77 揉琪T涉w~掮w1_琪 00405030 FC A7 E7 77 ED 95 E7 77 0C 16 E6 77 68 5A E7 77 ?琪?琪.骥hZ琪 00405040 7E 17 E6 77 43 99 A0 00 37 99 A0 00 7C 68 A0 00 ~骥C?.7?.|h? 00405050 35 69 A0 00 B9 E6 E7 77 C0 30 E9 77 A9 AD E7 77 5i?规琪?轺┉琪 00405060 42 75 E9 77 95 E5 E7 77 49 A9 E7 77 D9 57 E7 77 Bu轺?琪I╃w僮琪 00405070 A7 4F A0 00 80 5B A0 00 94 E4 E7 77 77 79 A0 00 ?????琪wy? 00405080 16 89 E7 77 D2 E2 E7 77 CB 15 E8 77 6B 15 F5 77 ?w意琪?梓k貅 等等 00406000 00 00 00 00 00 00 00 00 00 00 00 00 D5 2B 40 00 ............?@. 00406010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00406030 50 6C 65 61 73 65 20 54 72 79 20 41 67 61 69 6E Please Try Again 00406040 21 20 3A 28 00 00 00 00 42 61 64 20 42 6F 79 21 ! :(....Bad Boy! 00406050 00 00 00 00 43 6F 6E 67 72 61 74 75 6C 61 74 69 ....Congratulati 00406060 6F 6E 73 2E 2E 2E 20 79 6F 75 27 72 65 20 67 6F ons... you're go 00406070 6F 64 20 69 6E 20 72 65 76 65 72 73 69 6E 67 0A od in reversing. 00406080 0D 50 6C 65 61 73 65 20 4B 65 79 67 65 6E 20 49 .Please Keygen I 等等 现在我们去 OEP=401416 你会看见: 00401416 -EB FE JMP SHORT muna.00401416 00401418 EC IN AL,DX ; I/O 命令 00401419 6A FF PUSH -1 0040141B 68 E0504000 PUSH muna.004050E0 00401420 68 0C204000 PUSH muna.0040200C 00401425 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 0040142B 50 PUSH EAX 0040142C 64:8925 00000000 MOV DWORD PTR FS:[0],ESP 00401433 83EC 58 SUB ESP,58 设置 EIP=OEP=00401416h. 恩,记得我们设的那个无限循环吗?不过不要修改他,我们过会用我们前面保存的正确的代码中恢复他。 如果你现在想脱壳的话,你会发现困难重重,因为你看下内存就会知道,现在你对他们只有读取的权利: 内存映像 地址 大小 所有者 区段 包含 类型 访问 初始访问 映射为 00400000 00001000 muna Imag R RWE 00401000 00004000 muna .text Imag R RWE 00405000 00001000 muna .rdata Imag R RWE 00406000 00001000 muna .data Imag R RWE 00407000 00040000 muna .text1 code Imag R RWE 00447000 00010000 muna .adata SFX Imag R RWE 00457000 00020000 muna .data1 data,imports Imag R RWE 00477000 00030000 muna .pdata Imag R RWE 004A7000 00001000 muna .rsrc resources Imag R RWE 所以,在每个区段上(包括 400000)右击并设置为完全访问。所有的区段都是 RWE 即为 读取、写入、执行。 再试着脱一次看看,可能还是不行。因为 PE header 被檫除了。所以打开一个新的OD,重新载入被保护的文件,然后把他的 00400000 段复制过来。 现在用OD的插件来脱吧,不要选 IAT 修复。然后用一个新的OD载入他,并把我们的那个正确的文件的 401000-405000 处的代码复制过来。我猜你现在应该还记得我们是在哪里处理 CP2 的吧? 现在唯一要修复的就是 IAT 了,虽然这个脱壳文件也能运行的很好。不信? 那好,载入那个未加壳的文件,把 405000 段中的所有东西都复制到脱壳文件的 405000 段中。试着运行一下,看见了吗?他运行的很好。 好了下一部分(如果有的话),我来讲解 IAT 的重建... =======> 仅感谢 Richardo 和他的教程,因为没有其他的帮助 <======== 不过希腊语和西班牙语还是有些相同的 |
|
[求助]一些汇编语句的用途
谢谢zzsx |
|
[求助]一些汇编语句的用途
谢谢loveboom,jianlizhao,那么PUSHFW的作用呢?还有可以说一下在哪本书上吗?有下载地址就更好了。 |
|
|
|
[求助]移除SafeDisc 2.90.40
可是看起来我只差那么一点点了。 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值