新手破解练习Crackme160之082 - ultraschall
原程序无法运行, 依照大佬的方法将原文件用UE打开在00000241h处的4A(J)改成42(B), 保存后即可正常运行
-
暴力破解, OD载入修正后的程序, 搜索框没任何数据, PEID分析可知程序直接是汇编写的, 所以我们直接OD分析代码, F9运行程序, 输入用户名系列号点注册, 弹出错误框, 这时OD点暂停(F12), 这时在内存右侧数据区下翻找到第一次出现"Registration Code.."错误信息第一次出现的那行, 看到的内存地址是00403115, 我们先记住这个地址, 重新运行程序(ctrl+F2), 在下面的内存数据区左侧ctrl+G, 输入00403115, 直接定位到提示信息处, 点击第一位"52", 右键->断点->内存访问, 然后我们输入用户名系列号点注册, 成功在52处断点停下, ctrl+F9运行到retn, F8返回到上一层, 一直重复操作直到程序运行了0040xxxxx地址段为止, 最终运行到00401339, 往上看一堆db xx和jmp xxx的东东(后来看了大佬的解文才知道这些叫做"花指令",是用来反编译的混淆代码的手段), 我们先不管这些乱的代码, 继续往上看到了0040132A处有关键字"MessageBoxExA"这就是弹框的方法, 我们继续向上找到弹框的内容入参(重点找push xx命令), 我们在最前面一个push处下个断点(004012E0 push ecx处), 重新输入信息点注册, 成功在断点处停下, F8往下执行, 在004012E9处看到了错误信息ebx, 基内存值正好就是00403115, 我们需要想个办法将这个地址改成00403137(成功信息的内存地址), 004012E9处, ebx = ebx + 0x0040300B = 0x00403115, 我们需要的是00403137, 那我们就需要再加0x22, 所以我们把0040300B改为0040302D, 即将004012E9处改为 add ebx, 0040302D这样我们就把ebx的值改为成功信息的内存地址值了, F9运行, 看到提示信息已经变成功信息了, 先别点确定, OD中先保存, 不然程序直接退出了, 需要重新再来一遍_, 我们运行保存的程序, 随意输入信息点注册, 看到了成功的信息, 到此暴破成功~
-
正常破解, 由于程序中一大堆花指令, 正常破解就放弃了, 以后学会了继续研究, 这里附上大佬的注册机代码: keygen.c
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int getSN1(char * name);
int getSN2(char * name);
int testSN1(long sum_name);
/// 伪指令结构
struct Instruction {
char opcode;
DWORD operand1; /// and result
DWORD operand2;
WORD next_ip;
};
int main(int argc, char** argv) {
char name[256];
printf("Input your name: ");
gets(name);
getSN1(name); //// 方式1, 碰撞测试
//getSN2(name); //// 方式2,加双前导 0
getchar();getchar();
return 0;
}
unsigned long xor_base[] = {0xD4E1C094, 0xFF1F9811, 0x91FABBC8, 0x781D9410, 0x918FFABC};
int getSN1(char * name) {
char buffer[48];
memset(buffer, 0, 48);
/// name: 52pojie.cn
/// SN: 1557972636
int n = strlen(name);
if (n>20) {
n = 20;
}
strncpy(buffer, name, n);
long sum_name = 0;
for(int i=0; i<20; i++) {
sum_name += * ((long *)&buffer[i]); //// 将char* 当作 long* 取 name,一次取4个字符
}
int count = testSN1(sum_name);
if(count == 0) {
printf("SN: no result.\n");
}
return 0;
}
int getSN2(char * name) {
char buffer[48];
memset(buffer, 0, 48);
/// name: 52pojie.cn
/// SN: 001524614812
int n = strlen(name);
if (n>20) {
n = 20;
}
strncpy(buffer, name, n);
//// SN处理,SN 前导 0 不影响数值大小
buffer[21] = '0'; /// CrackMe 中对 name 操作时取到了 SN 最前面两个字符
buffer[22] = '0'; /// CrackMe 中对 name 操作时取到了 SN 最前面两个字符
long sum = 0;
for(int i=0; i<20; i++) {
sum += * ((long *)&buffer[i]); //// 将char* 当作 long* 取 name,一次取4个字符
}
// long xor_check = 0;
// for(int i=0; i<5; i++) {
// xor_check ^= xor_base[i];
// }
long xor_check = 0x53968DE1; //// 5 个整数的 Xor 结果值
// printf("xor check: %08X\n", xor_check);
sum ^= xor_check;
//// SN处理,SN 前导 0 不影响数值大小
printf("SN: 00%lu\n", (unsigned long)sum);
return 0;
}
/*
* SN 前两位碰撞测试
*/
int testSN1(long sum_name) {
char sn[16];
//long sum0 = 0xE652C233;
int n = 0;
long sum0 = sum_name;
for(int i=9; i>=0; i--) {
long k = i+0x30;
long sum1 = (k<<24) + (k<<16);
for(int j=9; j>=0; j--) {
long m = j + 0x30;
long sum2 = (m<<24);
long sum3 = sum0 + sum1 + sum2;
long sum = sum3 ^ 0x53968DE1; /// xor_check
//// 有前导 0 时, 分情况格式化
if(i==0) {
if(j==0) {
sprintf(sn, "00%lu", (unsigned long)sum); /// 这一种情况与 getSN2() 方式一致
} else {
sprintf(sn, "0%lu", (unsigned long)sum);
}
} else {
//// 没有前导 0 时,直接输出
sprintf(sn, "%lu", (unsigned long)sum);
}
//printf("%c%c: %s\n", k, m, sn);
if(((sn[0]) == k) && ((sn[1]) ==m)) {
//printf("%c%c: %s\n", k, m, sn);
printf("SN: %s\n", sn);
n++;
}
}
}
return n;
}
运行结果示例:
Input your name: abcde
SN: 2127102478
SN: 1657274894
SN: 02144010766
SN: 002043347470
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号