初始破解之爆破

爆破就是通过修改软件机器码(汇编代码)达到绕过注册验证环节的目的

 

爆破中修改机器码通常都是修改跳转指令,而跳转指令实现与否多和标志寄存器相关(jmp,call除外),所以这里不得不复习下关于标志寄存器的内容:

标志位寄存器

标志位寄存器能够设置各位标志位,但某个位是否被置位或复位依赖于计算结果或别的事件的发生。我并不想在这里讨论标志寄存器中所有的标志位,我只讨论一些重要的位:

ZF(0标志位)
当计算结果是0的时候,就会将它置位(“比较”实际上是一个不保存结果的减法运算,它只改变ZF)

SF(符号位)
如果被置位,那么就标志计算结果是一个负数

CF(进位标志位)
CF会保存计算过程中在最左边多出来的位(译者注:著者描述得并不完全正确,只要计算结果的最高位产生了一个进位或借位,CF就会被置位)

OF(溢出标志位)
它被置位说明计算过程中发生了溢出。机算结果超过当前计算位数所能表示的范围称为“溢出”。

其实还有很多的标志位,它们暂时对我们没什么用处,这里就不讨论它们了。

 

下面就是常用的跳转指令了:

条件跳转总汇

下面是所有的条件跳转指令,它们执行与否都依赖于相关标志位的状态。大部分条件跳转指令都拥有很容易记忆的名字,让你不用强行去记忆哪个位被置位时它才发生跳转。

例如:“如果大于等于就跳转”(jge)和“符号标志=溢出标志”一样,而“如果零就跳转”和“如果零标志=1就跳转”一样。

在下表中,“意思”指的是什么样的计算结果该跳转。“如果大于就跳转”意为:

cmp x, y
jmp 如果x比于y

-------------------------------------------------------------------
操 作 码 |             意    思            |   条   件    |
------------------------------------------------------------------
   ja    |           大于则跳转            | CF=0 且 ZF=0
-----------------------------------------------------------------
   jae   |         大于或等于则跳转        | CF=0
----------------------------------------------------------------
   jb    |            小于则跳转           | CF=1
----------------------------------------------------------------
   jbe   |         小于或等于则跳转        | CF=1 或 ZF=1
----------------------------------------------------------------
   jc    |      如果进位位被置位则跳转     | CF=1
----------------------------------------------------------------
   jcxz  |        如果cx的值为0则跳转      | CX=0
----------------------------------------------------------------
   je    |            相等则跳转           | ZF=1
----------------------------------------------------------------
   jg    |       大于则跳转(有符号数)    | ZF=0 且 SF=OF
----------------------------------------------------------------
   jge   |    大于或等于则跳转(有符号数) | SF=OF
----------------------------------------------------------------
   jl    |       小于则跳转(有符号数)    | SF != OF
----------------------------------------------------------------
   jle   |    小于或等于则跳转(有符号数) | ZF=1 或 SF!=OF
----------------------------------------------------------------
   jmp   |            无条件跳转           | -
----------------------------------------------------------------
   jna   |           不大于则跳转          | CF=1 或 ZF=1
----------------------------------------------------------------
   jnae  |       不大于或不等于则跳转      | CF=1
----------------------------------------------------------------
   jnb   |           不小于则跳转          | CF=0
----------------------------------------------------------------
   jnbe  |       不小于或不等于则跳转      | CF=1 且 ZF=0
----------------------------------------------------------------
   jnc   |      进位位没有被置位则跳转     | CF=0
----------------------------------------------------------------
   jne   |           不相等则跳转          | ZF=0
----------------------------------------------------------------
   jng   |      不大于则跳转(有符号数)   | ZF=1 或 SF!=OF
----------------------------------------------------------------
   jnge  | 不大于或不等于则跳转(有符号数)| SF!=OF
----------------------------------------------------------------
   jnl   |      不小于则跳转(有符号数)   | SF=OF
----------------------------------------------------------------
   jnle  | 不小于或不等于则跳转(有符号数)| ZF=0 且 SF=OF
----------------------------------------------------------------
   jno   |      未溢出则跳转(有符号数)   | OF=0
----------------------------------------------------------------
   jnp   |      奇偶校验位被复位则跳转     | PF=0
----------------------------------------------------------------
   jns   |   符号位为0则跳转(有符号数)   | SF=0
----------------------------------------------------------------
   jnz   |          不等于0则跳转          | ZF=0
----------------------------------------------------------------
   jo    |      溢出则跳转(有符号数)     | OF=1
----------------------------------------------------------------
   jp    |      奇偶校验位被置位则跳转     | PF=1
----------------------------------------------------------------
   jpe   |      奇偶校验位被置位则跳转     | PF=1
----------------------------------------------------------------
   jpo   |      奇偶校验位被复位则跳转     | PF=0
----------------------------------------------------------------
   js    |   符号位为1则跳转(有符号数)   | SF=1
----------------------------------------------------------------
   jz    |           等于0则跳转           | ZF=1
----------------------------------------------------------------

所有的跳转指令都需要一个操作数:即要跳转到的内存单元的偏移量。

 

比较指令

问题又来了,是生么影响标志寄存器呢,因为破解中通常在关键跳前面都有一个比较,正是这些比较影响(置位)了相关标志位。当然不是只有比较才能影响标志位,还有因为算术运算的进位,借位也会影响,但在破解中常见的还是比较。

1)test

test与逻辑与(译者注:即and操作码)的工作几乎相同,将两个操作数进行“与”运算并设置标志寄存器相应的位。但test不保存运算结果。test常用来像下面这个例子一样测试某个位:

test eax, 100b ;(后缀b表示这是一个二进制数)
jnz 跳转目的地

 

如果eax的右边第3位是1的话,jnz将会发生跳转。test操作码常常被用来测试一个寄存器的值是否为0:

test ecx, ecx
jz 跳转目的地

当ecx为0时,jz就会被执行而发生条转。

2)cmp

cmp的意思是“比较”。它会比较两个值(来自寄存器、内存或立即数)并且当它们相等时将ZF(0标志位)置位。与CF一样,ZF也是标志寄存器中的一个位。

 

 

好了理论知识已经完备了,下面实战破解一款小外挂程序(本例无壳)

1,载入OD-->搜索ASCII(查找所有参考字符串,查找UNICODE也可以尝试),

 

 2,来到有注册成功或失败字样的地方,双击就来到调用该字符串的地方了,这时如果感觉代码有点乱(不规则)可以右键分析下代码

我们可以看到在“软件已注册”上面有这样两句代码:

test al,al                                                      ;这里就是通过设置标志位从而影响下面一句跳转是否实现的比较了

je short QQ火拼斗.004580C1                  ;  怀疑是一处(功能)关键跳
mov edx,QQ火拼斗.004580EC                   ;  软件已注册

 

可以看到如果je实现了的话,含有“软件已注册”的代码段就不会被执行了,也就意味着可能就是软件注册失败了,所以我们可以尝试着把这处je该为相反的条件跳转:JNZ

强制让它执行到含有“软件已注册”的代码。

 

上面我们看到的是两个“软件以注册”的字符串,那么我们是不是两处都要修改呢?我也没有肯定的答案,改一处不行那就只有全改了

 

双击第二个字符串来到这里:

 

呵呵,是不是又看到了熟悉的比较指令:test 和紧接着的的条件跳转指令jnz了,和上一处不同的是:这处要是满足条件才跳到并执行含有“软件已注册”的代码,也就意味这不执行就可能是注册失败,所以无论如何我们都想让它跳过来(实现),所以我们可以尝试这该条件跳转jnz为无条件跳转jmp。

 

然后右键--->复制可执行文件--->选择所有修改--->保存文件即可! 

 

注意:这里是只有两个“软件已注册”,可能有的软件有很多像这样的提示,那么你是不是要一个一个的去改呢?据我的理解,之所以会有多个成功的字样,有可能是功能的限制,一个对应一个功能是否注册成功,所以我们也称这中挨个改跳的为功能爆破。当然如果功能字符串太多了的话将是一个很大的工作量,这是我们就需要找到影响整个注册机制的关键位置(关键跳),这样才能完美爆破。


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值