硬编码寻找序列号(二)
使用工具
- OllyDbg 1.10原版,简称
OD
; OD
汉化
和插件
均来自互联网;- CrackMe来自互联网,仅供学习使用;
- 文中特殊数字均是
HEX
,为了书写方便采用DEC
;
逆向思路
首先,打开软件到处点点,逆向一个软件起码要会用吧,不会用就没必要说逆向了;
倒入
OD
开始分析:首先按下
Ctrl + A
让OD
分析一下代码;接着按下
Ctrl + N
查看使用了哪些API
,咦,发现可疑函数:很好的开始,在
GetDlgItemTextA
函数上设置断点,然后去断点窗口
双击断点进入反汇编窗口
给断点设置备注,这是一个好的习惯,请保持;然后
F9
运行程序,“随便输入” 一些字符后点击验证,可以随便输入,但请记住它;程序断在了设置断点的 API 的行首,在堆栈窗口可以看到 API 的各种参数,而参数 Buffer 里存放着函数返回的数据,选中 Buffer 右键
数据窗口中跟随
,可以看到,由于断点中断在了函数的第一行,所以这个地址里什么也没有:接着按下 Ctrl + F9 或点击菜单栏的调试选项并选择
执行到返回
,然后发现 Buffer 对应的地址里有数据了,并且是我们输入的字符串;在上一步中,我们
执行到返回
,那就意味着接下来登场的将会是RETN
了,按下 F8,返回到调用 API 的程序,哇,密密麻麻全是汇编语句,往下翻了翻,也没发现什么关键字、有用的信息,接着F9
运行,直接弹出了错误信息:看来此路不通啊,但是“程序给我们关上了一扇门,同时又开了一扇窗”,没错,就是它,弹窗,在最开始的函数列表中也有它的身影
MessageBoxA
,那就从它入手试试;禁用
GetDlgItemTextA
并设置MessageBoxA
断点,重新运行程序,输入并运行程序后,拦截到了即将要弹出的信息,信息显示在堆栈窗口:如果程序继续运行,将弹出
错误!
弹窗;堆栈窗口的顶部显示的是调用信息,包括调用地址、返回地址等
堆栈顶端,也就是当前
ESP
指向的堆栈中则是调用地址,也就是说这个地址调用了MessageBoxA
这个API
,根据程序的流程:程序经过比较之后,发现序列号不对,所以调用MessageBoxA
并弹出错误窗口。
按照这个逻辑,如果跟随调用地址,是不是就能找到程序进行比较的代码?那还等什么,右键堆栈顶端的地址(堆栈中被标注黑色背景的地址就是堆栈顶端)选择反汇编窗口中跟随
,就来到了调用MessageBoxA
的程序,查看上面的代码,发现了一些端倪:上面有一个
JNZ
跳转进来,从而调用了MessageBoxA
,所以弹出了错误弹窗,而JNZ
的下面还有一个MessageBoxA
,那可以猜测,如果不跳转继续向下执行,很有可能弹出的就是注册成功的弹窗,JNZ
根据ZF 标志位
进行跳转,如果修改ZF 标志位
为1
,就可以验证一下猜测是否正确,如何修改呢,继续往上翻代码,嘿嘿,发现一个有用的东西GetDlgItemTextA
,在调用地址双击数据窗口设置CC断点
,重载程序输入并运行程序后,在最后设置断点的地方停了下来,那下面就是要执行的代码了,分析一下看能不能找到隐藏的序列号:
才分析了几行代码,有一种上了恶当的感觉,感觉它在转移某些内容,就暂且将它转移的内容称为“可疑字符串”:
不管了,继续分析,依然没有收获:
直到分析了一个轮回,终于有了收获,程序会用我们输入的序列号的每一个字节的机器码减 14 后,和指定的机器码进行比较:
而我们利用
MessageBoxA
断点,分析的JNZ
的跳转条件是:如何让条件成立呢?恰恰在我们没有分析到的代码,因为我们输入的序列号是错误的,所以正确的代码根本不会执行,更谈不上分析了:
在这里,如果是正确的序列号,那么每次比较完成后,
EBP - 10
和EBP - 34
作为两个计数器,它们会正确的同时自增,在最后的比较长度时也就会相等了;
所以,正确的序列号是什么呢?
- 在比较的位置设置断点,获取每次比较时给定的字符的机器码,然后加上 14,最后转为 ASCII 码,就是正确的序列号;
- 获取到的给定字符的机器码:
1D 1E 1F 44 61 51 3C 5B 36 55 51
; - 字符的机器码加 14 之后的值:
31 32 33 58 75 65 50 6F 4A 69 65
; - 转换为 ASCII 码后的值:123XuePoJie;
最后,完整的分析图: