老文章档案 · 2003 年

Soft-ICE 实例起步( Windows 版)

天下资讯 · 破解文章 · 2003-10-14 · 作者:人气: · 出处:赢政天下整理收藏

为了以后说话方便 , 这里把 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 中用户输入的数据 ;

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

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

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

相关资讯:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

我为人人《《==》》人人为我

关于我们 |

帮助(?)|

广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright (C) 1998-2004 winzheng.com All Rights Reserved.

特别感谢 蓝芒科技 提供下载站及论坛服务器

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史