程序是使用delphi编写的 无壳
分析程序
整个程序分为两部分 一个是序列号+用户名 一个是单纯的序列号 我们需要把两个部分都解出来
首先来解决序列号部分
分析Serial
随便输入一组错误的序列号 程序弹出一个失败的提示框
那么首先可以从这个字符串入手 载入OD
找到字符串之后反汇编窗口跟随 可以看到在错误的提示上面有一个正确的提示 和一个关键跳转42F4D5,如果不等于0就跳转到输出错误的地方,正确的话就输出congratz!
再往上会看到一个比较函数 而关键跳转就是根据这个函数来执行的 所以我们在这个函数上下断点 输入一个错误的序 列号 然后等待程序的断下,这里我们输入的是111111111
根据传入的参数可知 函数将eax和edx进行比较 然后根据比较的结果进行跳转 所以第一个序列号是一个固定的硬编 码 Hello Dude!
输入 Hello Dude! 程序弹出正确提示 序列号部分完成
分析Serial/Name
先随意输入一点数值,看回显
这里输出sorry…..通过字符串定位函数
下断点运行
首先检测用户名长度是否大于等于4,如果不是则提示错误
接着是用户名的计算部分 也是唯一一处有用的计算部分 前面虽然也有对用户名进行计算 但是并没有采用计算出来的 结果。计算过程如下 首先取出用户名的第一位,乘以0x29。然后再乘以2。保留结果。
接着,将计算的结果转为字符串,然后和实现准备好的字符串进行拼接,结果为 CW-4018-CRACKED 这个就是序 列号,也就是说序列号是根据用户名动态生成的。
然后与输入的serial比较
注册机
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include <stdlib.h> #include <windows.h> int main() {
char key1[3] = "CW"; char key2[8] = "CRACKED";
char username[10] = { 0 }; printf("请输入用户名 长度必须大于等于4:"); scanf_s("%s", username, 10);
if (strlen(username) < 4) 验证结果 { printf("长度必须大于等于4,请重新输入\n"); }
int username1 = username[0]; int result1 = (username1 << 0x3) - username1;
int username2 = username[1]; result1 = (username1 << 0x4) + result1;
int username4 = username[3]; int result2 = username4 * 0xB;
int username3 = username[2]; result2 = (username3 * 0xE) + result2;
int result3 = username1 * 0x29 * 2;
char key[50] = { 0 }; sprintf(key, "%s-%d-%s", key1, result3, key2);
printf("密钥为:%s\n", key); system("pause"); return 0; }
|