软件逆向破解零基础入门实战8篇,与上篇同一个作者写的软件。要求就是输入正确的用户名与注册码完成软件注册。难度也是一颗星! 打开反汇编调试器OllyDBG,将软件拖进直接F9运行。开干吧!和上篇文章一样,去查找下字符吧!直接CTRL+G输入401000来到程序模块内从API调试来看它也是个VB写的软件!在汇编窗口中右键选择如下图片:内容不多,功能也比较简单,搜索关键字符下断点找关键位置。这次我们换个姿势来找关键位置。不用查字符串了。 教大家另一种更直接找关键代码位置的方法,大家坐好扶稳准备开车了。这次教大家个新姿势,必须要快也要帅。 F9运行软件后,输入假用户名与注册码,按下调试器上的暂停(F12)暂停后,在打开堆栈窗口(调试器上工具栏上的K图标)注意观察,这里调用的地址是不是最后一个它是程序自身的地址,7开头都是系统DLL的地址了。那就双击0040240f这行,在反汇编窗口进行下断点(F2)。F9运行软件后,在点击软件上的OK按钮断下来。在注意观察右下角堆栈窗口是谁调用了它。看到00402415调用了它,那就在返回到这个地址。右键选择反汇编跟随(回车键)。
004021D1 .^\E9 5CFFFFFF jmp Andréna.00402132
这个位置有个循环,调用了很多API在干什么也不清楚。在下一条语句下个断点(F2)后F9跳过它。
0040229E . 50 push eax ; /var18 = NULL0040229F . 51 push ecx ; |var28 = 0018F3DC004022A0 . C745 A8 00000>mov dword ptr ss:[ebp-0x58],0x0 ; |004022A7 . C745 94 08800>mov dword ptr ss:[ebp-0x6C],0x8008 ; |004022AE . FF15 48414000 call dword ptr ds:[<&MSVBVM50.__vbaVarTs>; \__vbaVarTstEq
__vbaVarTstEq 是 Visual Basic 运行时库中的一个函数,用于比较两个变量的值是否相等。
这个函数是比较,PUSH了两个值。在堆栈窗口可以看到它在拿假注册码与一个 UNICODE "527-6048-030"在做比较,会不会这个是真注册码?比较后,这个跳转直接就跳到失败提示的代码去了。所以这里就是关键位置,直接NOP掉保存就可以直接破解了。
这个就是正确的注册码了!
========逆向注册机尝试=======
单直接破解这软件非常简单。作为学习,要去逆它的代码与算法。争取把注册机写出来。算法关键代码:
00402132 > /85C0 test eax,eax00402134 . |0F84 9C000000 je Andréna.004021D60040213A . |8D55 94 lea edx,dword ptr ss:[ebp-0x6C]0040213D . |8D45 DC lea eax,dword ptr ss:[ebp-0x24]00402140 . |52 push edx00402141 . |50 push eax00402142 . |C745 9C 01000>mov dword ptr ss:[ebp-0x64],0x100402149 . |895D 94 mov dword ptr ss:[ebp-0x6C],ebx ; MSVBVM50.__vbaVarDup0040214C . |FF15 90414000 call dword ptr ds:[<&MSVBVM50.__vbaI4Var>; MSVBVM50.__vbaI4Var00402152 . |8D4D BC lea ecx,dword ptr ss:[ebp-0x44] ; |00402155 . |50 push eax ; |Start = 0x18F3AC00402156 . |8D55 84 lea edx,dword ptr ss:[ebp-0x7C] ; |00402159 . |51 push ecx ; |dString8 = 0018F3BC0040215A . |52 push edx ; |RetBUFFER = 0018F3CC0040215B . |FF15 38414000 call dword ptr ds:[<&MSVBVM50.#632>] ; \rtcMidCharVar00402161 . |8D45 84 lea eax,dword ptr ss:[ebp-0x7C]00402164 . |8D4D A8 lea ecx,dword ptr ss:[ebp-0x58]00402167 . |50 push eax ; /String8 = 0018F3AC00402168 . |51 push ecx ; |ARG2 = 0018F3BC00402169 . |FF15 70414000 call dword ptr ds:[<&MSVBVM50.__vbaStrVa>; \__vbaStrVarVal0040216F . |50 push eax ; /String = ""00402170 . |FF15 0C414000 call dword ptr ds:[<&MSVBVM50.#516>] ; \rtcAnsiValueBstr00402176 . |66:8985 4CFFF>mov word ptr ss:[ebp-0xB4],ax0040217D . |8D55 CC lea edx,dword ptr ss:[ebp-0x34]00402180 . |8D85 44FFFFFF lea eax,dword ptr ss:[ebp-0xBC]00402186 . |52 push edx ; /var18 = 0018F3CC00402187 . |8D8D 74FFFFFF lea ecx,dword ptr ss:[ebp-0x8C] ; |0040218D . |50 push eax ; |var28 = 0018F3AC0040218E . |51 push ecx ; |saveto8 = 0018F3BC0040218F . |899D 44FFFFFF mov dword ptr ss:[ebp-0xBC],ebx ; |MSVBVM50.__vbaVarDup00402195 . |FF15 94414000 call dword ptr ds:[<&MSVBVM50.__vbaVarAd>; \__vbaVarAdd0040219B . |8BD0 mov edx,eax0040219D . |8D4D CC lea ecx,dword ptr ss:[ebp-0x34]004021A0 . |FFD6 call esi ; MSVBVM50.__vbaVarMove004021A2 . |8D4D A8 lea ecx,dword ptr ss:[ebp-0x58]004021A5 . |FF15 B8414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeS>; MSVBVM50.__vbaFreeStr004021AB . |8D55 84 lea edx,dword ptr ss:[ebp-0x7C]004021AE . |8D45 94 lea eax,dword ptr ss:[ebp-0x6C]004021B1 . |52 push edx004021B2 . |50 push eax004021B3 . |53 push ebx ; MSVBVM50.__vbaVarDup004021B4 . |FFD7 call edi ; MSVBVM50.__vbaFreeVarList004021B6 . |83C4 0C add esp,0xC004021B9 . |8D8D E8FEFFFF lea ecx,dword ptr ss:[ebp-0x118]004021BF . |8D95 F8FEFFFF lea edx,dword ptr ss:[ebp-0x108]004021C5 . |8D45 DC lea eax,dword ptr ss:[ebp-0x24]004021C8 . |51 push ecx ; /TMPend8 = 0018F3BC004021C9 . |52 push edx ; |TMPstep8 = 0018F3CC004021CA . |50 push eax ; |Counter8 = 0018F3AC004021CB . |FF15 AC414000 call dword ptr ds:[<&MSVBVM50.__vbaVarFo>; \__vbaVarForNext004021D1 .^\E9 5CFFFFFF jmp Andréna.00402132
没有接触过VB编程,还是找资料把这些函数功能查找下。才好操作。
__vbaI4Var:该函数通常用于从字符串中提取子字符串,其行为与VB中的MID函数一致,支持指定起始位置和长度。
rtcMidCharVar:该函数的功能是从字符串的指定位置开始截取指定长度的子串。
__vbaStrVarVal:该函数从字符串变量的指定位置获取字符值,通常用于实现VB内置字符串操作(如MID函数)。在反汇编代码中,它常与rtcMidCharVar等函数配合使用,以截取字符串子串。
rtcAnsiValueBstr:该函数的作用是提取字符串中某个字符的 ASCII 编码。
__vbaVarAdd:对两个变体变量(Variant)执行加法运算.
__vbaFreeStr:作用是抹掉内存中指定字符串的数据,并释放对应资源。
__vbaFreeVarList:主要用于清理和释放与变量列表相关的资源。
__vbaVarForNext:程序中用于处理 For...Next 循环结构的内部函数。
F8单步看这个循环,我们发现了它的算法其它非常简单。根据上面API函数功能说明,它就是把输入的用户名取出每个字符的ASCII码相加。
__vbaVarMul:主要用于执行变体类型变量(Variant)之间的乘法运算。调用通常涉及寄存器操作和栈管理。例如,被乘数和乘数的地址会被加载到寄存器(如 eax 和 ecx),然后压入栈中,结果存储地址也通过栈传递,最后通过 call __vbaVarMul 指令执行乘法,并将结果存入指定变量。
004021D6 > \8D4D CC lea ecx,dword ptr ss:[ebp-0x34]004021D9 . 8D95 54FFFFFF lea edx,dword ptr ss:[ebp-0xAC]004021DF . 51 push ecx ; /var18 = 0018F404004021E0 . 8D45 94 lea eax,dword ptr ss:[ebp-0x6C] ; |004021E3 . 52 push edx ; |var28 = 0018F38C004021E4 . 50 push eax ; |SaveTo8 = 0018F3CC004021E5 . C785 5CFFFFFF>mov dword ptr ss:[ebp-0xA4],0x499602D2 ; |004021EF . C785 54FFFFFF>mov dword ptr ss:[ebp-0xAC],0x3 ; |004021F9 . FF15 5C414000 call dword ptr ds:[<&MSVBVM50.__vbaVarMu>; \__vbaVarMul
直接运行F8什么都看不到,直接F7进入函数内部我们分析看在干什么吧!看到API内部有个CALL压入了我们需要的值在堆栈窗口看到1AB就是IT0365的ASCII值相加,499602d2是固定值传入。18F3CC应该是个地址。后面具体看写入什么内容。这里就是在做1AB*499602D2的操作了。计算的值保存在EDX和EAX中。
FLD 指令是Intel x86 汇编语言中用于浮点运算的指令,其全称为 "Floating-point Load"。该指令的功能是将一个整数或浮点数从内存加载到FPU(浮点运算单元)的栈顶寄存器 ST(0)中。
FSTP是一条 x86 汇编语言指令,用于将浮点栈顶元素弹出。
fstp qword ptr ds:[ecx+0x8]
qword ptr 指定操作的数据类型为 8 字节(64 位)双精度浮点数,保存在[ecx+8]地址中。
执行以后,看到里面的内容为:
运算后得到的值为:527160489030。返回程序模块后F8往下走来到这两个代码处:00402206 . 8B1D A0414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaMidStmtVar>; MSVBVM50.__vbaMidStmtVar0040220C . 8D4D CC lea ecx,dword ptr ss:[ebp-0x34]0040220F . 51 push ecx00402210 . 6A 04 push 0x400402212 . 8D95 54FFFFFF lea edx,dword ptr ss:[ebp-0xAC]00402218 . 6A 01 push 0x10040221A . 52 push edx0040221B . C785 5CFFFFFF>mov dword ptr ss:[ebp-0xA4],Andréna.00401C34 ; -00402225 . C785 54FFFFFF>mov dword ptr ss:[ebp-0xAC],0x80040222F . FFD3 call ebx ; MSVBVM50.__vbaMidStmtVar; <&MSVBVM50.__vbaMidStmtVar>00402231 . 8D45 CC lea eax,dword ptr ss:[ebp-0x34]00402234 . 8D8D 54FFFFFF lea ecx,dword ptr ss:[ebp-0xAC]0040223A . 50 push eax0040223B . 6A 09 push 0x90040223D . 6A 01 push 0x10040223F . 51 push ecx00402240 . C785 5CFFFFFF>mov dword ptr ss:[ebp-0xA4],Andréna.00401C34 ; -0040224A . C785 54FFFFFF>mov dword ptr ss:[ebp-0xAC],0x800402254 . FFD3 call ebx ; MSVBVM50.__vbaMidStmtVar
F7进去分析代码可以看到把数值:527160489030第一次将第4位替换成-,第二次将第9位替换-得到了我们的注册码。 这样注册机编写代码就非常容易了。同样可以用参考前面1,2,3篇中的方法使用deepseek生成注册机代码,或自己编写都可以了。#include <stdio.h>#include <string.h>
int main() { char input[100]; printf("输入字符: "); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = '\0';
unsigned long long sum = 0; for (int i = 0; input[i] != '\0'; i++) { sum += (unsigned char)input[i]; } sum *= 0x499602d2;
char result[20]; sprintf(result, "%llu", sum);
if (strlen(result) >= 4) result[3] = '-'; if (strlen(result) >= 9) result[8] = '-';
printf("处理结果: %s\n", result); return 0;}
阅读原文:原文链接
该文章在 2025/12/13 8:59:16 编辑过