[逆向工程]160个CrackMe入门实战之Andrnalin.2解析(九)
一.Andrnalin.2功能
输入用户名ok按钮可用,输入Key,点击ok弹出错误框。
猜测验证逻辑是根据用户名动态生成验证码进行验证。

爆破运行程序验证成功:

真码运行成功:

二.查壳
无壳,32位程序,vb语言

三.逆向
3.1 线索搜索
dbg打开,所有用户模块,搜索字符串,发现有德语"RiCHTiG !",意思是"对了","正确"。00402308此处下断点,转到断点处,向上搜索段首00401FF0 处下断,运行程序,输入用户名和码,点击ok键,程序断在"ok"按钮事件段首

004022CB | 0F84 C0000000 | je andrénalin.2.402391 |
发现在004022CB处指令有JE跳转,同时用IDA静态分析确认,猜测可能是关键跳,那么nop掉打补丁保存,运行程序发现验证成功


3.2 追码
在VB中,文本是使用Unicode存储,并且每个变量(无论整数,浮点数还是文本),前两个4字节表示数据类型信息,第三个4字节开始才存储数据。
算法分析如下:
- 循环结构
程序使用__vbaVarForInit、__vbaVarForNext和__vbaFreeVarList三个函数构建了一个For循环。其中:__vbaVarForInit初始化循环变量、终止条件和步长;- 每次迭代结束后调用
__vbaVarForNext更新循环变量并判断是否继续; - 循环完全结束后调用
__vbaFreeVarList释放循环中使用的临时 Variant 变量。
- 循环体操作
在循环内部,每次迭代:- 调用
rtcMidCharVar从源字符串中按位置提取一个字符(返回 Variant 类型); - 将该字符传递给
rtcAnsiValueBstr,将其转换为对应的 ANSI 码值(整数); - 调用
__vbaVarAdd将所有字符的 ANSI 码值累加到一个累加器变量中。
- 调用
- 结果运算
循环结束后:- 将累加得到的和(Variant 类型)与常量 1234567890 通过
__vbaVarMul执行乘法运算,得到一个 64 位浮点(double) 结果。
- 将累加得到的和(Variant 类型)与常量 1234567890 通过
- 格式转换与字符串替换
- 将上述浮点结果通过类型转换函数(如
__vbaR8Str或__vbaStrR8)转换为十进制整数字符串(例如 "1234567890" 形式); - 调用
__vbaMidStmtVar对该字符串执行替换操作 :将第 4 个字符和第 9 个字符替换为连字符"-"。
- 将上述浮点结果通过类型转换函数(如
- 最终结果
经过替换后的字符串即为程序生成的 Key。
shell
00401FF0 | 55 | push ebp | ok段首
00401FF1 | 8BEC | mov ebp,esp |
00401FF3 | 83EC 0C | sub esp,C |
00401FF6 | 68 26104000 | push <JMP.&__vbaExceptHandler> |
00401FFB | 64:A1 00000000 | mov eax,dword ptr fs:[0] |
00402001 | 50 | push eax |
00402002 | 64:8925 00000000 | mov dword ptr fs:[0],esp |
00402009 | 81EC 18010000 | sub esp,118 |
0040200F | 53 | push ebx | ebx:__vbaMidStmtVar
00402010 | 8B5D 08 | mov ebx,dword ptr ss:[ebp+8] | ebx:__vbaMidStmtVar
00402013 | 8BC3 | mov eax,ebx | ebx:__vbaMidStmtVar
00402015 | 56 | push esi | esi:__vbaVarMove
00402016 | 83E3 FE | and ebx,FFFFFFFE | ebx:"2@"将 EBX 寄存器的最低有效位(bit 0)清零 EBX 可能变为指向 "2@" 所在地址的偶数对齐版本(如果原地址是奇数,会减小 1,指向前一个字节)
00402019 | 57 | push edi | edi:__vbaFreeVarList
0040201A | 8965 F4 | mov dword ptr ss:[ebp-C],esp |
0040201D | 83E0 01 | and eax,1 |
00402020 | 8B3B | mov edi,dword ptr ds:[ebx] | edi:__vbaFreeVarList, ebx:__vbaMidStmtVar
00402022 | C745 F8 00104000 | mov dword ptr ss:[ebp-8],andrénalin.2.4 |
00402029 | 53 | push ebx | ebx:__vbaMidStmtVar
0040202A | 8945 FC | mov dword ptr ss:[ebp-4],eax |
0040202D | 895D 08 | mov dword ptr ss:[ebp+8],ebx | ebx:__vbaMidStmtVar
00402030 | FF57 04 | call dword ptr ds:[edi+4] | edi+04:__vbaFreeVarList+4
00402033 | 33F6 | xor esi,esi | esi:__vbaVarMove
00402035 | 53 | push ebx | ebx:__vbaMidStmtVar
00402036 | 8975 DC | mov dword ptr ss:[ebp-24],esi | esi:__vbaVarMove
00402039 | 8975 CC | mov dword ptr ss:[ebp-34],esi | esi:__vbaVarMove
0040203C | 8975 BC | mov dword ptr ss:[ebp-44],esi | esi:__vbaVarMove
0040203F | 8975 AC | mov dword ptr ss:[ebp-54],esi | esi:__vbaVarMove
00402042 | 8975 A8 | mov dword ptr ss:[ebp-58],esi | esi:__vbaVarMove
00402045 | 8975 A4 | mov dword ptr ss:[ebp-5C],esi | esi:__vbaVarMove
00402048 | 8975 94 | mov dword ptr ss:[ebp-6C],esi | esi:__vbaVarMove
0040204B | 8975 84 | mov dword ptr ss:[ebp-7C],esi | esi:__vbaVarMove
0040204E | 89B5 74FFFFFF | mov dword ptr ss:[ebp-8C],esi | esi:__vbaVarMove
00402054 | 89B5 64FFFFFF | mov dword ptr ss:[ebp-9C],esi | esi:__vbaVarMove
0040205A | 89B5 54FFFFFF | mov dword ptr ss:[ebp-AC],esi | esi:__vbaVarMove
00402060 | 89B5 44FFFFFF | mov dword ptr ss:[ebp-BC],esi | esi:__vbaVarMove
00402066 | 89B5 14FFFFFF | mov dword ptr ss:[ebp-EC],esi | esi:__vbaVarMove
0040206C | 89B5 F8FEFFFF | mov dword ptr ss:[ebp-108],esi | esi:__vbaVarMove
00402072 | 89B5 E8FEFFFF | mov dword ptr ss:[ebp-118],esi | esi:__vbaVarMove
00402078 | FF97 FC020000 | call dword ptr ds:[edi+2FC] | edi+2FC:__vbaVarMul+1A1
0040207E | 8D4D A4 | lea ecx,dword ptr ss:[ebp-5C] |
00402081 | 50 | push eax |
00402082 | 51 | push ecx |
00402083 | FF15 24414000 | call dword ptr ds:[<__vbaObjSet>] |
00402089 | 8BD8 | mov ebx,eax | ebx:__vbaMidStmtVar
0040208B | 8D45 A8 | lea eax,dword ptr ss:[ebp-58] |
0040208E | 50 | push eax |
0040208F | 53 | push ebx | ebx:__vbaMidStmtVar
00402090 | 8B13 | mov edx,dword ptr ds:[ebx] | ebx:__vbaMidStmtVar
00402092 | FF92 A0000000 | call dword ptr ds:[edx+A0] |
00402098 | 3BC6 | cmp eax,esi | esi:__vbaVarMove
0040209A | 7D 12 | jge andrénalin.2.4020AE | 有符号数 大于等于则跳转
0040209C | 68 A0000000 | push A0 |
004020A1 | 68 201C4000 | push andrénalin.2.401C20 |
004020A6 | 53 | push ebx | ebx:__vbaMidStmtVar
004020A7 | 50 | push eax |
004020A8 | FF15 14414000 | call dword ptr ds:[<__vbaHresultCheckOb |
004020AE | 8B45 A8 | mov eax,dword ptr ss:[ebp-58] |
004020B1 | 8975 A8 | mov dword ptr ss:[ebp-58],esi | esi:__vbaVarMove
004020B4 | 8B35 FC404000 | mov esi,dword ptr ds:[<__vbaVarMove>] | esi:__vbaVarMove
004020BA | 8D55 94 | lea edx,dword ptr ss:[ebp-6C] |
004020BD | 8D4D BC | lea ecx,dword ptr ss:[ebp-44] |
004020C0 | 8945 9C | mov dword ptr ss:[ebp-64],eax |
004020C3 | C745 94 08000000 | mov dword ptr ss:[ebp-6C],8 |
004020CA | FFD6 | call esi | esi:__vbaVarMove
004020CC | 8D4D A4 | lea ecx,dword ptr ss:[ebp-5C] |
004020CF | FF15 B4414000 | call dword ptr ds:[<__vbaFreeObj>] |
004020D5 | B8 01000000 | mov eax,1 |
004020DA | 8D8D 54FFFFFF | lea ecx,dword ptr ss:[ebp-AC] |
004020E0 | 8985 5CFFFFFF | mov dword ptr ss:[ebp-A4],eax |
004020E6 | 8985 4CFFFFFF | mov dword ptr ss:[ebp-B4],eax |
004020EC | 8D55 BC | lea edx,dword ptr ss:[ebp-44] |
004020EF | 51 | push ecx |
004020F0 | 8D45 94 | lea eax,dword ptr ss:[ebp-6C] |
004020F3 | BB 02000000 | mov ebx,2 | ebx:__vbaMidStmtVar
004020F8 | 52 | push edx |
004020F9 | 50 | push eax |
004020FA | 899D 54FFFFFF | mov dword ptr ss:[ebp-AC],ebx | ebx:__vbaMidStmtVar
00402100 | 899D 44FFFFFF | mov dword ptr ss:[ebp-BC],ebx | ebx:__vbaMidStmtVar
00402106 | FF15 18414000 | call dword ptr ds:[<__vbaLenVar>] |
0040210C | 8D8D 44FFFFFF | lea ecx,dword ptr ss:[ebp-BC] |
00402112 | 50 | push eax |
00402113 | 8D95 E8FEFFFF | lea edx,dword ptr ss:[ebp-118] |
00402119 | 51 | push ecx |
0040211A | 8D85 F8FEFFFF | lea eax,dword ptr ss:[ebp-108] |
00402120 | 52 | push edx |
00402121 | 8D4D DC | lea ecx,dword ptr ss:[ebp-24] |
00402124 | 50 | push eax |
00402125 | 51 | push ecx |
00402126 | FF15 20414000 | call dword ptr ds:[<__vbaVarForInit>] | 初始化for循环 设置循环起点 终点 步长
0040212C | 8B3D 04414000 | mov edi,dword ptr ds:[<__vbaFreeVarList | 用于一次性清理函数返回前或循环结束后的多个局部变量,以回收内存
00402132 | 85C0 | test eax,eax | 是否循环标识
00402134 | 0F84 9C000000 | je andrénalin.2.4021D6 |
0040213A | 8D55 94 | lea edx,dword ptr ss:[ebp-6C] |
0040213D | 8D45 DC | lea eax,dword ptr ss:[ebp-24] |
00402140 | 52 | push edx |
00402141 | 50 | push eax |
00402142 | C745 9C 01000000 | mov dword ptr ss:[ebp-64],1 |
00402149 | 895D 94 | mov dword ptr ss:[ebp-6C],ebx | ebx:__vbaMidStmtVar
0040214C | FF15 90414000 | call dword ptr ds:[<__vbaI4Var>] | 是将传入的 VARIANT 类型变量,安全地转换为一个 4 字节有符号的 Long(长整型)整数
00402152 | 8D4D BC | lea ecx,dword ptr ss:[ebp-44] |
00402155 | 50 | push eax |
00402156 | 8D55 84 | lea edx,dword ptr ss:[ebp-7C] |
00402159 | 51 | push ecx |
0040215A | 52 | push edx |
0040215B | FF15 38414000 | call dword ptr ds:[<Ordinal#632>] |
00402161 | 8D45 84 | lea eax,dword ptr ss:[ebp-7C] |
00402164 | 8D4D A8 | lea ecx,dword ptr ss:[ebp-58] |
00402167 | 50 | push eax |
00402168 | 51 | push ecx |
00402169 | FF15 70414000 | call dword ptr ds:[<__vbaStrVarVal>] | 从字符串变量取值
0040216F | 50 | push eax |
00402170 | FF15 0C414000 | call dword ptr ds:[<Ordinal#516>] |
00402176 | 66:8985 4CFFFFFF | mov word ptr ss:[ebp-B4],ax | 输入用户名为111 此时内存只显示1
0040217D | 8D55 CC | lea edx,dword ptr ss:[ebp-34] |
00402180 | 8D85 44FFFFFF | lea eax,dword ptr ss:[ebp-BC] |
00402186 | 52 | push edx |
00402187 | 8D8D 74FFFFFF | lea ecx,dword ptr ss:[ebp-8C] |
0040218D | 50 | push eax |
0040218E | 51 | push ecx |
0040218F | 899D 44FFFFFF | mov dword ptr ss:[ebp-BC],ebx | ebx:__vbaMidStmtVar
00402195 | FF15 94414000 | call dword ptr ds:[<__vbaVarAdd>] | 加法
0040219B | 8BD0 | mov edx,eax |
0040219D | 8D4D CC | lea ecx,dword ptr ss:[ebp-34] |
004021A0 | FFD6 | call esi | esi:__vbaVarMove
004021A2 | 8D4D A8 | lea ecx,dword ptr ss:[ebp-58] |
004021A5 | FF15 B8414000 | call dword ptr ds:[<__vbaFreeStr>] | 释放字符串内存
004021AB | 8D55 84 | lea edx,dword ptr ss:[ebp-7C] |
004021AE | 8D45 94 | lea eax,dword ptr ss:[ebp-6C] |
004021B1 | 52 | push edx |
004021B2 | 50 | push eax |
004021B3 | 53 | push ebx | ebx:__vbaMidStmtVar
004021B4 | FFD7 | call edi | edi:__vbaFreeVarList
004021B6 | 83C4 0C | add esp,C |
004021B9 | 8D8D E8FEFFFF | lea ecx,dword ptr ss:[ebp-118] |
004021BF | 8D95 F8FEFFFF | lea edx,dword ptr ss:[ebp-108] |
004021C5 | 8D45 DC | lea eax,dword ptr ss:[ebp-24] |
004021C8 | 51 | push ecx |
004021C9 | 52 | push edx |
004021CA | 50 | push eax |
004021CB | FF15 AC414000 | call dword ptr ds:[<__vbaVarForNext>] | 继续或终止for循环 根据输入名长度循环次数
004021D1 | E9 5CFFFFFF | jmp andrénalin.2.402132 |
004021D6 | 8D4D CC | lea ecx,dword ptr ss:[ebp-34] |
004021D9 | 8D95 54FFFFFF | lea edx,dword ptr ss:[ebp-AC] |
004021DF | 51 | push ecx |
004021E0 | 8D45 94 | lea eax,dword ptr ss:[ebp-6C] |
004021E3 | 52 | push edx |
004021E4 | 50 | push eax |
004021E5 | C785 5CFFFFFF D2029649 | mov dword ptr ss:[ebp-A4],499602D2 | 1234567890
004021EF | C785 54FFFFFF 03000000 | mov dword ptr ss:[ebp-AC],3 |
004021F9 | FF15 5C414000 | call dword ptr ds:[<__vbaVarMul>] | 相乘
004021FF | 8BD0 | mov edx,eax |
00402201 | 8D4D CC | lea ecx,dword ptr ss:[ebp-34] |
00402204 | FFD6 | call esi | esi:__vbaVarMove
00402206 | 8B1D A0414000 | mov ebx,dword ptr ds:[<__vbaMidStmtVar> | 替换字符串中指定位置的内容
0040220C | 8D4D CC | lea ecx,dword ptr ss:[ebp-34] |
0040220F | 51 | push ecx |
00402210 | 6A 04 | push 4 | 第四个
00402212 | 8D95 54FFFFFF | lea edx,dword ptr ss:[ebp-AC] |
00402218 | 6A 01 | push 1 |
0040221A | 52 | push edx |
0040221B | C785 5CFFFFFF 341C4000 | mov dword ptr ss:[ebp-A4],andrénalin.2. |
00402225 | C785 54FFFFFF 08000000 | mov dword ptr ss:[ebp-AC],8 |
0040222F | FFD3 | call ebx | ebx:__vbaMidStmtVar
00402231 | 8D45 CC | lea eax,dword ptr ss:[ebp-34] |
00402234 | 8D8D 54FFFFFF | lea ecx,dword ptr ss:[ebp-AC] |
0040223A | 50 | push eax |
0040223B | 6A 09 | push 9 | 第9个
0040223D | 6A 01 | push 1 |
0040223F | 51 | push ecx |
00402240 | C785 5CFFFFFF 341C4000 | mov dword ptr ss:[ebp-A4],andrénalin.2. |
0040224A | C785 54FFFFFF 08000000 | mov dword ptr ss:[ebp-AC],8 |
00402254 | FFD3 | call ebx | ebx:__vbaMidStmtVar
00402256 | 8B45 08 | mov eax,dword ptr ss:[ebp+8] |
00402259 | 50 | push eax | 181-8147-830
0040225A | 8B10 | mov edx,dword ptr ds:[eax] |
0040225C | FF92 04030000 | call dword ptr ds:[edx+304] |
00402262 | 50 | push eax |
00402263 | 8D45 A4 | lea eax,dword ptr ss:[ebp-5C] |
00402266 | 50 | push eax |
00402267 | FF15 24414000 | call dword ptr ds:[<__vbaObjSet>] |
0040226D | 8BD8 | mov ebx,eax | ebx:__vbaMidStmtVar
0040226F | 8D55 A8 | lea edx,dword ptr ss:[ebp-58] |
00402272 | 52 | push edx |
00402273 | 53 | push ebx | ebx:__vbaMidStmtVar
00402274 | 8B0B | mov ecx,dword ptr ds:[ebx] | ebx:__vbaMidStmtVar
00402276 | FF91 A0000000 | call dword ptr ds:[ecx+A0] |
0040227C | 85C0 | test eax,eax |
0040227E | 7D 12 | jge andrénalin.2.402292 |
00402280 | 68 A0000000 | push A0 |
00402285 | 68 201C4000 | push andrénalin.2.401C20 |
0040228A | 53 | push ebx | ebx:__vbaMidStmtVar
0040228B | 50 | push eax |
0040228C | FF15 14414000 | call dword ptr ds:[<__vbaHresultCheckOb |
00402292 | 8B45 A8 | mov eax,dword ptr ss:[ebp-58] |
00402295 | 8D4D CC | lea ecx,dword ptr ss:[ebp-34] |
00402298 | 8945 9C | mov dword ptr ss:[ebp-64],eax | 输入的key 222
0040229B | 8D45 94 | lea eax,dword ptr ss:[ebp-6C] |
0040229E | 50 | push eax |
0040229F | 51 | push ecx | 111对应的真码181-8147-830
004022A0 | C745 A8 00000000 | mov dword ptr ss:[ebp-58],0 |
004022A7 | C745 94 08800000 | mov dword ptr ss:[ebp-6C],8008 |
004022AE | FF15 48414000 | call dword ptr ds:[<__vbaVarTstEq>] | 比较两个 Variant 变量是否相等
004022B4 | 8D4D A4 | lea ecx,dword ptr ss:[ebp-5C] |
004022B7 | 8BD8 | mov ebx,eax | ebx:__vbaMidStmtVar
004022B9 | FF15 B4414000 | call dword ptr ds:[<__vbaFreeObj>] |
004022BF | 8D4D 94 | lea ecx,dword ptr ss:[ebp-6C] |
004022C2 | FF15 00414000 | call dword ptr ds:[<__vbaFreeVar>] |
004022C8 | 66:85DB | test bx,bx |
004022CB | 0F84 C0000000 | je andrénalin.2.402391 | 真假码比较 关键跳转
3.3 注册机
c++
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
int main() {
char Name[100] = {0};
char key[100] = {0};
int nCode = 0;
std::cout << "Input your Name: ";
std::cin.getline(Name, 100);
if (strlen(Name) > 0) {
for (size_t i = 0; i < strlen(Name); i++) {
nCode += static_cast<unsigned char>(Name[i]); // 确保 ANSI 范围
}
double dNum = 1234567890.0; // VB 中是 64 位浮点 (double)
dNum *= nCode;
// 转换为整数字符串(无小数部分)
std::snprintf(key, sizeof(key), "%.0f", dNum);
// 注意:索引从 0 开始,第4个字符对应 key[3],第9个对应 key[8]
// 需要确保字符串长度足够
if (strlen(key) >= 9) {
key[3] = '-';
key[8] = '-';
}
std::cout << "Key: " << key << std::endl;
} else {
std::cout << "input error!" << std::endl;
}
std::system("pause");
return 0;
}
验证:

四.VB 逆向常用函数
4.1 数据类型转换(String ↔ Numeric / Variant)
| 函数 | 作用 |
|---|---|
__vbaI2Str |
字符串 → 短整数(2 字节,-32768~32767) |
__vbaI4Str |
字符串 → 长整数(4 字节) |
__vbar4Str |
字符串 → 单精度浮点(4 字节) |
__vbar8Str |
字符串 → 双精度浮点(8 字节) |
VarCyFromStr |
字符串 → 货币型(Currency,8 字节整数) |
VarBstrFromI2 |
短整数 → 字符串 |
4.2 数据移动 / 拷贝
| 函数 | 作用 |
|---|---|
__vbaStrCopy |
拷贝字符串 |
__vbaVarCopy |
拷贝变量(Variant) |
__vbaVarMove |
移动变量(效果类似拷贝) |
4.3 数学运算(Variant 类型)
| 函数 | 作用 |
|---|---|
__vbaVarAdd |
加法 |
__vbaVarSub |
减法 |
__vbaVarMul |
乘法 |
__vbaVarIDiv |
整除(取商) |
__vbaVarXor |
异或 |
4.4 字符串 / 变量操作(常用)
| 函数 | 作用 |
|---|---|
rtcMidCharVar |
取子串:Mid() |
rtcLeftCharVar |
取左子串:Left() |
rtcRightCharVar |
取右子串:Right() |
__vbaStrCat |
字符串连接(& 或 +) |
__vbaLenBstr |
取字符串长度(VB中汉字长度为1) |
rtcTrimBstr |
去除首尾空格 |
__vbaStrCmp |
字符串比较(= 或 <>) |
__vbaVarCmp 族 |
变量比较(Eq/Ne/Ge/Gt/Le/Lt) |
ASC |
取字符 ASCII 码(反汇编中常表现为 movsx) |
4.5 内存释放 / 对象释放
| 函数 | 作用 |
|---|---|
__vbaFreeStr |
释放字符串内存 |
__vbaFreeObj |
释放对象(窗口/对话框等) |
__vbaFreeVar |
释放变量(Variant) |
4.6 控制流 / 对话框
| 函数 | 作用 |
|---|---|
__vbaVarForNext |
For...Next 循环结构 |
rtcMsgBox |
消息框(MsgBox) |
rtcInputBox |
输入框(InputBox) |
__vbaNew / __vbaNew2 |
创建/显示对话框 |
4.7 其他辅助
| 函数 | 作用 |
|---|---|
MultiByteToWideChar |
多字节 → Unicode(VB内部常用) |
__vbaStrVarVal |
从字符串变量取值 |
4.8 函数名中的缩写含义
| 缩写 | 含义 |
|---|---|
str |
String(字符串) |
var |
Variant(变体变量) |
i2 / i4 |
2字节整数 / 4字节整数 |
r4 / r8 |
单精度 / 双精度浮点 |
cy |
Currency(货币型,8字节整数) |
fp |
Floating Point |
cmp |
Compare(比较) |
tsteq / tstne |
Test Equal / Not Equal |