注:此文章仅供学习使用,造成的一切后果与作者无关!!!
样本概况

程序信息
它是需要注册的一个状态
一般这种情况都会有两种思路
1, 暴力破解(脚本小子)
2, 序列号解密(需要屏蔽网络验证)
分析环境
系统:Win 7 32为专业版
使用工具:IDA,OD,(PE/010Editor),VS2019
分析过程
暴力破解
提取关键字符串
一般在没有序列号的情况下随机输入是这样的

这个时候复制它的报错信息
1 | --------------------------- |
使用OD打开010Editor

让他运行起来(由于之前折腾过的原因我这里,点击运行后会直接弹出注册窗口,这个无所谓,只要你能找到这个窗口随机输入一个序列号,复制他的报错信息就可以了)
注:注册窗口在(Help–>About…)

右击反汇编界面–>查找–>所有参考文本字串

在弹出的(文本字串参考位于)窗口右击–>查找文本,,,输入之前提取的字符串(只需要关键字符串即可,如图)

找到之后双击进入代码区域

双击后会看到自己搜索的字符串

找到关键函数
要知道,搜索的字符串是是序列号错误的情况下输出的信息,所以需要找到什么地方判断序列号是错的从而跳转到该错误的信息处
当鼠标左键点击到push的字符串的那句代码上时下面的提示框显示了该语句来自于那个地址的跳转,这时可以右击该地址–>单机(转到jnz来自)

跳转到的地方

可以看到这一块都是比较后跳转,不用关系这些是往哪跳的,主要找到是哪跳过来的
接下来继续找到跳转到这里的的地方

同样的方法继续,右击该地址–>单机(转到jnz来自)

这里有个关键信息 CMP edi,0xDB,要注意到跳转后的地方有赋值个EDI的指令
继续

在这块地方可以得知EDI是call 00409C9B 这个函数的返回值,(说明这个函数是关键)
更改指令
先不用关注这个函数到底干了啥,现在掌握的基本只要确认DB的等于或者不等会得到什么样的结果(我这里已经试过了不等于DB代表的就是错误)
本来一开始是想改cmp esi,0xBD这条指令后面的跳转给Nop掉,但是前面有几个网络验证(俩三个call),所以我准备在函数返回值出来就写上跳转到cmp esi,0xBD这条指令的的跳转后面,地址是0x00DD592C(就是你要跳转的地方的最前面那串16进制)

然后运行之后你会看到,“成功了”

当然OD关了之后就会失效了,要把更改保存下来
保存更改



这样不能算完全破解,因为每次启动都会弹出注册框(虽然随便输入也能用,但是就是不爽)
所以继续分析
完美破解
回到刚刚地方分析那个关键函数

打上断点,运行之后步入看一下,主要关注的是DB是怎么返回的
一进来就看到的是网络验证,这层验证可以使用jmp直接跳过

由于不知名的bug 导致我换了一个OD,分析是一样的
更改jmp

继续往下分析

把每个比较的跳转都看一下跳到那
运气比较好,第一个比较0x2D就直接跳到了需要的返回值DB

进入关键函数,一般里面还有一层,直接回车即可(这个函数要记住,等下解密序列号的时候要详细分析这个函数)

接下只要把这个关键函数的返回值改成一直返回0x2D即可
进入函数之后更改如下

更改完成后继续将程序运行起来,发现又走到一个网络验证

这个网络验证的返回值为-1,直接把返回值强行修改为1,(尝试一下,看看结果如何)
同样进入这个函数,进入之后更改如下

再次将程序运行起来
这个时候发现成功了

再次保存,不过这次保存要整个保存,因为修改的地方太多(不然每修改一个地方就保存一次)

一路确定之后,在下图窗口右击保存,(取一个名字,确定保存即可)

之后就能直接打开了

当然还有重要的一点,如果其中涉及重定位操作,最好把重定位标志去除
解密序列号
解密序列号的话就不能像暴力破解哪有直接修改源代码,那是脚本小子干的事(当然网络验证还是得这么改)
接下来打卡原版的(未更改的010Editor),
回到如下界面

进入之后长这样

由于这个函数稍微有那麽一丢丢长,同时我也写上了注释,直接将他复制出来,以便查看
函数的解析
1 | 013BDBC0 55 PUSH EBP ; \ |
关键部分
序列号(字节)之间的关系

把这两个函数带入参数分别解析(K是输入的(密码/序列号)K[0]代表第一个字节,例如:112233445566778899AA,K[0]就等于 11)
函数1 (00407644)参数(K[0],^K[6])
1 | 013BD0B0 /> \55 PUSH EBP |
函数2 (004083C8)参数 ( ((K[1]^K[6]) & 0xFF) * 0x100) + (K[2]^K[5] & 0xFF)&0xFFFF)
1 | 013BD020 /> \55 PUSH EBP |
代码转换
根据以上信息,可以通过c++代码运算得到序列号
1 | int main() |
根据以上代码算出来的序列号(序列号字节之间的对应关系)没有问题,但是下面还要分析与账户之间的对应关系
账户与序列号之间的关系

1 | 013BDD98 . FF77 20 PUSH DWORD PTR DS:[EDI+0x20] ; 返回值(商),第四个参数 |
使用加密代码
这里地方要转换成c++代码稍微有点麻烦,因为有一个加密,这里我直接用IDA打开,用IDA分析这个加密函数,然后直接拿过来用
注:如果要通过IDA找到该函数的地址需要经过地址转换,随意这里最好使用默认基址(把重定位标志去掉),而且使用IDA打开010Editor,需要几分钟时间,需要耐心等待
完全打开的状态:左下角那串字符不在动了
IDA打开

或者是这个样子

也可能是这个样子

这种状态可通过空格键(Space)切换
013BDDB6 . E8 955004FF CALL 010Edito.00402E50 ; 这个是用户名的加密,看多了会掉头发
函数调用地址 013BDDB6 在IDA界面按G搜索

点击OK后

双击进入后

再次双击后,会看到如下界面

然后直接按F5,会看到它被解析成C++代码

这个是后看一下,这个函数的代码是不是可以直接拿过来用
当往下看的时候,发现有一个四字节的数组操作
找数组元素

这个时候需要找到这个数组的,双击数组地址进入

可以看到这个数组在data段,地址是02E6418,这个时候可以通过OD找到这个数组的定义(元素)

找到的数组元素

把它复制出来(这里用到一个插件”数据转换“)

复制出来的元素
1 | { |
复制加密代码
回到IDA,之前还记得加密函数的第四个参数是四字节整数(013BDD98 . FF77 20 PUSH DWORD PTR DS:[EDI+0x20] ; 返回值(商),第四个参数),但是IDA分析的是char类型,需要给他改过来

改完之后全选后复制
1 | int __cdecl sub_13BD120(const char *a1, int a2, char a3, DWORD a4) |
注册机编写
现在开始写成自己的代码
注
1 |
|
运行测试
运行结果

把这串序列号和用户米输入试一下

然后发现网络验证失败,这个时候需要把网络验证给屏蔽掉,具体方法在暴力破解时已经简述
成功破解
屏蔽网络后发现就成功了,
