软件逆向破解零基础入门实战第四篇,继续分析一个软件的注册部分和注册机算法逆向。 同样打开OllyDBG.EXE,将要反汇编的软件拖进OD内,F9运行,先试用软件功能。尝试输入错误的用户名和密码,就报错了。使用最直接的方式,搜索内存字符串。点击OD上面菜单的M按钮,选择程序TEXT段,右键 反汇编在反汇编窗口右键选择字符串搜索插件进行字符搜索。也可以在菜单上的插件菜单选择进行搜索。这里就有刚才我们点程序注册时提示的错误字符,我们双击看反汇编。在找到它跳转提示的位置,先找到程序头进行下断,输入注册码和用户名后注册让程序断下来F8单步走一遍。
__vbaLenBstr是Visual Basic中用于获取字符串长度的函数,其核心功能是返回输入字符串的字符数(以字节为单位)。
它就是一个取字符长度的函数。继续往下分析,看看它是哪个跳转提示失败的。分析到这看到寄存器里有我们的注册码,还有个数字。猜测是不是真实注册码?这用到了一个函数,字面意思就是比较。通过网络搜索函数的解释如下:
__vbaStrCmp是VBA语言中用于比较两个字符串的函数,返回比较结果。若字符串相等返回0,第一个字符串小于第二个返回负数,大于返回正数。
就是两个字符串比较是否相等,这个程序和我们分析的第一个类似,但它比较的注册码出现在栈窗口中。由此猜测可能是真实的注册码:
0018F360 00626E7C UNICODE "AKA-585291"
F8单步走看到EAX的值为1了,说明内容不相等
到这一步看到JE就已经跳转到错误提示字符了。那如果这个JE我们不让它跳,那就可以直接破解了软件。将JE直接NOP掉保存新程序就直接破解了。具体修改和保存修改数据的方法在第一篇有讲,可以转去学习:
跟我这样做帮你快速零基础入门软件逆向与破解01
前面分析出现的个串字符,我们猜测它可能是真正的注册码,输入验证:
软件提示注册成功,说明内存中的真正的注册码!像这种内存有注册码的,我们也可以写内存注册机,直接取真实的注册码。后面有机会在单独写一篇如何制作内存注册机的文章。
软件直接破解就分析完了,接着分析下它的注册算法和注册机如何写吧!
输入假的用户名和密码,断下后继续分析。。。。。。。。。。
00402409 > \8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0]0040240F . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C]00402412 . 50 push eax ; /String = "it0365"00402413 . 8B1A mov ebx,dword ptr ds:[edx] ; |00402415 . FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBs>; \__vbaLenBstr
前面讲到了这里取了用户名的长度。
00402525 . 8B1D 70414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaSt>; MSVBVM50.__vbaStrMove0040252B . 8BD0 mov edx,eax0040252D . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20]00402530 . FFD3 call ebx ; MSVBVM50.__vbaStrMove; <&MSVBVM50.__vbaStrMove>00402532 . 50 push eax00402533 . FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vbaStrCm>; MSVBVM50.__vbaStrCmp
这里已经将一个固定字符串和数字拼接出正确注册码了。说明算法在前面,注册码的组成就是固定字符串+一串数字。现在重新点注册,找去找生成数字的关键位置。
00402409 > \8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0]0040240F . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C]00402412 . 50 push eax ; /String = 00000006 ???00402413 . 8B1A mov ebx,dword ptr ds:[edx] ; |00402415 . FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBs>; \__vbaLenBstr0040241B . 8BF8 mov edi,eax0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18]00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB00402426 . 51 push ecx ; /String = "?"00402427 . 0F80 91020000 jo Afkayas_.004026BE ; |0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; \rtcAnsiValueBstr00402433 . 0FBFD0 movsx edx,ax00402436 . 03FA add edi,edx00402438 . 0F80 80020000 jo Afkayas_.004026BE
它取了用户名的长度,下面有个运算。
IMUL是x86架构中的有符号整数乘法指令,用于执行带符号数的乘法运算。
0040241B . 8BF8 mov edi,eax0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18]00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB
取的长度和0X17CFB相乘。
0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; \rtcAnsiValueBstr
rtcAnsiValueBstr是VB程序中用于将ASCII码值转换为字符的函数
这里对输入的用户名取第一个字符ASCII值。
0040241B . 8BF8 mov edi,eax0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18]00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB00402426 . 51 push ecx ; /String = B61F7D18 ???00402427 . 0F80 91020000 jo Afkayas_.004026BE ; |0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; \rtcAnsiValueBstr00402433 . 0FBFD0 movsx edx,ax00402436 . 03FA add edi,edx00402438 . 0F80 80020000 jo Afkayas_.004026BE0040243E . 57 push edi0040243F . FF15 E0404000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>; MSVBVM50.__vbaStrI400402445 . 8BD0 mov edx,eax
这句
00402436 . 03FA add edi,edx
ADD是Intel x86架构的汇编语言算术指令,用于执行寄存器、内存地址与立即数之间的加法运算,结果存储在目标操作数中。
到此非常明显整个算法就分析出来了。继续往下走,到这里
00402510 > \8B45 E8 mov eax,dword ptr ss:[ebp-0x18]00402513 . 8B4D E4 mov ecx,dword ptr ss:[ebp-0x1C]00402516 . 8B3D 00414000 mov edi,dword ptr ds:[<&MSVBVM50.__vbaSt>; MSVBVM50.__vbaStrCat0040251C . 50 push eax0040251D . 68 701B4000 push Afkayas_.00401B70 ; AKA-00402522 . 51 push ecx ; /String = "|nb"00402523 . FFD7 call edi ; \__vbaStrCat
__vbaStrCat是VB6中用于字符串连接的底层函数,其功能等同于VB中的&或+运算符,用于将两个字符串合并为一个新字符串。
这个函数就直接把一个固定字符和前面计算得来的数拼接,完成了注册码。
这样一个完整的注册码生成过程就分析出来了。具体流程:
1、输入用户名取它的长度
2、用这个长度和固定0x17cfb相乘
3、取用户名的第一个字符和前面相乘的值进行相加
4、一个固定字符连接前面计算得来的数值形成注册码。
算法分析完了,思路也有。用上面的流程我们代入AI让它给我们写出注册机代码:
打开百度AI后,选择AI编程,直接输入:
C语言写一段输入一个字符串,取它的长度 和0x17CFB 相乘,然后在和输入的字符串第一个数值相加转换成十进制数值,在用字符串形式输入固定值为:AKA-加上这个十进制数值
等待数秒它直接生成了代码:
#include <stdio.h>#include <string.h>
int main() { char str[100]; printf("Enter a string: "); scanf("%s", str);
int len = strlen(str); int result = (len * 0x17CFB) + (int)str[0]; printf("Result: %d\n", result);
char output[100]; sprintf(output, "AKA-%d", result); printf("Output: %s\n", output); return 0;}
执行看看:
============================================================================================================================it0365
Enter a string: Result: 585291
Output: AKA-585291
============================================================================================================================
✅ 运行结束
科技的进步,AI功能非常强。不用自己敲一个代码,全自动生成可运行的C语言源码。
阅读原文:原文链接
该文章在 2025/12/10 18:25:50 编辑过