新手破解练习Crackme160之007 - aLoNg3x.2
暴力破解:
-
DarkDe分析
CancellaClick 00442B98 (试了一下这个应该只有清0的作用)
AboutClcik 00442CC8
RegisterzClick 00442F28
AgainClick 004430BC (这个是界面上没看到的隐藏按钮事件)
以上4处都先打上断点 -
什么都不想输, 直接点注册按钮, 进入00442F28这个断点, F8向下执行, 遇到第一个关键跳00442F64, 改为 jmp 00442FC2 直接跳转到成功分支, 成功干掉注册按钮, 保存~
-
上一步注册按钮成功隐藏了, 但又新显示出一个重试按钮, 好吧, 我们还需努力~
进入断点004430BC后发现跟注册按钮的写法完全一样, 接下来就同样操作, 第一个关键跳004430F6改为 jmp 0044315B 到成功分支, 保存测试完全搞定~
正常破解:
ctrl+F2或菜单上操作重新运行程序, 输入用户名abc, 注册码123, 点击注册, 断点处停下(上面4个断点还在), F8单步跟踪分析算法:
1). 00442F59处, 将注册码转16进制, 123=0x7B
2). 00442FB9处, 是用户名验证算法, 继续进入分析
3). 004429D7处, 判断用户长度是否<=4, 所以我们上面输入的abc不符合要求, 我们换成abcde与12345, 重来一遍, 12345=0x3039
4). 00442A03处, 循环计算ebx += user[0] * user[len-1] * edi
5). 下面便是一堆运算这里不再列出, 看具体代码
6). 然后比较ebx 与 code(0x3039), 即ebx就是答案了
从上面上步骤分析可知, 其中还有个未知数edi, 具体分析得知, 他来自方法入参eax, eax又来自内存地址[0x445830], 经调试, 每次这个值都为0, 那我们就需要查什么时候这个值才会变, 于是我们右键查找所有常量, 查到的结果有10个之多, 其中有8个会对其赋值,
00442F86 mov dword ptr ds:[0x445830],eax ;;这个可疑先标记
00442FB4 mov eax,dword ptr ds:[0x445830] ;;这个上读取, 不是
00442FEB mov dword ptr ds:[0x445830],eax ;;这个双击进去看到eax=0, 不是
00442FF4 mov dword ptr ds:[0x445830],eax ;;这个双击进去看到eax=0, 不是
00443007 mov dword ptr ds:[0x445830],eax ;;这个双击进去看到eax=0, 不是
00443118 mov dword ptr ds:[0x445830],eax ;;这个在AgainClick按钮事件中, 也不是
0044314D mov eax,dword ptr ds:[0x445830] ;;这个上读取, 不是
004431C7 mov dword ptr ds:[0x445830],eax ;;这个也是在AgainClick中, 且eax=0, 不是
004431D0 mov dword ptr ds:[0x445830],eax ;;这个也是在AgainClick中, 且eax=0, 不是
0044320A mov dword ptr ds:[0x445830],eax ;;这个也是在AgainClick中, 且eax=0, 不是
所以只有第一个才可是有用的, 但这个是在失败分支中, 也就是说, 我们第一步得先失败一次, 不然永远都无法成功, 我们把注册码改成非数字的6位以上字符串a12345进入失败分支分析算法:
1). 00442AB4处, 判断长度是否<=5
2). esi = 0x37B, ebx=len, edx = [eax-0x8] = 2
3). 循环计算
直接开始写注册机代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char x[21] = {0};
char y[21] = {0};
int lenx=0, leny=0, v=0;
while(lenx < 5) {
printf("请输入用户名(5位以上): ");
scanf("%s", x);
lenx = strlen(x);
}
while(leny < 6) {
printf("请输入错误注册码(不能全数字6位以上): ");
scanf("%s", y);
leny = strlen(y);
v = atoi(y);
if(v > 0){ continue; } //说明是数字
}
int edi=0x37B;
for(int i=1; i<leny; i++){ edi += (y[i] % 0x11 + 1) * y[i-1]; }
edi %= 0x7148; //得到edi
printf("EDI为: %d\n", edi);
//开始计算注册码
int ebx = 0;
for(int i=0; i<lenx; i++){
for(int j=lenx-1; j>=0; j--){
ebx += x[i] * x[j] * edi;
}
}
ebx %= 0xA2C2A;
printf("EBX为: %d\n", ebx);
ebx -= 1;
int code = 0;
//ebx -1 == code / 0x59 + code % 0x50;
code = ebx * 0x59; //取最大值那个
code = code - (code % 0x50) + 1; //同时满足%0x50条件
printf("正确注册码为: %d\n\n", code);
//这是所有的
for(int i=(ebx-0x50)*0x59; i<ebx*0x59; i++){
if(i / 0x59 + i % 0x50 == ebx) { printf("找到:%d\n",i); }
}
getchar();getchar();
return 0;
}
操作流程为:
- 输入5位以上用户名
- 输入6位以上非纯数字的注册码
- 点击注册按钮, 弹出错误信息, 点确定, 注册码变为0
- 输入正确的注册码, 点注册按钮, 注册按钮隐藏, 重试按钮显示
- 输入6位以上非纯数字的注册码(重复操作2.~4.步)
- 点击重试按钮, 弹出错误信息, 点确定, 注册码变为0
- 重新输入刚才正确的注册码, 点重试按钮, 重试按钮也隐藏
- 后记: 查看取消按钮代码可知, 作者还隐藏了小惊喜在这里, 这个按钮事件不光只是注册码置0的功能, 还有个成功分支, 条件是当用户名与注册码相同时进入~ 测试可喜提两个提示框
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号