首页
社区
课程
招聘
[原创]突破封锁线:第一章--脱壳篇
发表于: 2006-4-28 14:55 24273

[原创]突破封锁线:第一章--脱壳篇

2006-4-28 14:55
24273

【文章标题】: 突破封锁线:第一章--脱壳篇
【文章作者】: Austin
【作者邮箱】: austiny.cn@gmail.com
【软件名称】: 神州数码网络客户登陆程序
【软件大小】: 不重要
【下载地址】: http://www.dcnetworks.com.cn
【加壳方式】: UltraProtect 1.x
【保护方式】: 加壳 网络封禁
【编写语言】: VC6.0
【使用工具】: PEid OllyDbg LordPE ImportRec
【操作平台】: Windows2003
【软件介绍】: 神州数码小区宽带网络登陆客户端,诸多限制
【作者声明】: 技术交流中。。。
--------------------------------------------------------------------------------
【详细过程】
  一、(背景)山和云的彼端
  
  那时候天很蓝,网很宽,资源可以共享,BT随便可以下。后来有了客户端,一切化为泡影。
  
  神州数码是一套小区宽带解决方案,使用802.x认证等技术,限制了网络的很多使用:
  
    1. 帐号与机器绑定(换机器不能登陆)
    2. 限制共享网络连接(发现代理,强制下线)
    3. 限制BT下载(强制下线)
    4. 无法从路由后连接(拒绝登陆)
    ...
  
  诸多不便,一一破之。
  
  二、(调查)英雄莫问出处
  
  神州数码(DigitalChina下简称DIGI)安装文件夹大概就是一个主EXE文件外加一堆DLL文件和配置文件。
  DLL文件都是系统常用如MFC42.DLL和AMT.DLL等,故搞定EXE一个即可。
  
   1. 先看看加壳否
   
   用PEid(侦壳工具)打开DIGI.EXE,得到 "UltraProtect 1.x -> RISCO Software Inc."。(看来盔甲穿得挺厚)
   
   2. 再看仔细些
  
   用LordPE(DUMP和PE修改工具)打开,看到程序有5个段。
   出特别指明,文中都使用十六进制
  
               地址          长度
   .text       00410000     10000
   .rdata      00411000      4000
   .data       00415000    204000
   .rsrc       00619000      3000
   .perplex    0061C000     1D000
  
   前4个都很典型(正常编译的程序一般都有这几个段),故不出意外,壳代码都在perplex段中。
  
   3. 战略
  
   UltraProtect壳没有脱壳机,只有自己动手脱光它了:
  
   调试 -> 找OEP -> dump -> 修复IAT -> 修复资源 -> 减肥
  
  三、(行动)骡子还是马,拉出来遛遛先
   
  用OllyDbg(调试工具)装载,运行。啪!OllyDbg退出了。(烈马!)看来壳中有反调试检查。
  
  难不倒我们:打开HideOD插件的隐藏选项,再运行。再啪!OllyDbg再次退出了。
  (我看这马挺烈吧)(那是相当烈啊)
  
  去看雪搜了一下,发现UltraProtect有检查加载者并于进程列表比对的习惯,而非常规的检查调试标志。
  故HideOD骗不倒它。
  
  再来,加载之,停在0061c000处:(正是在.perplex段中)
  
  0061C000 >  60              pushad
  0061C001    FC              cld
  0061C002    4D              dec     ebp
  0061C003    72 01           jb      short 0061C006
  0061C005    4E              dec     esi
  0061C006    50              push    eax
  0061C007    E8 01000000     call    0061C00D
  0061C00C    71 58           jno     short 0061C066
  0061C00E    58              pop     eax
  0061C00F    0F84 03000000   je      0061C018
  0061C015    66:13EF         adc     bp, di
  0061C018    76 03           jbe     short 0061C01D
  0061C01A    77 01           ja      short 0061C01D
  0061C01C  - 7E C1           jle     short 0061BFDF
  0061C01E    DD22            frstor  [edx]
  0061C020    7C 03           jl      short 0061C025
  0061C022    7D 01           jge     short 0061C025
  0061C024    9A BA21D624 CBB>call    far BACB:24D621BA
  
  将断点下至Process32First函数(获得进程列表会调用)
   bp Process32First+2
  
  F9运行,断在了7c85a26e处:(应该在Process32FirstA中)
  
  7C85A26E >  55              push    ebp
  7C85A26F    8BEC            mov     ebp, esp
  7C85A271    81EC 30020000   sub     esp, 230
  7C85A277    A1 08D1887C     mov     eax, [7C88D108]
  7C85A27C    56              push    esi
  7C85A27D    8B75 0C         mov     esi, [ebp+C]
  7C85A280    85F6            test    esi, esi
  7C85A282    8945 FC         mov     [ebp-4], eax
  7C85A285    8B45 08         mov     eax, [ebp+8]
  7C85A288    0F84 9D000000   je      7C85A32B
  7C85A28E    813E 28010000   cmp     dword ptr [esi], 128
  7C85A294    0F82 91000000   jb      7C85A32B
  7C85A29A    53              push    ebx
  7C85A29B    8D8D D0FDFFFF   lea     ecx, [ebp-230]
  7C85A2A1    51              push    ecx
  7C85A2A2    50              push    eax
  7C85A2A3    C785 D0FDFFFF 2>mov     dword ptr [ebp-230], 22C
  7C85A2AD    E8 FDFEFFFF     call    Process32FirstW
  
  Shift+F9回到用户代码:
  
  00620B3F > /E9 AD000000     jmp     00620BF1            ;直接跳转到下面
  00620B44   |60              pushad
  00620B45   |8DBD E1444000   lea     edi, [ebp+4044E1]
  00620B4B   |B9 26000000     mov     ecx, 26
  00620B50   |E8 A9EDFFFF     call    0061F8FE
  00620B55   |AB              stos    dword ptr es:[edi]
  00620B56  ^|E2 F8           loopd   short 00620B50
  00620B58   |61              popad
  00620B59   |60              pushad
  00620B5A   |E8 F2EFFFFF     call    0061FB51
          .......
  00620BF1   \0BC0            or      eax, eax            ;跳转到此,单步往下走
  00620BF3    0F84 27020000   je      00620E20            ;此处未跳转
  00620BF9    8B95 45424000   mov     edx, [ebp+404245]   ;[ebp+404245]的值从0开始,依次为各进程PID
  00620BFF    3B95 35424000   cmp     edx, [ebp+404235]   ;[ebp+404235]中为父进程OllyDbg的PID,此句进行比对
  00620C05    0F84 DC000000   je      00620CE7            ;在比对前将[ebp+404235]的值改为Explorer.exe的PID
  00620C0B    B8 3D424000     mov     eax, 0040423D       ;就可以骗过DIGI.EXE
  00620C10    03C5            add     eax, ebp
  00620C12    50              push    eax
  00620C13    FFB5 39424000   push    dword ptr [ebp+404239]
  00620C19    50              push    eax
  00620C1A    8B85 05454000   mov     eax, [ebp+404505]
  00620C20    8038 CC         cmp     byte ptr [eax], 0CC
  00620C23    74 10           je      short 00620C35
  
  不多说,改之。顺利通过检测。:)
  
  清除刚才的断点。(重要,除非你愿意一次又一次重打第一关BOSS)
  
  四、(继续)万里长征第二步
  
  通过了第一关,开始进行寻找OEP的伟大战役。
  (注:OEP=Original Entry Point,就是加壳前程序开始的地方,也是我们dump的起点)
  
  常识告诉我们,OEP应该在.text段。(当然也有不是的时候,不过大多数的时候还是是的)
  
  Alt+M打开内存图,F2设一个访问断点在.text段上。(没有用二次断点,因为幸运的是,此时代码段已经解压完毕)
  
  F9往下跑,程序停在0040fb74处,在.text段。(简直就是VC程序的标准入口,这里应该就是EOP没错了)
  
  0040FB74 > .  68 A82A4100   push    00412AA8
  0040FB79   .  68 D4FC4000   push    0040FCD4                         ;  jmp 到 msvcrt._except_handler3; SE 处理程序安装
  0040FB7E   .  64:A1 0000000>mov     eax, fs:[0]
  0040FB84   .  50            push    eax
  0040FB85   .  64:8925 00000>mov     fs:[0], esp
  0040FB8C   .  83EC 68       sub     esp, 68
  0040FB8F   .  53            push    ebx
  0040FB90   .  56            push    esi
  0040FB91   .  57            push    edi
  0040FB92   .  8965 E8       mov     [ebp-18], esp
  0040FB95   .  33DB          xor     ebx, ebx
  0040FB97   .  895D FC       mov     [ebp-4], ebx
  0040FB9A   .  6A 02         push    2
  0040FB9C   .  FF15 64144100 call    [411464]                         ;  msvcrt.__set_app_type
  0040FBA2   .  59            pop     ecx
  0040FBA3   .  830D 5C8E6100>or      dword ptr [618E5C], FFFFFFFF
  0040FBAA   .  830D 608E6100>or      dword ptr [618E60], FFFFFFFF
  0040FBB1   .  FF15 68144100 call    [411468]                         ;  msvcrt.__p__fmode
  0040FBB7   .  8B0D A06F4100 mov     ecx, [416FA0]
  0040FBBD   .  8908          mov     [eax], ecx
  0040FBBF   .  FF15 6C144100 call    [41146C]                         ;  msvcrt.__p__commode
  0040FBC5   .  8B0D 9C6F4100 mov     ecx, [416F9C]
  
  至此,EOP已经找到。
  
   由于可能多次重复,用OllyMachine插件完成整个上述过程:
  
  ;LOAD.TXT
  ;//////////////////////////////////////////////////////
  invoke bp, 0x7c85a26e;Process32First+2
  run
  runtousercode
  invoke bp, 0x7c85a26e;Process32First+2
  run
  invoke bc, 0x7c85a26e
  runtousercode
  invoke writememlong, 0x61f235, 1960, 2
  invoke bp, 0x0040fb74
  run
  ;//////////////////////////////////////////////////////
  
  五、(出击)衣带渐宽终不悔
  
  局势很明朗,dump之。这里用了OllyDbg的插件OllyDump。
  注意dump的时候不要选择Rebuild Import(术业有专攻,这个留给ImportRec来处理),保存为DIGI_DUMP.EXE。
  
  打开ImportRec(修复IAT之王),在它的进程表中找到正在调试的DIGI。
  在OEP中填入刚刚找到的0000FB74(偏移量),点击"IAT AutoSearch",再点击"Get Imports",得到Imported Functions列表。
  
  表中有两块为解决的项:
   ? FThunk:00011048 NbFunc:2D (decimal:45) valid:NO        这一项中有45个函数不可用
   ? FThunk:00011504 NbFunc:16 (decimal:22) valid:NO        这一项中有22个函数不可用
  
  注意表中00011048为偏移地址,所以实际地址应加上基地址00400000,为00411048。
  在OllyDbg的数据窗口中来到00411048(按地址方式显示):
  
  00411048  0061C000  offset DigitalC.<模块入口点>
  0041104C  0061C00D  DigitalC.0061C00D
  00411050  0061C01A  DigitalC.0061C01A
  00411054  0061C027  DigitalC.0061C027
  00411058  0061C034  DigitalC.0061C034
  0041105C  0061C041  DigitalC.0061C041
  00411060  0061C04E  DigitalC.0061C04E
  
  表中00411048指向0061c000(注意这正是.perplex段开始的地方),在反汇编窗口中跟踪:
  
  0061C000 >  68 D6DDEAA8     push    A8EADDD6
  0061C005    813424 A6AD68D4 xor     dword ptr [esp], D468ADA6
  0061C00C    C3              retn
  0061C00D    68 2666EDA8     push    A8ED6626
  0061C012    813424 4AC468D4 xor     dword ptr [esp], D468C44A
  0061C019    C3              retn
  0061C01A    68 9D6FEDA8     push    A8ED6F9D
  0061C01F    813424 7ECC68D4 xor     dword ptr [esp], D468CC7E
  0061C026    C3              retn
  0061C027    68 75D6EAA8     push    A8EAD675
  0061C02C    813424 42E668D4 xor     dword ptr [esp], D468E642
  0061C033    C3              retn
  
  注意每隔三句为表中指向的一项。
  
  如第一项所做的操作相当于 jmp xxxxxxxx (xxxxxxxx = A8EADDD6 xor D468ADA6),下面的项对应相同。
  故将算出的xxxxxxxx写入00411048即为真实的Imported Function地址。
  
  过程繁琐,用OllyMachine插件脚本来完成。(两个invalid的表一起解决掉)(此脚本来源于看雪论坛)
  
  ;修复IAT.TXT
  ;//////////////////////////////////////////////////////
  mov reg01,0x411048
  lp:
  invoke ReadMemLong,reg01,4;         ---先取出要跳转的指针
  ;invoke PrintNum,reg00,16;         ----这些是我最初拿来验证数据是否正确的
  mov reg02,reg00;         --------------存一下,下面还要用,寄存器多就是好
  inc reg00;         --------------------上面的代码中可以看出来,xor的前一个数在被指向地址+1处
  invoke ReadMemLong,reg00,4;         ---读取
  ;invoke PrintNum,reg00,16
  mov reg10,reg00
  add reg02,8;         ------------------xor后一个数在+8处
  invoke ReadMemLong,reg02,4;         ---读取
  xor reg00,reg10;         --------------xor,我们要的api地址
  ;invoke PrintNum,reg00,16
  invoke WriteMemLong,reg01,reg00,4;  ---写入到IAT中
  add reg01,4
  cmp reg01,0x4110f9;         -----------比较修复是否完成
  jb lp
  
  mov reg01,0x411504
  lp1:
  invoke ReadMemLong,reg01,4
  ;invoke PrintNum,reg00,16
  mov reg02,reg00
  inc reg00
  invoke ReadMemLong,reg00,4
  ;invoke PrintNum,reg00,16
  mov reg10,reg00
  add reg02,8
  invoke ReadMemLong,reg02,4
  xor reg00,reg10
  ;invoke PrintNum,reg00,16
  invoke WriteMemLong,reg01,reg00,4
  add reg01,4
  cmp reg01,0x411559
  jb lp1
  ;//////////////////////////////////////////////////////
  
  运行后发现00411048处的函数表已经修复,可以正确识别:
  
  00411048  7C827070  kernel32.SetThreadPriority
  0041104C  7C85A26C  kernel32.Process32First
  00411050  7C85A3E3  kernel32.Process32Next
  00411054  7C823037  kernel32.CreateThread
  00411058  7C82BC7C  kernel32.MultiByteToWideChar
  0041105C  7C806165  kernel32.DeleteFileA
  00411060  7C826919  kernel32.GlobalHandle
  00411064  7C8270B2  kernel32.SetEvent
  00411068  7C8266C5  kernel32.GlobalUnlock
  
  再回到Import Rec中,"Get Imports",形势一片大好,全部valid。
  
  将Add new section选中,点击"Fix Dump",选择之前保存的DIGI_DUMP.EXE:
  得到修复了Import Table的DIGI_DUMP_.EXE文件。
  
  六、(:)脱掉脱掉脱掉
  
  脱到这里,脑海里已经响起杜德伟的歌声。
  
  得意的运行DIGI_DUMP_.EXE文件。(冷水!)却得到一个引用0x0000000内存的错误。
  分析一下,应该是修改了入口地址(EP),壳中有些代码没有运行,所以程序未能正常运行。
  
  关闭对内存异常的忽略(因为是内存错误),再用OllyDbg打开新得到的DIGI_DUMP.EXE文件。
  
  从入口点0040fb74开始单步跟踪:
  
  0040FC93  |> \50            push    eax
  0040FC94  |.  56            push    esi
  0040FC95  |.  53            push    ebx
  0040FC96  |.  53            push    ebx                              ; /pModule
  0040FC97  |.  FF15 CC104100 call    [<&kernel32.GetModuleHandleA>]   ; \GetModuleHandleA
  0040FC9D  |.  50            push    eax
  0040FC9E  |.  E8 13010000   call    0040FDB6                         ;单步过此处出现异常
  0040FCA3  |.  8945 98       mov     [local.26], eax
  0040FCA6  |.  50            push    eax                              ; /status
  0040FCA7  |.  FF15 C0144100 call    [<&msvcrt.exit>]                 ; \exit
  0040FCAD  |.  8B45 EC       mov     eax, [local.5]
  0040FCB0  |.  8B08          mov     ecx, [eax]
  0040FCB2  |.  8B09          mov     ecx, [ecx]
  
  程序停在0061d137:
  
  0061D131    FF25 C0951500   jmp     [1595C0]
  0061D137 >  FF25 C4951500   jmp     [1595C4]       ;程序停在这里
  0061D13D    FF25 C8951500   jmp     [1595C8]
  0061D143    FF25 CC951500   jmp     [1595CC]
  0061D149    FF25 D0951500   jmp     [1595D0]
  0061D14F    FF25 D4951500   jmp     [1595D4]
  0061D155    FF25 D8951500   jmp     [1595D8]
  0061D15B    FF25 DC951500   jmp     [1595DC]
  0061D161    FF25 E0951500   jmp     [1595E0]
  0061D167    FF25 E4951500   jmp     [1595E4]
  
  这里(0061d137)已经是.perplex的领域,就是壳的代码段,看在程序运行后还是在调用壳中的代码。
  
  看一下堆栈:
  
  0012AEF8   0040FB6D  返回到 digi_dum.0040FB6D 来自 digi_dum.0061D137
  0012AEFC   00000000
  0012AF00   00000000
  0012AF04   00000000
  
  看来就是从0040fb6d之前调用了这里,Ctrl+G 跳过去:
  
  0040FB64  |.  8501          test    [ecx], eax
  0040FB66  |.  8BE1          mov     esp, ecx
  0040FB68  |.  E8 CAD52000   call    0061D137               ;就是这里调用了壳中代码
  0040FB6D  |.  50            push    eax
  0040FB6E  \.  C3            retn
  0040FB6F      63            db      63                               ;  CHAR 'c'
  0040FB70      72            db      72                               ;  CHAR 'r'
  0040FB71      6A            db      6A                               ;  CHAR 'j'
  0040FB72      D8            db      D8
  0040FB73      D4            db      D4
  0040FB74 >/$  68 A82A4100   push    00412AA8
  0040FB79  |.  68 D4FC4000   push    <jmp.&msvcrt._except_handler3>   ;  SE 处理程序安装
  0040FB7E  |.  64:A1 0000000>mov     eax, fs:[0]
  
  果不其然,就是这里调用了壳中的代码。
  
  分析一下:
  这是一种典型的壳驻留方式,就是在解压完毕之后,任有部分壳中代码被运行,以防止壳失去控制权(或者说,被脱掉)。
  
  这里用了一种叫做Code Splitting的技术(之后再具体分析)。
  应该是壳正常调用时,会在001595c4写入正常的函数地址以被调用。
  而现在壳代码没有运行,001595c4中就无没有正确的地址了。
  
  问题的关键就是得到001595c4中正确的地址。记下0061d137这个地方。
  
  将之前的内存异常忽略选项打开,用OllyDbg打开未脱壳的DIGI程序,在0061d137下断点。
  用之前的OllyMachine脚本将程序跑起来,停在0040fb7e处,再跑,停到0061d137处:
  
  0061D137  - FF25 C4951500   jmp     [1595C4]
  0061D13D  - FF25 C8951500   jmp     [1595C8]
  
  在数据窗口(地址模式)看1595c4的内容:
  
  001595BC  0015A56E
  001595C0  0015A574
  001595C4  0015A57A   ;这就是将要jmp到的地方
  
  在反汇编窗口跟过去:
  
  0015A56E    8BCF            mov     ecx, edi
  0015A570    8957 FC         mov     [edi-4], edx
  0015A573    C3              retn
  
  这三句就是壳程序在内存中写入的代码,
  在 0040FB68  |.  E8 CAD52000   call    0061D137 的调用最后就是调用了这三句代码。
  
  注意到 0040fb68 中的call语句占用了5个字节,而三句代码中的前两句占用的也是5个字节(第三句用于返回)。
  
  这就是Code Splitting的秘密!!!
  将原程序中的部分语句用壳中的一个call来代替,这样脱出来的程序就离不开壳来运行。
  
  解决方法就是将0015a56e开始的5个字节代码拷回至0040fb68就可以了。
  
  这么繁琐的工作,让OllyMachine来做:
  
  ;修复代码1.TXT
  ;//////////////////////////////////////////////////////
  mov reg01, 0x00401030
  lp:
  add reg01, 5
  invoke Find, reg01, "e8????2000"
  cmp reg00, -1
  je end1
  
  mov reg01, reg00 //reg01="call 0061????"
  invoke printbuftodump, reg01
  ;invoke printbuf, reg01, 5
  
  ;invoke MsgYn, "Process?"
  ;or reg00, 0
  ;je lp
  
  mov reg02, reg01
  inc reg02 //reg02="0020????"
  invoke readmemlong, reg02, 4
  mov reg03, reg00 //reg03=0020????
  ;invoke printnum, reg01, 16
  ;invoke printnum, reg03, 16
  add reg03, reg01
  add reg03, 5 //reg03=61????(jmp[15????])
  add reg03, 2 //reg03="15???"
  invoke printbuftodump, reg03
  
  invoke readmemlong, reg03, 4
  mov reg04, reg00 //reg04=15????
  
  invoke readmemlong, reg04, 4
  mov reg05, reg00 //reg05=[15????](xor ...)
  invoke printbuftodump, reg05
  ;invoke printbuf, reg05, 5
  
  ;invoke MsgYn, "Process?"
  ;or reg00, 0
  ;je lp
  
  invoke readmemlong , reg05, 4
  invoke writememlong, reg01, reg00, 4
  add reg01, 4
  add reg05, 4
  invoke readmemlong, reg05, 1
  invoke writememlong, reg01, reg00, 1
  sub reg01, 4
  invoke printbuftodump, reg01
  
  ;invoke MsgYn, "Continue?"
  ;or reg00, 0
  jne lp
  end1:
  ;//////////////////////////////////////////////////////
  
  ;修复代码2.TXT
  ;//////////////////////////////////////////////////////
  mov reg01, 0x00401030
  lp:
  add reg01, 5
  invoke Find, reg01, "e8????2100"
  cmp reg00, -1
  je end1
  
  mov reg01, reg00 //reg01="call 0061????"
  invoke printbuftodump, reg01
  ;invoke printbuf, reg01, 5
  
  ;invoke MsgYn, "Process?"
  ;or reg00, 0
  ;je lp
  
  mov reg02, reg01
  inc reg02 //reg02="0020????"
  invoke readmemlong, reg02, 4
  mov reg03, reg00 //reg03=0020????
  ;invoke printnum, reg01, 16
  ;invoke printnum, reg03, 16
  add reg03, reg01
  add reg03, 5 //reg03=61????(jmp[15????])
  add reg03, 2 //reg03="15???"
  invoke printbuftodump, reg03
  
  invoke readmemlong, reg03, 4
  mov reg04, reg00 //reg04=15????
  
  invoke readmemlong, reg04, 4
  mov reg05, reg00 //reg05=[15????](xor ...)
  invoke printbuftodump, reg05
  ;invoke printbuf, reg05, 5
  
  ;invoke MsgYn, "Process?"
  ;or reg00, 0
  ;je lp
  
  invoke readmemlong , reg05, 4
  invoke writememlong, reg01, reg00, 4
  add reg01, 4
  add reg05, 4
  invoke readmemlong, reg05, 1
  invoke writememlong, reg01, reg00, 1
  sub reg01, 4
  invoke printbuftodump, reg01
  
  ;invoke MsgYn, "Continue?"
  ;or reg00, 0
  jne lp
  end1:
  ;//////////////////////////////////////////////////////
  
  运行上述两个脚本,以及之前的修复IAT脚本。 Dump出来,用ImportRes修复。(啤酒拿出来,准备庆祝)
  
  运行一下新的DIGI_DUMP_.EXE程序 ~~ 程序界面飘然而至 :)
  
  七、(狂欢)I am a super dancing queen!
  
  为了确定已经脱光了,用OllyDbg打开之,清除所有断点,对.perplex段下访问断点(在Alt+M中),运行。
  试验各项功能,并没有被断下来,说明.perplex中的壳代码再也没有运行。
  
  脱壳成功!!!
  
--------------------------------------------------------------------------------
【经验总结】
  至此,神州数码的UltraProtect壳已经被彻底的脱下来了。为后续的工作做好了准备。
  
  脱壳中注意的关键点有:
   1. 壳会对进程列表进行比对,关键点是Process32First函数   .........  LOAD.TXT脚本
   2. 壳中有奇怪形式的IAT表,注意修复     ..........................  修复IAT.TXT脚本
   3. 壳使用了Code Splitting技术,注意还原     .....................  修复代码1.TXT 修复代码2.TXT 脚本
   4. 脚本真是个好东西
  
  突破封锁线:第一章--脱壳篇 [完]
  
  谢谢您耐心的看到这里,在下一章--资源篇中,将详细讲述如何修复资源和加入自己的资源到程序中。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年04月28日 14:49:03


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (56)
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
又一位新人加入论坛,欢迎!
Austin文章条理性很好,期待你的下一篇。
另外,这篇是关于脱壳的,过会我转到脱壳分论坛。
2006-4-28 15:16
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
怎么找不到程序的下载?
2006-4-28 15:49
0
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
学习啊学习
2006-4-28 16:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
楼主说话还蛮有趣有类,不过我刚刚接触这些东西嘛。
你说的技术我也没有看懂的啦,不过恭喜你的啦。
2006-4-28 16:21
0
雪    币: 208
活跃值: (41)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
从题目看,还有是个系列,严重支持。
2006-4-28 16:40
0
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
顶一下吧 ~~~~~

D:
2006-4-28 16:53
0
雪    币: 97697
活跃值: (200824)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
8
I sustain!
2006-4-28 16:55
0
雪    币: 279
活跃值: (145)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
9
支持一下,看来写脚本对付SDK是正途.
2006-4-28 16:57
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
10
支持文学青年
2006-4-28 17:01
0
雪    币: 256
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
严重期待资源篇.............
2006-4-28 17:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
顶一下~~~~~~~~
2006-4-28 18:09
0
雪    币: 212
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
我在学校里的神州数码客户端最新的一版已经没有壳了。

UltraProtect是比较好的壳,而且提供了SDK以供“里应外合”,但是神州数码客户端的保护是用的UltraProtect的免费功能,自然不咋地。

原来我也脱过前一个版本的神州数码客户端,总的说来,这个壳用了动态混淆代码,多种的反调试器监测,而且把程序前几条指令偷到自己体内,自然,还有Stolen code
2006-4-28 18:19
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
14
文章写的很风趣,学习!
2006-4-28 18:23
0
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
又见猛人!!!
2006-4-28 18:42
0
雪    币: 296
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
严重支持....就是脚本的地方看不懂....
2006-4-28 18:49
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
UltraProtect的好文章
早些日子玩一个旧软用的就是这个
在算法处就有楼主说的偷字节现象
当时不太会脚本
手动修了几处就烦了
爆之
看了这个
觉得有必要试试脚本的威力了
赞一下清晰的分析先
2006-4-28 19:57
0
雪    币: 331
活跃值: (56)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
18
这段时间,牛人都浮出水面了
2006-4-28 21:41
0
雪    币: 313
活跃值: (250)
能力值: ( LV9,RANK:650 )
在线值:
发帖
回帖
粉丝
19
的确是好文
2006-4-28 21:54
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
妙文,学习了。但有些看不懂,尤其脚本的应用
2006-4-28 22:23
0
雪    币: 50
活跃值: (145)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
21
写的好,佩服
2006-4-28 23:03
0
雪    币: 196
活跃值: (135)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
22
牛人渐渐浮上来,菜鸟可以学习了.....
2006-4-28 23:17
0
雪    币: 235
活跃值: (100)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
23
【文章标题】: 脱壳篇[补]--修复代码脚本分析
【文章作者】: Austin
【作者邮箱】: austin.cn@gmail.com
【作者声明】: 技术交流中。。。
--------------------------------------------------------------------------------
【详细过程】
  阅读本文前最好先阅读OllyMachine手册,掌握基本命令。(OllyMachine是强大的OllyDbg脚本插件)
  
  脚本的工作流程基本上就是从.text段的最开始搜索,找到有call 0061????形式的call就跟进去,找出被偷的代码,写回来。
  搜索中使用了OllyMachine的Find函数,该函数寻找特定的命令字符。
  
  下面逐行分析:
  
    ;修复代码1.TXT
    ;//////////////////////////////////////////////////////
    mov reg01, 0x00401030                         ;//从00401030开始察看,也可以从00401000开始,不过前面确实没有
    lp:                                           ;//循环开始
    add reg01, 5                                  ;//每次走5个字节
    invoke Find, reg01, "e8????2000"              ;//e8是call的机器码,后面跟的是跳转的偏移量。??代表任意一个字节
    cmp reg00, -1                                 ;//注意偏移量是反序,即高位在后。所以一个0020????的偏移量写成了????2000
    je end1                                       ;//若找不到,则跳转到结束
    
    mov reg01, reg00                              ;//将找到的地址存入reg01,则reg01指向一个形如call 0061????的指令
    invoke printbuftodump, reg01                  ;//打印到数据窗口察看
    ;invoke printbuf, reg01, 5
    
    ;invoke MsgYn, "Process?"
    ;or reg00, 0
    ;je lp
    
    mov reg02, reg01                              ;//将reg01存到reg02
    inc reg02                                     ;//reg02增加一个字节,则它指向 0020????这个偏移量
    invoke readmemlong, reg02, 4                  ;//将这个偏移量读入reg00
    mov reg03, reg00                              ;//存入reg03中
    ;invoke printnum, reg01, 16
    ;invoke printnum, reg03, 16
    add reg03, reg01                              
    add reg03, 5                                  ;//此时reg03已经是跳转到的指令地址,形如jmp[15????]
    add reg03, 2                                  ;//再向前两个字节,reg03指向 15????的地址
    invoke printbuftodump, reg03                  ;//打印
    
    invoke readmemlong, reg03, 4                  ;//将 15????这个数值读入reg00
    mov reg04, reg00                              ;//存入reg04备用
    
    invoke readmemlong, reg04, 4                  ;//将15????指向的地址读入reg00
    mov reg05, reg00                              ;//存入reg05备用
    invoke printbuftodump, reg05                  ;//打印
    ;invoke printbuf, reg05, 5
    
    ;invoke MsgYn, "Process?"
    ;or reg00, 0
    ;je lp
    
    invoke readmemlong , reg05, 4                 ;//读出真正指令的前4个字节,共五个,但一次最多读4个。所以分两次来做。
    invoke writememlong, reg01, reg00, 4          ;//将这4个字节写回.text段中
    add reg01, 4                                  ;//后移4个字节
    add reg05, 4
    invoke readmemlong, reg05, 1
    invoke writememlong, reg01, reg00, 1          ;//读出和写入最后一个字节
    sub reg01, 4
    invoke printbuftodump, reg01                  ;//打印
    
    ;invoke MsgYn, "Continue?"
    ;or reg00, 0
    jne lp                                        ;//循环继续
    end1:
    ;//////////////////////////////////////////////////////
  
--------------------------------------------------------------------------------
【经验总结】
  使用脚本可以使我们破解工作的繁重程度大大减轻,自动化程度大大提高。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年04月28日 23:18:20[CODE]
2006-4-28 23:26
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
24
没有找到软件的下载地址。。。楼主提供的下载不到
2006-4-29 09:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
看雪里果然牛人N多.一定要好好学习!
2006-4-29 09:55
0
游客
登录 | 注册 方可回帖
返回
//