软件逆向技术零基础入门18:这样做你也能快速找到注册码和算法位置
|
admin
2026年1月15日 15:14
本文热度 1040
|
继续学习软件逆向技术零基础入门18个实例。前面有分析过,是同一个作者写的crackme,这个实例相比前一个他提高了点难度。当我们拿到一个软件时,首先是要运行它,了解下它的一个界面和大概的功能。比如我们今天分析的软件就相对简单,就是一个按钮。名字有个默认的用户名,要求我们输入注册码。这次的软件和前面相比,输入错误的注册码,它没有任何提示,并直接将注册码框清空。对于这种没有提示和报错的软件,如何定位到关键的位置进行分析呢?作为一名正向开发人员的话,向编辑框中写入内容,我们肯定就要去获取它。获取到用户输入的内容后才会去做其它操作。VC编程中,读取编辑框内容就有个API函数:GetDlgItemText,其它分为 GetDlgItemTextA、GetDlgItemTextW分别是窄字节与多字节编码具体看用户开发的软件用的哪种编码。如果下API断点不确定软件是哪个编码,就2个API都下个断点,看它断在哪上就行了。打开调试器x32dbg.exe,前面文章中总有人说OllyDBG.EXE太老,没用了。其它调试器用哪个都是一样的,看自己习惯。只是OllyDBG.EXE它只支持分析32位软件。这节中就用新的调试器进行分析吧。按上面软件开发思路对 GetDlgItemTextA 进行下断点调试,看看会不会断下。CTRL+G 输入 GetDlgItemTextA 来到系统模块中API头部在头部双击下断点,或按F2键,F9运行软件,启动后输入假的注册码前面的猜想是正确的,软件确实也断下来。在堆栈窗口中有个地址调用,我们直接反汇编窗口查看是哪里调用了它在下一段代码下断点。进行F9运行到当前地址上继续分析。004013C6 | E8 49020000 | call <JMP.&GetDlgItemTextA> |004013CB | 89C3 | mov ebx,eax |004013CD | 83FB 08 | cmp ebx,8 |004013D0 | 74 10 | je 18.4013E2 |004013D2 | 6A 00 | push 0 |004013D4 | 6A 66 | push 66 |004013D6 | FF75 08 | push dword ptr ss:[ebp+8] |004013D9 | E8 2A020000 | call <JMP.&SetDlgItemTextA> |
这里读取了注册码,获取了它的长度进行和8比较。不相等就直接清空内容了。说明注册码长度要等于8。继续往下分析,进行了注册码生成和对比的关键算法位置:004013E4 | 8B3D 38204000 | mov edi,dword ptr ds:[402038] | 00402038:&"figugegl"004013EA | 0FB6741D CA | movzx esi,byte ptr ss:[ebp+ebx-36] |004013EF | 0FB6541D DF | movzx edx,byte ptr ss:[ebp+ebx-21] |004013F4 | B9 07000000 | mov ecx,7 |004013F9 | 29D9 | sub ecx,ebx |004013FB | 0FBE0C0F | movsx ecx,byte ptr ds:[edi+ecx] |004013FF | 89D0 | mov eax,edx |00401401 | 31C8 | xor eax,ecx |00401403 | B9 08000000 | mov ecx,8 |00401408 | 99 | cdq |00401409 | F7F9 | idiv ecx |0040140B | 0FBE3C17 | movsx edi,byte ptr ds:[edi+edx] |0040140F | 39FE | cmp esi,edi |00401411 | 74 1A | je 18.40142D |00401413 | 6A 00 | push 0 |00401415 | FF35 44204000 | push dword ptr ds:[402044] | 00402044:&"Uuuups..."0040141B | FF35 48204000 | push dword ptr ds:[402048] | 00402048:&"Something's wrong!"00401421 | FF75 08 | push dword ptr ss:[ebp+8] |00401424 | E8 27020000 | call <JMP.&MessageBoxA> |00401429 | 31C0 | xor eax,eax |0040142B | EB 1F | jmp 18.40144C |0040142D | 43 | inc ebx |0040142E | 83FB 08 | cmp ebx,8 |00401431 | 7C B1 | jl 18.4013E4 |
关键的算法我们分析知道,它在取用户名,注册码的ascii码进行运算后,从一个常量字符中取值组成注册码。00401411 | 74 1A | je 18.40142D |
这个比较就是真假注册码的比较,我们把它改成JMP让它跳,把每次运行到这记录EDI的值。就是真实的注册码了。我们在分析时输入it0365..得到了一组注册码:eueguglf1、定义了常量字符串"figugegl"作为加密密钥2、用户输入一个用户名对每个输入字符,获取其ASCII值并与常量字符串从后往前对应位置字符进行异或运算将异或结果对8取余,再用余数从常量字符串中选取对应字符
3、最终将所有处理后的字符组合成结果字符串输出得到最终的注册码
#include "stdafx.h"
#include <stdio.h>#include <string.h>
int main() { const char figugegl[] = "figugegl"; char input[1000]; char result[1000];
printf("请输入用户名: "); fgets(input, sizeof(input), stdin);
int len = strlen(input); if (len > 0 && input[len-1] == '\n') { input[len-1] = '\0'; len--; }
if (len == 0) { printf("输入为空\n"); return 1; }
int fig_len = strlen(figugegl);
for (int i = 0; i < len; i++) { int ascii_val = (int)input[i];
int fig_index = (len - 1 - i) % fig_len; char constant_char = figugegl[ fig_index];
int xor_result = ascii_val ^ (int)constant_char;
int remainder = xor_result % 8;
int final_index = remainder % fig_len; result[i] = figugegl[final_index]; }
result[len] = '\0';
printf("注册码为: %s\n", result);
return 0;}
阅读原文:https://mp.weixin.qq.com/s/dTkF1QKR9bl3kyQzUupBLQ
该文章在 2026/1/15 17:46:15 编辑过