160 个 Crackme 之 066 -- figugegl.2 算法分析和注册机实现
有一段时间没有发贴了,这次发一个非常简单的,萌新可以来看看。160 个 CrackMe 之 066 -- figugegl.2 是一个 LCC-Win32 编译的 CrackMe,LCC 是一个小巧的 C 语言编译环境,编写简单的 C 程序比较方便,开发环境的体积很小,并且包括了资源编辑器。
先看看 CrackMe 的信息:
节的信息如下:
可见,该 CrackMe 没有加壳,编译器是 LCC Win32。
直接用OD载入,显示如下:
前面是 SEH 处理代码,后面一个内部过程调用,这个调用相当于 C 语言的 main() 函数。
跟随进入 main() 函数,如下图所示:
开始部分就是命令行参数处理,继续向下看,如下图所示:
在调用 KERNEL32.GetModuleHandleA() 后,就是 Windows 程序的入口函数了,即 WinMain() 函数。
再跟随这个 WinMain() 函数,如下图所示:
由上图可见,通过以下代码,生成一个对话框应用程序:
00401298|.6A 00 push 0 ; /lParam = NULL
0040129A|.68 4F144000 push 0040144F ; |DlgProc = figugegl.0040144F
0040129F|.6A 00 push 0 ; |hOwner = NULL
004012A1|.6A 64 push 64 ; |pTemplate = 64
004012A3|.57 push edi ; |hInst
004012A4|.E8 F7020000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
可以看到,DlgProc = 0x0040144F,通过 OD 的右键菜单“跟随立即数”,就可来到这个 DlgProc 了,如下图所示:
可以看到处理 WM_CLOSE, WM_INITDIALOG, WM_COMMAND 消息的代码,我们主要关心其处理 WM_COMMAND 代码,如图所示的所选代码部分,就是一个 Case 跳转,其参数 EAX = 0 ~ 3,共4种情况。
静态分析就到这里,我们先运行 CrackMe 看看,直接 F9,弹出 CrackMe 界面如下:
先输入假码注册,如上图所示,点“CHECK”。来到前面静态分析的 Case 跳转处,如下图所示:
可以看到,分成4个部分,在数据区,可以看到用到的 4 个地址。点击“CHECK”按钮时,EAX = 0x00000001,这就表示 CHECK 按钮的 ControlID 为 0x00000001。
上图显示,“CHECK”的处理代码如下:
004014A1 .FF75 08 push dword ptr
004014A4 .E8 FCFEFFFF call 004013A5 ;注册验证函数
004014A9 .59 pop ecx
004014AA .31C0 xor eax, eax
004014AC .40 inc eax
004014AD .EB 56 jmp short 00401505
其中,只有一个 call 004013A5 调用,接着直接返回 eax=1。跟随进入 call 调用,如下图所示:
这个过程就是注册码的算法代码,其中算法在上图所选择的代码内,算法也很简单。主要代码如下:
004013C2|.89C6 mov esi, eax ;名字的长度值
004013C4|.EB 06 jmp short 004013CC
004013C6|>C64435 EB 20 /mov byte ptr , 20 ;在name后添加 0x20,空格
004013CB|.46 |inc esi
004013CC|>83FE 14 cmp esi, 14 ;len < 20
004013CF|.^ 7C F5 \jl short 004013C6 ;长度<20,添加空格
004013D1|.31F6 xor esi, esi ;int i=0
004013D3|>0FB67C35 EB /movzx edi, byte ptr ;name
004013D8|.0FB65435 F5 |movzx edx, byte ptr ;name
004013DD|.89F8 |mov eax, edi
004013DF|.31D0 |xor eax, edx ;xor值 = name^name
004013E1|.B9 0A000000 |mov ecx, 0A ;10
004013E6|.99 |cdq
004013E7|.F7F9 |idiv ecx
004013E9|.83C2 30 |add edx, 30 ;dl = (xor值 % 10) + '0'
004013EC|.885435 D6 |mov byte ptr , dl ;serial = dl
004013F0|.46 |inc esi
004013F1|.39CE |cmp esi, ecx ;i<10
004013F3|.^ 7C DE \jl short 004013D3 ;循环
分析如下:
1、通过 GetDlgItemTextA() 取得界面上输入的用户名;
2、如果用户名长度不够20个字符,则在后面添加空格字符,直到长度达到20个字符;
3、取名字第1到10字符,依次与名字的第11到20字符异或运算;
4、将异或运算后的结果与10求余,并加上0x30,实际上就是生成一个'0'~'9'范围的数字字符。
5、将前面生成的10个数字字符组成序列号(但这个数字并不一定是真正的序列号,看下面説明)。
6、CrackMe 并没有用上面生成的序列号与界面上输入的序列号进行字符串比较,而是先转换成整数再进行比较的。如上图所示,是通过库函数 strtoul() 函数转换的,不过,前面代码生成的序列号有10位数字,当大于最大无符号整数范围(0xFFFFFFFF,也就是 4294967295)时,会返回最大无符号整数(0xFFFFFFFF)。这个时候,我们输入的就不能是前面1~5步生成的序列号了,而是一个常数:4294967295。
如下图所示:
前5步生成的序列号是:8359659000,明显这个数字已超出 4294967295 了,即溢出了。
通过 strtoul()转换后,EAX 返回的是 0xFFFFFFFF,也就是 4294967295 了,明显已经是不正确的值了。
转换计算的序列号以后, CrackMe 通过调用 GetDlgItemInt() 函数,从界面取回输入的序列号,然后与转换后的序列号比较,如下图所示:
比较后,根据结果会跳转到下面显示正确与否的提示。
如上图所示,两个序列号不相等,结果是失败,显示信息如下:
我们根据前面的分析,重新输入新的序列号:4294967295。如下图所示:
再点“CHECK”,来到序列号比较处,如下图所示:
这次是一样的了,都是 0xFFFFFFFF,即 4294967295 了。F9 继续,这次提示如下了:
表明这次序列号输入正确。
前面测试的是一个异常的序列号,下面我们看看正常的序列号,如下图所示,先把 name 改一下:
点击“CHECK”,再次来到序列号比较的代码处:
可以看到,这次转换正常了,没有溢出了,序列号是 3966900000,小于 4294967295,转换正常了。
F9 运行,返回界面。输入正确的序列号,如下图所示:
重新点击“CHECK”,再一次来到序列号对比的代码处:
可以看到,这次是相等的了,F9后,提示如下,表明序列号正确:
分析完毕!!!
下面代码是根据前面分析的算法写出的注册机:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getSN(char * name);
int main(int argc, char** argv) {
char name = {0};
printf("Input your name: ");
gets(name);
getSN(name);
return 0;
}
int getSN(char * name) {
int n=strlen(name);
for (int i=n; i<20; i++) {
name = 0x20; /// padding
}
unsigned long long check = 0;
for (int i=0; i<10; i++) {
check = check * 10 + (name ^ name) % 10;
}
if(check>>32) {
printf("Serial: 4294967295\n"); /// overflow, Max: 0xFFFFFFFF
} else {
printf("Serial: %lu\n", check); /// normal case
}
return 0;
}
使用 Dev-C++ 调试通过。
w780628d 发表于 2019-11-19 06:52
这个真看不懂。
这个 Crackme 已是相当的简单了。如果不写贴,不写注册机,三~五分钟不到就可找到码了。 hfxiang 发表于 2019-11-19 10:09
这个好像是太专业了,学习起来有困难
这个就是一个裸*奔的结构清晰的货,已是很简单的了。。。 学习一下,给楼主点个赞{:1_921:} 这个好像是太专业了,学习起来有困难 虽然我看不懂,评分支持一下 有看没有懂,最基础的还没看懂 支持一下 高手简单,初学难!赞!
页:
[1]
2