这篇来学习下真实注册码的实现算法,接上篇我们对关键跳转位置进行了NOP后,软件随便输入内容都提示注册成功。仔细观察发现JNE是一个条件跳转,它的上一条语句是一个CALL,其实它就是一个函数,用真注册码和假注册码进行对比,如果不相等就会跳转。相等就说明注册码正确,完成注册。 我们输入的xuejiemi.com是假注册码,EAX就是真正的注册码了。这个真实的注册码是如何得到的,就是前面的算法计算的。本篇主要学习分析下它的具体算法。 F9运行程序后,继续点击注册,它程序断下来,我们F8单步分析。入下走,我们知道了它真正的注册码有固定字符串,CW,CRACKED,我们发现了关键位置0042FA87 |. 8B45 F0 mov eax,[local.4]0042FA8A |. 0FB600 movzx eax,byte ptr ds:[eax]0042FA8D |. F72D 50174300 imul dword ptr ds:[0x431750]0042FA93 |. A3 50174300 mov dword ptr ds:[0x431750],eax0042FA98 |. A1 50174300 mov eax,dword ptr ds:[0x431750]0042FA9D |. 0105 50174300 add dword ptr ds:[0x431750],eax0042FAA3 |. 8D45 FC lea eax,[local.1]0042FAA6 |. BA ACFB4200 mov edx,Acid_bur.0042FBAC ; CW
这里有几个汇编代码
movzx 是将源操作数的内容拷贝到目的操作数。
IMUL是x86架构中的有符号整数乘法指令,用于执行带符号数的乘法运算。
MOV(Move)是汇编语言中的基础传送指令,用于将字节、字或双字数据从源操作数复制到目的操作数,源内容保持不变。
ADD是Intel x86架构的汇编语言算术指令,用于执行寄存器、内存地址与立即数之间的加法运算,结果存储在目标操作数中。
LEA指令(Load Effective Address)是x86架构汇编语言中的核心指令,主要功能为计算内存操作数的有效地址并将计算结果直接存入目标寄存器,而非访问内存获取数据内容。
F8往下走,大概意思就是取用户名的第一个字符ASCII值 和
这个地址的内容相乘,这句
add dword ptr ds:[0x431750],eax
相乘的值在相加一遍,在和固定值进行拼接。
具体代码如何实现,我们也借助高科技产品AI帮我们完成代码。打开百度的文心助手,用DEEPSEEK把代码完成它。
直接输入
mov eax,[local.4] movzx eax,byte ptr ds:[eax] imul dword ptr ds:[0x431750] mov dword ptr ds:[0x431750],eax mov eax,dword ptr ds:[0x431750] add dword ptr ds:[0x431750],eax将上面汇编代码转换成C语言
只需几秒就给出了具体实现代码,高科技是真牛X,牛X的PLUS。
比较遗憾它的在线运行代码,出错了,代码也不能改。刚好电脑上装了个VS2017,新建个程序复制代码去跑下。这效率,直接飞上天。代码直接跑的起来。从反汇编来看把固定的内容修改后,看看运行的注册是和反汇编的对不对。真实的注册码为:it0365 [CW-8610-CRACKED]
8610那就完成正确了。
我们稍稍修改下,把完整的注册码格式输出来。
#include "stdafx.h"#include <stdint.h>#include<stdio.h>
uint32_t memory_value = 0x29;
void simulate_assembly_code(uint8_t* local_4_ptr) {uint8_t byte_value = *local_4_ptr;
uint32_t multiply_result = (uint32_t)byte_value * memory_value;
memory_value = multiply_result;
uint32_t current_value = memory_value;
memory_value += current_value; }
int main() {uint8_t test_byte = 0x69;uint8_t* test_ptr = &test_byte;
printf("初始内存值: %u\n", memory_value);printf("输入的用户名:%s,字节值: %u\n","it0365", test_byte);
simulate_assembly_code(test_ptr);
printf("最终内存值: %u\n", memory_value);printf("注册码:CW-%u-CRACKED\n", memory_value);
getchar();return 0;}
执行结果
到此我们简简单单把一个软件的注册机都写好了。是不是很有成就感!!!!
阅读原文:原文链接
该文章在 2025/12/10 18:24:05 编辑过