【文章标题】: 新手补给之DBPE
【文章作者】: rocktx
【软件名称】: 雪狐提醒簿 v3.0beta1
【软件大小】: 2.74MB
【下载地址】: 狗狗一下
【加壳方式】: DBPE 2.33
【编写语言】: Delphi
【使用工具】: Ollydbg、LordPE、ImportRec
【操作平台】: Win2K/XP SP2
【软件介绍】: 老版本就不作介绍了
【作者声明】: 只为学习,失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】

  一直没碰到过幻影的壳,今天终于让我给逮住了,也算是补补课吧,新手万一也碰到了,可以拿来主义一下!
  高手们只管超光速飞过...
  
  幻影DBPE v2.33 加壳程序的入口特征:
  
  008C9000 R> /EB 20               jmp short RemindBo.008C9022
  008C9002    |0000                add byte ptr ds:[eax],al
  008C9004    |40                  inc eax
  008C9005    |0000                add byte ptr ds:[eax],al
  008C9007    |0040 00             add byte ptr ds:[eax],al
  008C900A    |0000                add byte ptr ds:[eax],al
  008C900C    |0000                add byte ptr ds:[eax],al
  008C900E    |0000                add byte ptr ds:[eax],al
  008C9010    |0090 4C000B00       add byte ptr ds:[eax+B004C],dl
  008C9016    |0000                add byte ptr ds:[eax],al
  008C9018    |0230                add dh,byte ptr ds:[eax]
  008C901A    |0000                add byte ptr ds:[eax],al
  008C901C    |0000                add byte ptr ds:[eax],al
  008C901E    |0000                add byte ptr ds:[eax],al
  008C9020    |0000                add byte ptr ds:[eax],al
  008C9022    \9C                  pushfd
  008C9023     55                  push ebp
  008C9024     57                  push edi
  008C9025     56                  push esi
  008C9026     52                  push edx
  008C9027     51                  push ecx
  008C9028     53                  push ebx
  008C9029     9C                  pushfd
  008C902A     E8 00000000         call RemindBo.008C902F
  
  往下F7单步跟踪会发现两个函数调用 VirtualAlloc、VirtualFree;
  如果用断点 bp VirtualAlloc 跟踪,运行两次就挂了,这是DBPE壳的AntiDebug在作祟;
  主要是通过修改IDT(Interrupt Descriptor Table 中断向量表)来阻止调试,表现为:
  1、OD重新载入加壳程序后,无法停在入口,程序直接跑飞;
  2、严重一点,直接重启计算机;
  3、再严重一点,直接蓝屏
  4、再再严重一点,首先(同时省去286字...)
  
  对抗DBPE的步骤(前提是曾经运行过幻影加壳的程序):
  1、用Trial-Reset将DBPE的注册表信息清除(一般没什么东西);
  2、加壳程序运行后,会在c:\windows\system32生成cdcd.sys文件,并注册一个叫做Cdsys的服务;
  这里要用Wsyscheck、Syscheck2等高级安全工具,停止并删除该服务以及cdcd.sys文件;
  3、如果软件过期,可能会影响脱壳,所以最好先修改系统时间;
  4、重启计算机,用Xidt.exe保存当前的idt;
  5、每次调试DBPE加壳的程序时,如果出错(也可能不明显),就要用Xidt.exe恢复保存的idt;
  
  废话不多,开始脱壳:
  
  1、寻找OEP
  
  下断点 he VirtualAlloc,Shift+F9三次,查看堆栈:
  0013FF94   008E6234  /CALL 到 VirtualAlloc 来自 RemindBo.008E622E
  0013FF98   7FF60000  |Address = 7FF60000                              ;注意这个地址
  0013FF9C   0003078D  |Size = 3078D (198541.)
  0013FFA0   00101000  |AllocationType = MEM_COMMIT|MEM_TOP_DOWN
  0013FFA4   00000040  \Protect = PAGE_EXECUTE_READWRITE
  
  DBPE壳代码的地址一般在7F打头的高位区段,这里申请的是7FF60000;
  然后数据窗口跟随寄存器窗口中ESP的地址,下WORD硬件访问断点,Shift+F9两次后,来到壳代码领空:
  
  7FF7D504     83C4 04         add esp,4
  7FF7D507     EB 02           jmp short 7FF7D50B
  7FF7D509     99              cdq
  7FF7D50A     EB FF           jmp short 7FF7D50B
  7FF7D50C     0C 24           or al,24
  7FF7D50E     71 01           jno short 7FF7D511
  7FF7D510     E8 79E07A01     call 8172B58E
  7FF7D515   ^ 75 83           jnz short 7FF7D49A
  
  查找命令jmp eax,发现有两个,选择当前地址以后的,来到
  
  7FF8AACB     6A 00           push 0
  7FF8AACD     FF96 EA664300   call dword ptr ds:[esi+4366EA]
  7FF8AAD3     61              popad
  7FF8AAD4     58              pop eax                                  ;OEP地址pop到eax
  7FF8AAD5     83F8 FF         cmp eax,-1
  7FF8AAD8     75 05           jnz short 7FF8AADF
  7FF8AADA     33C0            xor eax,eax
  7FF8AADC     C2 0C00         retn 0C
  7FF8AADF     FFE0            jmp eax                                  ;这里跳到OEP
  
  在jmp eax 处下内存访问断点,F9运行后来到OEP:
  
  00693770     55              push ebp
  00693771     8BEC            mov ebp,esp
  00693773     83C4 DC         add esp,-24
  00693776     33C0            xor eax,eax
  00693778     8945 DC         mov dword ptr ss:[ebp-24],eax
  0069377B     B8 B02D6900     mov eax,RemindBo.00692DB0
  00693780     E8 AB41D7FF     call RemindBo.00407930
  00693785     33C0            xor eax,eax
  00693787     55              push ebp
  00693788     68 07396900     push RemindBo.00693907
  0069378D     64:FF30         push dword ptr fs:[eax]
  00693790     64:8920         mov dword ptr fs:[eax],esp
  
  
  2、处理IAT
  
  右键-查找-所有模块间的调用,发现有很多IAT跳转跑到壳里去了:
  
  0040143C   - FF25 49E0F87F   jmp dword ptr ds:[7FF8E049]
  00401442     8BC0            mov eax,eax
  00401444   - FF25 4DE0F87F   jmp dword ptr ds:[7FF8E04D]
  0040144A     8BC0            mov eax,eax
  0040144C   - FF25 51E0F87F   jmp dword ptr ds:[7FF8E051]
  00401452     8BC0            mov eax,eax
  00401454   - FF25 55E0F87F   jmp dword ptr ds:[7FF8E055]
  0040145A     8BC0            mov eax,eax
  0040145C   - FF25 59E0F87F   jmp dword ptr ds:[7FF8E059]
  00401462     8BC0            mov eax,eax
  00401464   - FF25 5DE0F87F   jmp dword ptr ds:[7FF8E05D]
  0040146A     8BC0            mov eax,eax
  0040146C   - FF25 61E0F87F   jmp dword ptr ds:[7FF8E061]
  
  当然也有一部分IAT没有被修改
  
  004087DC   - FF25 18686B00   jmp dword ptr ds:[6B6818]
  004087E2     8BC0            mov eax,eax
  004087E4   - FF25 14686B00   jmp dword ptr ds:[6B6814]
  004087EA     8BC0            mov eax,eax
  004087EC   - FF25 10686B00   jmp dword ptr ds:[6B6810]
  004087F2     8BC0            mov eax,eax
  004087F4   - FF25 0C686B00   jmp dword ptr ds:[6B680C]
  004087FA     8BC0            mov eax,eax
  004087FC   - FF25 08686B00   jmp dword ptr ds:[6B6808]
  00408802     8BC0            mov eax,eax
  00408804   - FF25 04686B00   jmp dword ptr ds:[6B6804]
  0040880A     8BC0            mov eax,eax
  0040880C   - FF25 00686B00   jmp dword ptr ds:[6B6800]
  
  可以用patch代码修复,但比较麻烦;
  
  程序中idata的区段是006B6000,查看发现:
  
  006B636C  77DDEAF4  絷    advapi32.RegCreateKeyExA
  006B6370  77DD6BF0      advapi32.RegCloseKey
  006B6374  77DD7753  Sw   advapi32.OpenProcessToken
  006B6378  77DFD11B  堰w   advapi32.LookupPrivilegeValueA
  006B637C  77DFC534  4胚w   advapi32.AdjustTokenPrivileges
  006B6380  00000000  ....
  006B6384  7FF87F15  ?   ASCII "h6"
  006B6388  7FF87F20   ?   ASCII "h7"
  006B638C  7FF87F2B  +?   ASCII "h8"
  006B6390  7FF87F36  6?   ASCII "h9"
  006B6394  7FF87F41  A?   ASCII "h:"
  006B6398  7FF87F4C  L?   ASCII "h;"
  006B639C  7FF87F57  W?   ASCII "h<"
  
  这下知道该怎么办了,关闭OD(不想出意外的话),然后用Xidt.exe写入之前保存的idt,再用OD载入程序;
  
  数据窗口跟随地址:006B6390,下内存访问断点后运行,停在
  
  7FF7EBE4     66:3103         xor word ptr ds:[ebx],ax               ;停在这里
  7FF7EBE7     7A 03           jpe short 7FF7EBEC
  7FF7EBE9     7B 01           jpo short 7FF7EBEC
  7FF7EBEB     75 66           jnz short 7FF7EC53
  7FF7EBED     48              dec eax
  7FF7EBEE     9C              pushfd
  7FF7EBEF     6A 10           push 10
  7FF7EBF1     73 0B           jnb short 7FF7EBFE
  7FF7EBF3     EB 02           jmp short 7FF7EBF7
  7FF7EBF5     C151 E8 06      rcl dword ptr ds:[ecx-18],6
  
  清除内存断点,用花指令去除器插件去掉花指令,效果如下
  
  7FF7EBE4     66:3103         xor word ptr ds:[ebx],ax
  7FF7EBE7     90              nop
  7FF7EBE8     90              nop
  7FF7EBE9     90              nop
  7FF7EBEA     90              nop
  7FF7EBEB     90              nop
  7FF7EBEC     66:48           dec ax
  7FF7EBEE     90              nop
  7FF7EBEF     90              nop
  7FF7EBF0     90              nop
  7FF7EBF1     90              nop
  
  往下找popad指令
  
  7FF7F085     68 00800000     push 8000
  7FF7F08A     6A 00           push 0
  7FF7F08C     50              push eax
  7FF7F08D     FF95 43C64200   call dword ptr ss:[ebp+42C643]         ;这个是VirtualFree
  7FF7F093     90              nop
  7FF7F094     90              nop
  7FF7F095     90              nop
  7FF7F096     90              nop
  7FF7F097     90              nop
  7FF7F098     90              nop
  7FF7F099     90              nop
  7FF7F09A     90              nop
  7FF7F09B     90              nop
  7FF7F09C     90              nop
  7FF7F09D     61              popad                                  ;F4到这里
  
  往下有个pushad指令
  
  7FF7F0CE     60              pushad                               
  7FF7F0CF     90              nop
  7FF7F0D0     90              nop
  7FF7F0D1     90              nop
  7FF7F0D2     90              nop
  7FF7F0D3     90              nop
  7FF7F0D4     8B9D 32CC4200   mov ebx,dword ptr ss:[ebp+42CC32]
  
  继续往下找到popad指令
  
  7FF7F166     50              push eax
  7FF7F167     6A 04           push 4
  7FF7F169     51              push ecx
  7FF7F16A     53              push ebx
  7FF7F16B     FF95 53C64200   call dword ptr ss:[ebp+42C653]         ;这个是VirtualProtect
  7FF7F171     90              nop
  7FF7F172     90              nop
  7FF7F173     90              nop
  7FF7F174     90              nop
  7FF7F175     90              nop
  7FF7F176     61              popad                                  ;F4到这里
  
  继续往下有个jmp回跳
  
  7FF7F1D5     90              nop
  7FF7F1D6     90              nop
  7FF7F1D7     90              nop
  7FF7F1D8     90              nop
  7FF7F1D9   ^ E9 BBF8FFFF     jmp 7FF7EA99
  
  继续往下找到
  
  7FF7F270     90              nop
  7FF7F271     E8 F40F0000     call 7FF8026A                          ;IAT解密call,F7跟进
  7FF7F276     90              nop
  7FF7F277     90              nop
  7FF7F278     90              nop
  7FF7F279     90              nop
  7FF7F27A     90              nop
  7FF7F27B     8D9D 90CB4200   lea ebx,dword ptr ss:[ebp+42CB90]
  
  继续去除花指令,来到
  
  7FF802B2     FF95 47C64200   call dword ptr ss:[ebp+42C647]         ; kernel32.GetCurrentProcessId
  
  7FF80448     03D3            add edx,ebx
  7FF8044A   ^ E2 DF           loopd short 7FF8042B                   ;loop循环
  
  7FF804BB     0385 32CC4200   add eax,dword ptr ss:[ebp+42CC32]      ;执行后出现DLL模块名称kernel32.dll
  
  7FF8068B     50              push eax                               
  7FF8068C     FF95 1A6F4300   call dword ptr ss:[ebp+436F1A]         ; kernel32.LoadLibraryA
  
  7FF806D1     8985 ABC34200   mov dword ptr ss:[ebp+42C3AB],eax      ; kernel32.7C800000
  
  7FF807C1     03D3            add edx,ebx
  7FF807C3   ^ E2 DF           loopd short 7FF807A4                   ;又一个loop循环
  
  7FF808E2     03D3            add edx,ebx
  7FF808E4   ^ E2 DF           loopd short 7FF808C5                   ;继续loop
  
  7FF80AB2     50              push eax                              
  7FF80AB3     FFB5 ABC34200   push dword ptr ss:[ebp+42C3AB]
  7FF80AB9     FF95 1E6F4300   call dword ptr ss:[ebp+436F1E]         ; kernel32.GetProcAddress
  
  上面有很多函数调用,可以作为断点跟踪的依据,仅供参考;
  
  往下到关键修改
  
  第一处:
  7FF80F5E     39BD 89CE4200   cmp dword ptr ss:[ebp+42CE89],edi      ; RemindBo.006B6244
  7FF80F64     76 10           jbe short 7FF80F76
  7FF80F66     90              nop
  7FF80F67     90              nop
  7FF80F68     90              nop
  7FF80F69     90              nop
  7FF80F6A     90              nop
  7FF80F6B     89BD 89CE4200   mov dword ptr ss:[ebp+42CE89],edi      ;nop掉
  
  第二处:
  7FF80F8D     39BD 85CE4200   cmp dword ptr ss:[ebp+42CE85],edi      ; RemindBo.006B6244
  7FF80F93     73 34           jnb short 7FF80FC9
  ......
  7FF80FAC     89BD 85CE4200   mov dword ptr ss:[ebp+42CE85],edi      ;nop掉
  
  第三处:
  7FF80FEA     890F            mov dword ptr ds:[edi],ecx             ;ecx改成eax,因为eax中是IAT函数指针
  7FF80FEC     90              nop
  7FF80FED     90              nop
  7FF80FEE     90              nop
  7FF80FEF     90              nop
  7FF80FF0     90              nop
  7FF80FF1     83C6 04         add esi,4
  7FF80FF4     90              nop
  7FF80FF5     90              nop
  7FF80FF6     90              nop
  7FF80FF7     90              nop
  7FF80FF8     90              nop
  7FF80FF9     83C7 04         add edi,4
  
  7FF81011     90              nop
  7FF81012     90              nop
  7FF81013   ^ E9 71F9FFFF     jmp 7FF80989                           ;解密循环
  
  下面有个popad指令,F4到那里后,恢复上面修改的代码,搜索命令jmp eax,直达OEP即可【切记勿下F2断点】;
  
  
  3、修复跳转
  
  IAT搞定了,可代码中有很多IAT地址出错了,类似:
  
  00407BE4     FF25 7C636B80   jmp dword ptr ds:[806B637C]
  00407BEA     8BC0            mov eax,eax
  00407BEC     FF25 78636B80   jmp dword ptr ds:[806B6378]
  00407BF2     8BC0            mov eax,eax
  00407BF4     FF25 74636B80   jmp dword ptr ds:[806B6374]
  00407BFA     8BC0            mov eax,eax
  00407BFC     FF25 70636B80   jmp dword ptr ds:[806B6370]
  00407C02     8BC0            mov eax,eax
  00407C04     FF25 6C636B80   jmp dword ptr ds:[806B636C]
  00407C0A     8BC0            mov eax,eax
  00407C0C     FF25 68636B80   jmp dword ptr ds:[806B6368]
  
  懒得跟踪原因,其实很简单,把80改成00即可,或者找个空白处,用下面的代码修复:
  
  00E80000     BA 00104000          mov edx,401000                    ;code段起始地址
  00E80005     66:813A FF25         cmp word ptr ds:[edx],25FF        ;搜索jmp指令
  00E8000A     75 1C                jnz short 00E80028
  00E8000C     8B42 01              mov eax,dword ptr ds:[edx+1]
  00E8000F     3D 2500606B          cmp eax,6B600025                  ;idata段起始地址,左移两位后,补25
  00E80014     7C 12                jl short 00E80028
  00E80016     3D 2500A06B          cmp eax,6BA00025                  ;idata段下一区段的起始地址
  00E8001B     77 0B                ja short 00E80028
  00E8001D     807A 05 00           cmp byte ptr ds:[edx+5],0         ;比较IAT地址第一个字节是否为0
  00E80021     74 05                je short 00E80028
  00E80023     C642 05 00           mov byte ptr ds:[edx+5],0         ;如果不是就赋0修正
  00E80027     41                   inc ecx                           ;计数器,看有多少个地址被修正了
  00E80028     42                   inc edx
  00E80029     81FA 00406900        cmp edx,694000                    ;data段起始地址
  00E8002F   ^ 72 D4                jb short 00E80005
  00E80031   - E9 3A3781FF          jmp RemindBo.00693770             ;跳到OEP
  
  二进制:
  BA 00 10 40 00 66 81 3A FF 25 75 1C 8B 42 01 3D 25 00 60 6B 7C 12 3D 25 00 A0 6B 77 0B 80 7A 05
  00 74 05 C6 42 05 00 41 42 81 FA 00 40 69 00 72 D4 E9 3A 37 81 FF
  
  写完后在00E80000处新建EIP,一定记得要在OEP处F2下断,跑飞就不爽了;
  
  4、DUMP修复
  
  Dump时注意修正一下镜像大小,ImportRec中填入OEP:00293770,IAT的RVA:002B6244,大小:1000;
  获取IAT,剪切掉无效指针,修复后程序运行正常;
  系统时间调回来以后,程序提示过期,用bp GetLocalTime跟踪一下,修改关键跳即可,具体从略;
  
  总结:
  没什么可总结的,互相学习,茁壮成长;
  步骤1和2借鉴了fly前辈5年前的方法,再次感激涕零!!!
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年05月20日 11:48:01