[逆向工程]160个CrackMe入门实战之Afkayas.1.Exe解析(二)
一、前言
在逆向工程的学习路径上,CrackMe程序是初学者最好的练手材料。今天我们要分析的是160个CrackMe系列的第二题——Afkayas.1.Exe。这个程序由Afkayas编写,难度为★(初级),包含了典型的验证机制。通过本实战,你将学会:
- 使用x32dbg进行动态调试
- 爆破方法
- 分析算法逻辑并编写注册机
- 掌握基本的汇编指令分析技巧
二、环境与工具准备
在开始逆向之前,我们需要准备以下环境:
- 操作系统:Windows 10
- 调试工具:x32dbg
- 目标程序:Afkayas.1.Exe
- 辅助工具:ExeinfoPe(查壳工具,虽然本程序无壳)
三、程序初步分析
3.1 查壳分析
无壳32位vb语言
3.2 运行Afkayas.1.Exe
功能:验证用户输入的用户名(Name)与序列号(Serial)是否匹配
目的:跳过账号序列号匹配验证
四、逆向破解实战
4.1 验证爆破
此部分需要同时输入用户名和序列号。
4.1.1 爆破方法
-
定位错误提示:
x32dbg打开程序,F9运行,搜索字符串“You Get Wrong” 找到关键跳转,直接爆破
将红色箭头处代码直接nop填充,打补丁另存程序
2.结果验证
4.1.2 算法分析与注册机编写
通过动态调试,我们可以发现序列号的生成规律:
1.序列号生成算法
call dword ptr ds:[eax+A0]
cmp eax,edi
jge afkayas.1.4023D2
push A0
push afkayas.1.401B5C
push ebx
push eax
call dword ptr ds:[<__vbaHresultCheckObj>]
push esi
call dword ptr ss:[ebp-C4]
lea edx,dword ptr ss:[ebp-28]
push eax
push edx
call dword ptr ds:[<__vbaObjSet>]
mov ebx,eax
lea ecx,dword ptr ss:[ebp-1C]
push ecx
push ebx
mov eax,dword ptr ds:[ebx]
call dword ptr ds:[eax+A0]
cmp eax,edi
jge afkayas.1.402409
push A0
push afkayas.1.401B5C
push ebx
push eax
call dword ptr ds:[<__vbaHresultCheckObj>]
mov edx,dword ptr ss:[ebp-B0]
mov eax,dword ptr ss:[ebp-1C]
push eax
mov ebx,dword ptr ds:[edx]
call dword ptr ds:[<__vbaLenBstr>]
mov edi,eax
mov ecx,dword ptr ss:[ebp-18]
imul edi,edi,17CFB ;账号长度乘以0x17cfb
push ecx
jo afkayas.1.4026BE
call dword ptr ds:[<Ordinal#516>] ;获取输入账号字符串首字符ASCII值
movsx edx,ax
add edi,edx ;相加生成字符串 比如 390173
jo afkayas.1.4026BE
push edi
call dword ptr ds:[<__vbaStrI4>]
mov edx,eax
lea ecx,dword ptr ss:[ebp-20]
call dword ptr ds:[<__vbaStrMove>]
vbastrcat函数将AKA-和后边字符串例如390173拼接在一起从而得到序列号:
AKA-390173
以上序列号是输入账号1111得到的,至此算法破解
2.注册机实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{char username[50] = {0};char serial[100] = {0};printf("Enter Username: ");scanf("%s", username);//账号长度自由发挥if(strlen(username) < 4) {printf("Error: Username must be at least 4 characters!\n");// 添加暂停printf("Press Enter to exit...");getchar(); // 清除输入缓冲区残留的换行符getchar(); // 等待用户按键return 1;}int firstChar = username[0];int serialNum = strlen(username) * 0x17CFB + firstChar; //算法账号长度*固定数+首字符ASCIIsprintf(serial, "AKA-%d", serialNum);printf("Your Serial: %s\n", serial);// 添加暂停printf("Press Enter to exit...");getchar(); // 清除输入缓冲区残留的换行符getchar(); // 等待用户按键return 0;
}
//gcc -0 cm.exe cm.c
3.验证注册机
如果你觉得本教程对你有帮助,请点赞❤️、收藏⭐、关注支持!欢迎在评论区留言交流技术细节!