您的位置:首页精文荟萃破解文章 → Soft-ICE 实例起步( Windows 版)

Soft-ICE 实例起步( Windows 版)

时间:2004/10/15 1:02:00来源:本站整理作者:蓝点我要评论(0)

 为了以后说话方便 ,  这里把  Soft-ICE  的一些简单使用方法说一下 ,  以免不通  E  文的同志们找不到中文的  Soft-ICE  说明而抓瞎 .

   Soft-ICE  由三部分  ( 以后说的  Soft-ICE,  如果不加特殊说明 ,  均指  Soft-ICE for Windows 95  的  2.0  版本以上 )  组成 : WINICE.EXE, WLDR.EXE ( 在  3.0  中这个文件叫做  LOADER32.EXE)  和显示驱动程序  SIWVID.386.


  另外 , Soft-ICE  在启动的时候要装入一些  DLL/EXE  的函数名信息 ,  你必须手工指定这些  DLL,  按照 :


   exp=d:\path\name.ext


  的格式写在  WINICE.DAT  文件里 .  本文附录里面有俺用的  WINICE.DAT,  你可以直接用起来 ,  省得自己写那么多行了 .  注意 ,  一定要把下面几行包括进去 ,  否则  WINICE  可能什么东东也拦不到 :


   exp=c:\win95\system\kernel32.dll


   exp=c:\win95\system\user32.dll


   exp=c:\win95\system\gdi32.dll


   exp=c:\win95\system\comctl32.dll


  一般我们使用  WLDR ( 以后把  LOADER32  也称为  WLDR)  来装入一个  EXE  文件或者一个  DLL  文件 ,  大多数的时候 ,  我们也可以直接执行  EXE  文件 ,  通过跟踪它的各种消息来找到它 .  启动  WINICE  的热键是  Ctrl+D.  先介绍常规的办法 :


  启动  WLDR,  然后选择你要跟的程序 ,  单击  Load  按钮 ,  屏幕上一阵乱闪后就进入了文本模式 ,  这就是  Soft-ICE  的跟踪界面 ,  虽然简单了点 ,  但是很友好 .  可以像  DOSKEY  那样用光标上下键重复上次输入的内容 ,  也可以输入上次输入内容的一部分 ,  然后按光标上键 ,  上次输入内容就完整地贴了出来 .
一般情况下 ,  如果装入的一个  NE  程序 , WINICE  会直接找到它的入口点 ,  并且把当前的光标定在  EXE  的头一条指令上 ;  如果是  PE  程序 , WINICE  会停在一个  INVALID  区 ,  按下  F10  后可以到  EXE  头部 .


  比较重要的功能键 :


   (1) F10 :  单步执行 ; CALL, INT  会被跳过 ;


   (2) F8   :  单步执行 ; CALL, INT  会被切入 ;


   (3) F4   :  查看程序画面 ;


   (4) F11 :  对于  CALL  形式的子程序 ,  直接执行完毕 ,  在  RET(F)  之后


       回到  CALL  的下一条指令 ;


  比较重要的几条命令是 :


   (1) G:  执行程序 ,  后面如果加地址 ,  则执行到该地址为止 ,  比如 :


     2400:0480      MOV     AH,30


     2400:0482      INT     21


     2400:0484      CMP     AL,09


     2400:0486      JZ     04F9


     2400:0488      MOV     AH,4C


     2400:048A      INT     21


  假设当前  CS:IP (EIP)  为  2400:0480,  如果我们直接执行  G,  就会一  G  到底 ,  直接回到命令行 ,  原因在于  DOS 9.00  还没出 ,  程序直接执行  DOS TERMINATE  功能了 .


  如果你把  DOS  版本号先改成  9.0,  然后执行  G 4F9, WINICE  会跑到  2400:04F9  处然后停下 ;  但是如果你不改版本号也这么来一把 ,  就也会一  G  到底 ,  回到命令行了 ,  因为  2400:04F9  在这种情况下永远不会被执行到 .


   (2) P:  单步执行程序 ;  只执行  P  时 ,  相当于按下  F10  键 ;  如果后面加入  P RET  参数 ,  会执行到最近的一条  RET/RETF  处 ,  注意 , IRET  会被忽略 ,  所以要小心 ;


   (3) T:  相当于按下  F8;


   (4) BPINT:  设置中断断点 ;  格式为  "BPINT  中断号  [ 条件 ]";  在  WINICE 2.0  里面 ,  条件只能是下面三种之一 :


     bpint xx ah=ab


     bpint xx al=cd


     bpint xx ax=abcd


  而在  WINICE 3.0  里面 ,  条件的格式丰富得多 :


     bpint xx if ah==ab


     bpint xx if al==cd


     bpint xx if ax==abcd


     bpint xx if dx->4==abcd ( 当  DS:DX+4  处的值为  0xabcd  的时候 )


  还有一些 ,  不是很常用 ,  等到用的时候再说吧 .         ;)


   (5) BPX:  设置执行地址断点 ;  格式为  "BPX  地址 ",  还以上面的例子来说 ,  假如我们执行  bpx 486,  然后来一把  G 4F9  的话就不会一  G  到底了 ,  因为我们在那个判断处设了断点 , WINICE  会执行到  2400:0486  然后停下 ;


   BPX  的第二种用法是我们这个教程的关键 ,  格式为  "BPX  函数名 ".  这个函数名可以是任意一个  Windows API  函数 ,  虚拟机指令 , DLL  的引出函数等等 .  功能强劲 .  比如说 ,  我们先启动  Notepad,  然后在里面随便敲些东东 ,  然后按  Ctrl+D,  执行 :


   :bpx messageboxa       ( 不用区分大小写 )


   :g


  然后关闭  Notepad,  这时  WINICE  会被激活 ,  原因是断点条件已经符合了 . Notepad  此时将弹出一个消息框提醒你存盘 ,  这就进入了  MessageBox  函数 ,  后面加一个  A  是由于我们现在在  Windows 95  里面 ,  函数是区分字符集的 . A  表示  ANSI, W  表示  Wide,  即  Unicode (Wide character-set).


   (6) BPM:  设置内存访问断点 ;  格式为  "BPM  地址 ";  比如 : BPM F000:E6F9  会把断点设在内存中存放  BIOS  更新版本号的内存位置上 ,  只要有程序访问这个地址 , WINICE  就会激活 .  另外 ,  还可以单独设定对地址的访问条件 :  读 (R)/ 写 (W)/ 执行 (X).  只需要在后面把对应的字母加上就可以了 .  以那段  " 一  G  到底 "  为例 :


   :bpm 2400:0486 x


   :g


  和  bpx 486  的效果完全一样 .


   (7) BMSG:  跟踪  Windows  消息 ;  格式为  "BMSG  消息名 ";  比如我们执行  Notepad,  然后  Ctrl+D  激活  WINICE,  输入 :


   :bmsg wm_char


   :g


  然后回到  Notepad  中 ,  随便按一个键 , WINICE  就激活了 ;  原因在于我们在按键消息上设置了断点 .


   (8) BL:  列出所有的断点 ;  格式为  "BL";  它会把所有断点按从  0  开始的编号列出 ;


   (9) BC:  清除断点 ;  格式为  "BC  断点编号 ",  这个编号就是  BL  列出的那个 ;  还有一种格式为  "BC *",  作用是清除所有的断点 .


   (10) RFL:  改变标志字 ;  格式为  "RFL  标志位 ";  比如当前  Z  标志位  ( 零位 )  为置位状态 ,  执行  "rfl z"  之后会被清楚 ;  如果  C  标志位为清除状态 ,  那么  "rfl c"  将使之置位 ;  比如 :


   :g 486


   :rfl z


   :g 4f9


  这次就真可以  G  到  4F9  处了 .


   (11) A:  进入  WINICE  小汇编状态 ;  格式为  "A  地址 ";  也可以不加地址值 ,  直接在当前  CS:IP  处汇编 ;  举例 :


   :g 486


   :a 2400:0486


   2400:0486 jnz 4f9


   2400:0488 ( 按下  ENTER  键结束汇编 )


   :g 4f9


  也可以  G  到  4F9  处 .


   (12) E:  进入  WINICE  内存修改状态 ;  格式为  "E  地址 ";  也可以不加地址值 ,  直接在  DS:DX  处修改 ;  比如 :


   :e 2400:0485


   2400:0485 - 09 74 XX XX XX XX XX XX XX XX XX XX XX XX XX XX


   ( 光标停在  09  下面 ,  我们输入  09 EB,  然后按  ENTER  结束修改 )


   2400:0485 - 09 EB XX XX XX XX XX XX XX XX XX XX XX XX XX XX


  然后  "g 4f9"  就可以到  4F9  啦 ;  我们输入的  EB  是  JMP  的机器码 .


   (13) U:  反汇编 ;  格式为  "U  地址 ",  也可以不加地址 ,  直接在当前  CS:IP (EIP)  往后反汇编  12  行  ( 行数由  CODE  栏的宽度而定 ).


   (14) R:  更改寄存器的值 ;  格式为  "R  寄存器名 = 值 ",  也可以不加值 , WINICE  会让你在最上面的寄存器区直接修改 ,  用光标键可以在各个位之间移动 .  比如 :


   :g 484


   :r ax=0009


   :g 4f9


  就到了  4F9  处 .


  基本的指令就是这  14  条 ,  如果需要 ,  俺随时补充就是了 .




---  如何拆解  ACDSee '95


   ACDSee'95  是一个速度快 ,  功能强 ,  格式多 , BUG  少的  ......  图形浏览程序  ( 不要想歪了哦 ! ;) .  我们以  ACDSee '95 1.0 正式版为例来看看此类程序如何拆解 .


  首先是得到该程序 , 该程序可以在 :


   http://www.acdsys.com/download.htm(l)


  下获得 . 也可以在国内的许多 BBS 上得到 . 注意 : 我们需要它的正式版 , 否则许多地址值是错误的 , 但是原理是一样的 .


  首先用用这个程序 , 当你看了 30 张左右的图片之后 , 该程序就开始频繁提醒你注册了 . 另外 , 在程序的 About 对话框里面也有 Register 按钮让你注册 . 我们来试试注册会是什么样子 . 在 Register 对话框里面随便输入一个名字 , 比如 "eGIS - pCE '97" 吧 , 然后按 Tab 键跑到 Code 栏里面输入个数字 , 比如 12345, 然后按回车键 .


  啊 !ACDSee'95  弹出一只  Message Box,  告诉你输入的号是无效的 .     :..(


  让我们来想想看这种判断应该是如何工作的 ,  这不难猜 :


   (1)  取得用户输入的名字 ;


   (2)  取得用户输入的注册号 ;


   (3)  使用某种算法检验 ;


   (4)  判断是否合法 ;


   (5)  如果合法就显示注册消息 ;


   (6)  如果非法就弹出一只  Message Box.


  好 .  知道了这个就好办 .  我们不难看到 ,  拆解的关键在于上面的第四步 ,  如何令这个程序认为你输入的号是正确的 .  从那个  " 一  G  到底 "  程序里面我们应该学到些简单的拆解经验 ,  在那个例子里 ,  我们就是改动了一个  Z  标志来达到可以  G  到  4F9  的目的的 ,  这个方法是  " 普适 "  的 ,  也适于这个比较复杂的例子 .


  现在我们开始拆 .  首先我们猜想  ACDSEE  使用了  GetWindowTextA  函数来取得用户输入的信息 ,  来试试 :


   :bpx getwindowtexta


   :g


  然后再按  ENTER  键 ,  结果  WINICE  没有被激活 .  为什么呢 ?  原因是很简单的啦 ,  就是  ACDSEE  没用这个函数 .  那用的是什么呢 ?  不难想到  GetDlgItemTextA  函数 ,  再跟一次看看 :


   :bc *


   :bpx getdlgitemtexta


   :g


  按下回车键 . Bingo! WINICE  被激活了 !  好 ,  说明我们跟的函数是对的 .  但是不要着急 ,  我们输入了两条信息 :  名字和注册号 ,  因此这个函数会被执行两次 ,  所以我们继续  G  一下 .  果然 , WINICE  又拦到一个  GetDlgItemTextA  函数 :


   USER32! GetDlgItemTextA


   --------------------------------------------------------------


   0137:BFF61657      MOV     CL,96


   0137:BFF61659      PUSH    EBP


   0137:BFF6165A      MOV     EBP,ESP


   0137:BFF6165C      PUSH    ECX


   0137:BFF6165D      SUB     ESP,3C


   0137:BFF61660      PUSH    WORD PTR [EBP+08]


  好了好了 ,  就  A  到这儿吧 .  反正  WINICE  拦到了这个函数 ,  并且我们不关心它是如何得到那些数据的 ,  我们直接走完这个函数 .  按下  F11  键就回到了调用它的地方 :


   0137:004016FB      CALL    EDI    ;  我们就是从这里回来的     ;)


   0137:004016FD      XOR     DI,DI ;  当前  EIP


   0137:00401700      LEA     EBX,[ESP+18]


   0137:00401704      CMP     BYTE [ESP+18],0


   0137:00401709      JZ     401723


   0137:0040170B      MOVSX    EAX,BYTE PTR [EBX]


  我们看到  EIP  下面两条指令都和  [ESP+18]  有关 .  究竟  [ESP+18]  处是什么东东呢 ?  我们来  DUMP  一下它 :


   :d esp+18


  哈哈 !  原来  [ESP+18]  处存的是你输入的姓名 .  那么下面一条  CMP  的作用很明显了 ,  它是判断你是不是什么都没有输入 ,  我们既然输入了姓名 ,  就可以狠光明正大地  G  到地址  40170B  去也 .


  接下来的一段是 :


   0137:0040170E     PUSH    EAX


   0137:0040170F     CALL    0045A230


   0137:00401714     ADD     ESP,04


   0137:00401717     TEST    EAX,EAX


   0137:00401719     JZ     0040171D


   0137:0040171B     INC     DI


   0137:0040171D     INC     EBX


   0137:0040171E     CMP     BYTE PTE [EBX],0


   0137:00401721     JNZ     0040170B


   0137:00401723     CMP     DI,05


   0137:00401727     JL     00401841


   0137:0040172D     LEA     EAX,[ESP+38]      ;  注册号


   0137:00401731     LEA     EAX,[ESP+18]      ;  名字


   0137:00401735     PUSH    EAX


   0137:00401736     PUSH    ECX


   0137:00401737     PUSH    0047A128


   0137:0040173C     CALL    00403560


   0137:00401741     ADD     ESP,0C


   0137:00401744     CMP     EAX,01


   0137:00401747     SBB     EAX,EAX


   0137:00401749     INC     EAX


   0137:0040174A     TEST    EAX,EAX


   0137:0040174C     JL     00401841


   0137:00401752     LEA     EAX,[ESP+14]


   0137:00401756     LEA     ECX,[ESP+0C]


   0137:0040175A     PUSH    EAX


   0137:0040175B     PUSH    ECX


   A  了这么长 ,  我们来看看这段代码的用处吧 .  首先我们看到在  40172D  这个地方用到了  [ESP+38]  和  [ESP+18],  经过  DUMP  知道 , [ESP+38]  存放着我们输入的序列号 ,  那么上面的一个循环就可以直接跳过来了 .  输入 :


   :g 40173c


  然后有一个  CALL,  它前面的几个压栈函数压进去的是名字和序号 ,  然后经过一个子程序 ,  然后下面又有判断 ,  那么这个  CALL  极有可能是判断名字和序号是否符合的子程序 ,  我们来看看是不是这么回事 .  先  G  到下面的判断处 :


   :g 401744


  我们看到这时候  EAX  是  0,  然后继续走到  40174C,  发现它是要跳到  401841  执行程序 .  我们继续走 ,  发现那个破框弹了出来 .  之前的唯一一个分支就是在  40174C  这个地方了 ,  因此我们重复上面的步骤跟到  401744,  将  EAX  改成  1,  到  40174C  的时候继续执行下一条指令 .  我们来  G  一把 .


   Bingo!!! ACDSee '95 告诉我们它已经被注册了 . 但是别得意 , 看看它的标题栏吧 , 还是 [unregistered] 的呢 .      :(


  这是怎么回事呢 ? 不难想到 , 还有别的判断 . 是不是还要跟呢 ? 不用啦 . 既然我们找到了判断子程序 , 就可以直接改它了 . 根据我们上次的经验 ,EAX 是 1 的时候表示名字和注册号是相符的 , 那么我们把程序的返回值 EAX 改成恒为 1 就可以了 .


  重新跟踪 , 到 40173C 这个地方按下 F8 开始 . 然后进入程序 , 我们用 Ctrl+ 光标下键移动代码 , 到 4035FE 处 :


   0137:004035FE      TEST    EAX,EAX


   0137:00403600      MOV    EAX,00000001


   0137:00403605      JZ     00403609


   0137:00403607      XOR    EAX,EAX


   0137:00403609      POP    EDI


   0137:0040360A      POP    ESI


   0137:0040360B      POP    EBX


   0137:0040360C      ADD    ESP,4


   0137:00403612      RET


  如果你有一些反汇编 C++ 编译出的 EXE 的经验 , 就可以看到这实际是 :


   return(fValid?1:0);


  的编译结果 . 可以看到 ,403605 是一个关键的地方 , 就是这条该死的指令把可爱的 EAX 弄成了 0. 知道这个就好办啦 . 我们把它跳过去 :


   :a 403605


   0137:00403605 jmp 403609


   0137:00403607( 按回车结束汇编 )


  然后重新执行一次 .HOHOHO! 这次标题栏也变成注册版的样子啦 . 拆解工作完毕 !


  回到 DOS 下 , 把我们的成果写回 EXE 里面就可以了 . 刚才我们改的是把 JZ 改成了 JMP, 也就是说 , 把


   B8 01 00 00 00 74 02 33 C0 5F 5E 5B


  改成了 :


   B8 01 00 00 00 EB 02 33 C0 5F 5E 5B


   ( 黑话叫做 "74  改  EB"    :)


  为什么要把要查找的串弄得这么长呢 ? 直接把 "74 02" 替换成 "EB 02" 不就得了吗 ? 不是这样的 . 在 EXE 里面可能有许多个 "74 02", 因为 JMP$+2 是一条太普通不过的指令了 , 而一个 EXE 里面有多个


     MOV    EAX,00000001


     JNZ    @HERE+2


     XOR    EAX,EAX


     POP    EDI


     POP    ESI


     POP    EBX


  的机会就少得多了 , 一般情况下只有一处 , 这就是我们要改的一处 .


  把特征串取得太长了也没什么实际意义 , 反而会浪费地球上有限的纸资源 , 地球只有一个 , 是我们的家 , 我们要爱护它 ......


  好 , 用一个你喜爱的二进制文件编辑器改掉它 . 然后重新执行 ACDSee'95.


  酷 !  大功告成啦 .  赶紧找个  MM  吹嘘一把  ......     ;)


  爽过以后总结一下经验 ,  下次泡的时候就是老枪了 :


  经验一 :  你现在知道了注册码的判断步骤 ;


  经验二 :  你知道了程序可以用  GetDlgItemText  和  GetWindowText  取得


      在  Edit Box  中用户输入的数据 ;


  经验三 :  你知道了程序判断注册号是否合法的地方可能不止一处 ,  但是一


      般都用同一个子程序来完成检验功能 ;


  经验四 :  你知道了取得替换码的一些原则 :  即  ---  不要太长也不要太短 .


    
    
     
    
    
     

相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么

文章评论
发表评论

热门文章 去除winrar注册框方法

最新文章 比特币病毒怎么破解 比去除winrar注册框方法 华为无线路由器HG522-C破解教程(附超级密码JEB格式文件京东电子书下载和阅读限制破解教UltraISO注册码全集(最新)通过Access破解MSSQL获得数据

人气排行 华为无线路由器HG522-C破解教程(附超级密码JEB格式文件京东电子书下载和阅读限制破解教UltraISO注册码全集(最新)qq相册密码破解方法去除winrar注册框方法(适应任何版本)怎么用手机破解收费游戏华为无线猫HG522破解如何给软件脱壳基础教程