程序:
运行
这是一个注册机
随便输入点内容,点击 Check
弹出错误的对话框
逆向:
用 OD 载入程序
在文本框处下断点
按 Alt+B 查看断点
这个断点在动态链接库那里
跑一下程序,输入内容,点击 check
程序停在断点处
在动态链接库的断点处不能进行跟踪和修改
按 Alt+F9 让其回到程序的部分
这里上下都有一个文本框
这里的 eax 的值为 4,是 test 的长度
按 F8 往下走
又进入到刚才的地方,这次是从第二个文本框进来的
按 Alt+F9 回去
这里 eax 的值为 5,是 12345 的长度
按 F8 往下走
这里调用 lstrlenA 函数获取输入的 test 的长度,为 4
这三条指令,xor esi,esi 将 esi 清零,这个 esi 可能有很大的用处
mov ecx,eax 将 eax 的值传给 ecx,而 ecx 是用来循环计数的,mov eax,1 将 eax 赋值为 1
接下来这一段是一个循环
走进这个循环
edx 被赋予 403038 上的值,就是那个 test,edx 中的 74,73,65,74 分别对应 test 的 ASCII 码值
eax+0x403037 等于 403038
就是把 test 的第一个 t 传给 dl
and edx,0xFF 将 edx 和 0FF 进行与运算
0FF 中的 FF 转换为二进制为 1111 1111,也就是后八位为 1,前面的数为 0
0FF 和 edx 进行与运算之后,使得 edx 后八位不变,也就是 74 不变;前面的 24 位全为 0
mov ebx,edx 将 edx 的值传给 ebx,就是把 74 传给 ebx
imul ebx,edx 将 edx 的值乘 ebx 的值再赋给 ebx,就是十六进制的 74 * 74,为 3490,也就相当于 t * t
然后再把 ebx 的结果加到 esi 中
mov ebx,edx 又把 edx 的值传给 ebx
sar ebx,1 对 ebx 进行偏移计算,ebx 向右偏移 1 位,相当于除以 2,74/2 等于 3A
add ebx,0x3 把 ebx 的值加 3,即 3A+3,等于 3D
imul ebx,edx 将 ebx 乘以 edx,再存到 ebx 中,3D * 74 = 1BA4
将 ebx 的值减去 edx 的值,再存入 ebx,1BA4 - 74 = 1B30
然后再把 ebx 的值加到 esi 上,1B30 + 3490 = 4FC0
add esi,esi 将 esi 的值乘以 2
inc eax 将 eax 的值加 1,dec ecx 将 ecx 的值减 1
捋一下,esi 这一次循环的值为 ['t'*'t' + ('t'/2 * 3)*'t' - 't'] * 2
每次循环,esi 的值都会在原本的基础上运算
结束循环之后
循环过后通过 cmp 指令把 esi 的值和地址 403138 上的值进行比较
如果值相等的话就不执行 jnz 跳转,如果不相等的话就执行跳转,如果 jnz 执行跳转的话,将跳过弹出成功的对话框
这个 403138 是 GetDlgItemTextA 函数获取字符串后存放的缓冲区,值为 12345
也就是说,那个 cmp 指令是把循环后 esi 的值和 12345 进行比较
12345 那个文本框是输入注册码的,循环后 esi 的值可能是根据 test 生成的某个注册码,然后进行对比
所以此时 esi 存放的值是根据 test 生成的注册码
接下来要做的就是获取 esi 的值,也就是根据 test 生成的注册码
找个空白区域写内嵌补丁
按 Alt+M 查看数据段的地址
为 439000
把 439000 出开始的数据段作为一个临时存放区
修改 jnz 跳转指令
让其执行跳转的时候跳到内嵌补丁那
在内嵌补丁这添加一条跳转指令,让其跳回到原先 jnz 跳转到的地方
接下来修改 MessageBox 的内容,让其弹出的内容是注册码
第二个参数是消息框的内容,就是这第二个入栈的内容
修改为显示注册码的内容
运行程序
没有显示正确还是错误,而是显示了一个乱码
编写注册机
C:
#include <stdio.h> #include <string.h> int main(void) { int i, len, result = 0; char str[] = "test"; len = strlen(str); for (i = 0; i < len; i++) { result += str[i]*str[i] + (str[i]/2 + 3)*str[i] - str[i]; result *= 2; } printf("%d ",result); return 0; }
运行结果
十进制 571152 的十六进制为 8B710