前言:这是来自看雪的一道题,年代久远。4nil前辈留下的一个crakeme。在此给出个人写得详细的,可以使新手从汇编到高级语言一一对应上的解析。希望不管是大佬还是新手,都可以来“刁难”我,提出问题,让我看看自己还有哪些不足,我会尽力回答的。
这是无壳版本(壳本身不难)。这道题的亮点在于:1.有多个导致挂的判断。2.无错误提示。3.有中间注册码,循环渐进的一个crackme。
爆破过程如下:
载入后输入name,Serial -> 鼠标右键 -> 中文搜索引擎 -> 搜索ASCII -> 发现” SHiT ... you entered the correct serial!”,下断点->往前翻找到004015A1的push下断 -> 从004015A1的push 一路F8下来,会发现0040162D的je short unpacked.00401682是关键跳转,
双击改变Z的值
继续F8,会弹窗
->在 0040162D 鼠标右键 -> 二进制用nop填充 -> 鼠标右键 -> 复制到可执行文件 -> 所有修改 -> 是 -> 鼠标右键 -> 保存文件,就可以了。
分析过程如下图:
算法如下:
#include <string.h> #include <stdio.h> int main() { char name[20], midserial[30], lastnum[6]; char* namef; int first,henNamef; int x,precondition; char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; unsigned long serial = 0, name_len = 0, serial_len, i, total = 0, temp; namef = ""; printf("\t|*------Keygen 4 Bigman's CrackMe#6------*|\n\n"); /* 前提条件: 1.name不能为空 2.name[1]*x(某个值) = 11CF余17,即11b8整除name[1] 3. 0x190<precondition(即此时的edi,图一)<0x2300 */ for (int i = 1; i < 10; i++) //图二上半部分 { x= 0x11b8 % i; if (x == 0) { printf("the first num you can use is:%d\n", i); } } printf("Input ur name:(not null)"); scanf("%s", name); name_len = strlen(name); precondition = ((0x2bc - (0x30 - (0x48 / name_len)) * 5) * 0x68) - 0xcf6c; if (precondition > 0x190 && precondition<0x2300) //图一 { for (i = 0;i < name_len;i++) //图二下半部分 { total += name[i]; } midserial[0] = 'T'; for (i = 0;i < name_len;i++) //图三部分 { temp = (((((name[i] ^ table[i * 3 - 1]) + ((total*i - total) ^ 0xffffffff) + 0x14d + (i + 3)*name_len*name[i]) % 10 + 0x30) ^ 0xadac)*(i + 2)) % 10 + 0x30; midserial[i + 1] = temp; } midserial[name_len + 1] = '\0'; temp = (name_len*total) % 0x64 + 0x30; //图四部分 ultoa(temp, lastnum, 10); strcat(midserial, "-"); strcat(midserial, lastnum); serial_len = strlen(midserial); for (i = 1;i < serial_len;i++) //图五部分 { midserial[i] = ((midserial[i] ^ 0x20) % 10 + 0x30); } printf("Serial:%s\n", midserial); } getch(); return 0; }