crackme006
crackme006
名称 | 值 |
---|---|
软件名称 | aLoNg3x.1.exe |
加壳方式 | 无 |
保护方式 | Serial |
编译语言 | Delphi |
调试环境 | Win10 64位 |
使用工具 | x32dbg,ida pro,PEid,DarkDe4 |
破解日期 | 2025-06-05 |
脱壳
1. 先用PEid查壳
查到无壳
寻找Serial
-
查询到编程语言为Delphi
-
导出Delphi符号表信息到x32dbg,用IDA Pro 打开程序
-
添加常见Delphi库的符号
常见Delphi库 |
---|
b32vcl |
bds2006 |
delphi |
d5vcl |
d4vcl |
c4vcl |
bds |
-
快捷键Shift+F5,如下图所示
-
导出map文件,
File->Produce file->Create MAP file...
-
安装SwissArmyKnife插件,导入上一步生成的map文件。x32dbg中
插件->SwissArmyKnife->Load->MAP file
-
用DarkDe4打开
PE文件
-
查看窗体结构
-
寻找flag,点击
About-Help
按钮,发现Flag:隐藏Cancella和Ok两个按钮
-
在DarkDe4中可以发现Cancella的id为:
2D0
,Ok按钮的id为:2CC
-
查找Cancella的调用
鼠标右键->搜索->当前模块->常数
输入2D0
-
选中
地址=00442EF2反汇编=mov eax,dword ptr ds:[ebx+2D0]
跳转到SetVisible函数的调用处,发现关键函数调用call <along3x.1.sub_442AF4>
-
分析函数调用
call <along3x.1.sub_442AF4>
mov eax,dword ptr ss:[ebp-4] ;取nome字符串首地址
call <along3x.1.unknown_libname_1145> ;获取nome字符串的长度
cmp eax,5 ;nome字符串长度与5比较
jle <along3x.1.loc_442B78> nome字符串长度小于等于5则字节,跳转到along3x.1.loc_442B78
mov eax,dword ptr ss:[ebp-4] ;取nome字符串首地址
movzx eax,byte ptr ds:[eax+4]; 取nome[4]的ASCII
mov ecx,7
xor edx,edx;情况edx
div ecx ;eax除以7,商存入eax,余数存入edx中
mov eax,edx;余数存入eax
add eax,2;eax = 余数+2
call <along3x.1.sub_442A20>;求eax的阶乘
mov esi,eax ;阶乘结果存入esi
xor ebx,ebx ;清空ebx
mov eax,dword ptr ss:[ebp-4];取nome字符串首地址
call <along3x.1.unknown_libname_1145>;nome字符串的长度
test eax,eax ;eax按位与
jle <along3x.1.loc_442B65> ;nome长度为0跳转到along3x.1.loc_442B65
mov edx,1 ;索引初值为1
along3x.1.loc_442B54: mov ecx,dword ptr ss:[ebp-4] ;取nome字符串首地址
movzx ecx,byte ptr ds:[ecx+edx-1];取nome[edx-1]的ascii
imul ecx,esi ;nome[edx-1]的ascii乘以阶乘
add ebx,ecx;nome[edx-1]的ascii乘以阶乘结果累加到ebx中
inc edx;索引自增1
dec eax;字符串长度自减1
jne <along3x.1.loc_442B54>; eax不为0跳转到along3x.1.loc_442B54
sub ebx,dword ptr ss:[ebp-8];累加结果减去strToInt(codice)
cmp ebx,7A69;结果是否等于7A69
jne <along3x.1.loc_442B74>;不等于7A69跳出
mov bl,1
- 综上分析出算法,写下c++代码注册机
#include<stdio.h>
#include<stdlib.h>
#include<string.h>int factorial(int n)
{if (n == 1)return 1;return n * factorial(n - 1);
}int serial1(char* name)
{int len = strlen(name);if (len <= 5){return -1;}int res = 0;int resA = (name[4] % 7 + 2);resA = factorial(resA);for (int index = 0; index < len; index++){res += name[index] * resA;}res -= 0x7A69;return res;
}
int main()
{char nome[1024]={0};printf("请输入Nome得出codice解锁Cancella:\n");scanf("%s", nome);int res = serial1(nome);if (res == -1){printf("字符串长度必须大于5\r\n");return 0;}printf("序列号为:%d\r\n", res);return 0;
}
- 查找Ok的调用 鼠标右键->搜索->当前模块->常数 输入2CC
- 选中
地址=00442DCC反汇编=mov eax,dword ptr ds:[ebx+2CC]
,跳转到SetVisible函数的调用处,发现关键函数调用call <along3x.1.sub_442BA0>
- 分析call <along3x.1.sub_442BA0>
mov eax,dword ptr ss:[ebp-8]; 取codice字符串首地址
call <along3x.1.unknown_libname_1145> ;取codice字符串长度
cmp eax,5 ; 比较字符串长度与5
jle <along3x.1.loc_442C4A> ;字符串长度小于等于5则跳转出去
mov eax,dword ptr ss:[ebp-8]; 取codice首地址
call <along3x.1.unknown_libname_1145> ; 取codice字符串长度
mov esi,eax
cmp esi,1 ; 字符串长度与1比较
jl <along3x.1.loc_442C28> ;字符串长度小于1跳转出去
along3x.1.loc_442BF9: lea eax,dword ptr ss:[ebp-C] ;取codice首地址
call <along3x.1.System::UniqueString(System::AnsiString &)>
lea eax,dword ptr ds:[eax+esi-1]; 取codice[esi-1]的地址
push eax ; codice[esi-1]的地址入栈
mov eax,dword ptr ss:[ebp-8] ; 取codice的首地址
movzx eax,byte ptr ds:[eax+esi-1] ; 取codice[esi-1]的ascci
imul eax ; eax = codice[esi-1]*codice[esi-1]
movsx eax,ax; 取积的低16位
imul esi ; 乘以当前索引
mov ecx,19
cdq
idiv ecx; 除以19
add edx,41; 除以19的余数+0x41
pop eax ; 将codice[esi-1]的地址赋值给eax
mov byte ptr ds:[eax],dl; 将结果的低8位赋值给codice[esi-1]
dec esi ; esi 自减1
test esi,esi 判断esi是否为0
jne <along3x.1.loc_442BF9> ; esi不为零循环继续
- 综上分析出算法,写下c++代码注册机
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* serial2(char* codice)
{int len = strlen(codice);if (len <= 5){return NULL;}int res = len;char ans[1024] = {0};for (int index = len - 1; index >= 0; index --){ans[index] = (codice[index] * codice[index] * (index + 1) % 0x19) + 0x41;}return ans;
}
int main()
{char codice[1024] = { 0 };printf("请输入codice得出nome解锁Ok:\n");scanf("%s", codice);char* ans_str = serial2(codice);if (ans_str == NULL){printf("字符串长度必须大于5\r\n");return 0;}printf("序列号为:%s\r\n", ans_str);return 0;
}