硬编码寻找序列号(三)
使用工具
- OllyDbg 1.10原版,简称
OD
; OD
汉化
和插件
均来自互联网;- CrackMe来自互联网,仅供学习使用;
- 文中特殊数字均是
HEX
,为了书写方便采用DEC
;
逆向思路
第一部分
首先,打开软件到处点点,逆向一个软件起码要会用吧,不会用就没必要说逆向了;
这个 CrackMe 不一般,有两个部分,两个按钮,那就分两部分分析喽(这句话绕不绕):
倒入
OD
开始分析:首先按下
Ctrl + A
让OD
分析一下代码;接着按下
Ctrl + N
查看使用了哪些API
,咦,发现可疑函数:很好的开始,在
GetWindowTextA
函数上设置断点,然后去断点窗口
双击断点进入反汇编窗口
给断点设置备注,这是一个好的习惯,请保持;然后
F9
运行程序,“随便输入” 一些字符后点击验证,可以随便输入,但请记住它;程序断在了设置断点的 API 的行首,在堆栈窗口可以看到 API 的各种参数,而参数 Buffer 里存放着函数返回的数据,选中 Buffer 右键
数据窗口中跟随
,可以看到,由于断点中断在了函数的第一行,所以这个地址里什么也没有:接着按下 Ctrl + F9 或点击菜单栏的调试选项并选择
执行到返回
,然后发现 Buffer 对应的地址里有数据了,并且是我们输入的字符串;在上一步中,我们
执行到返回
,那就意味着接下来登场的将会是RETN
了,按下 F8,返回到调用 API 的程序,多么令人兴奋的内容,这么简单吗,会不会有诈?那就分析一下,看看到底是啥:
看来第一部分很简单,逻辑简单粗暴,只要不对直接弹出错误;
第一部分到此结束。
既然第一部分这么简单,那难点肯定在第二部分,去看看!
第二部分
倒入
OD
开始分析:首先按下
Ctrl + A
让OD
分析一下代码;接着按下
Ctrl + N
查看使用了哪些API
,还是那个可疑的函数:很好的开始,在
GetWindowTextA
函数上设置断点,然后去断点窗口
双击断点进入反汇编窗口
给断点设置备注,这是一个好的习惯,请保持;然后
F9
运行程序,“随便输入” 一些字符后点击验证,可以随便输入,但请记住它;程序断在了设置断点的 API 的行首,在堆栈窗口可以看到 API 的各种参数,而参数 Buffer 里存放着函数返回的数据,选中 Buffer 右键
数据窗口中跟随
,可以看到,由于断点中断在了函数的第一行,所以这个地址里什么也没有:接着按下 Ctrl + F9 或点击菜单栏的调试选项并选择
执行到返回
,然后发现 Buffer 对应的地址里有数据了,并且是我们输入的字符串;在上一步中,我们
执行到返回
,那就意味着接下来登场的将会是RETN
了,按下 F8,返回到调用 API 的程序,哦豁,好像没啥有用的内容,等等,下面还有个GetWindowTextA
,对对,我们输入了用户名和密码,那就得获取两次,而第一次获取的是密码,那就F9
再运行程序;是的,又获取了一次,而这次获取的是用户名,执行到用户代码,果然是下面这个
GetWindowTextA
,那下面就是比较的代码了呗,毕竟它位于获取和弹窗之间;那就分析一下它的流程:
第一行
TEST EAX, EAX
不迷茫,TEST EAX, EAX
表示检查EAX
自身是否为 0,而第二行的JE SHORT 硬编码寻.0040167E
指向了一个MessageBoxA
,那就说明EAX
很重要,既然弹窗提示的是必须输入用户名才可以
,那它不是用户名的长度是什么,况且EAX
里的数据刚好和用户名长度相同;接下来,它对用户名做了一系列的运算,并把运算的结果放到了指定的内存中,暂时还不知道它想干嘛:
同样的,又对输入的假序列号进行了一系列运算,并把运算结果放到了指定的内存中,不过相对于用户名,序列号的处理比较简单,只是进行了除法运算,并存储了余数:
直到序列号运算完毕,一个
JMP
跳下来,分析之后,终于知道了它要干什么:原来,它上面进行的一系列运算,是为这一步的比较做准备;
至此,终于分析出了结果:这里没有硬编码,而是软编码,序列号是根据用户名计算出来的
至于计算的规则:
- 用户名的运算规则:用户名的下标从零开始,每个字节依次和
A
进行除法运算,然后用余数和下标异或之后的值加 2; - 序列号的运算规则:序列号的每个字节和
A
进行除法运算,然后用余数和用户名运算的结果进行比较; - 序列号的算法:任意数字和
A
进行乘法运算,并加上用户名每个字符运算的结果就是这个用户名对应的序列号,运算的结果必须可以转为ASCII
码中的数字; - 例如:
用户名: yang
运算的结果:03 08 04 02
序列号算法:
5 * A + 3 = 35
4 * A + 8 = 30
5 * A + 4 = 36
5 * A + 2 = 34
转成 ASCII:5064
- 用户名的运算规则:用户名的下标从零开始,每个字节依次和