160个CrackMe系列-003-Afkayas.2

selph
selph
发布于 2020-10-09 / 553 阅读
0
0

160个CrackMe系列-003-Afkayas.2

前言

这是160个CreakMe系列的第003个CM,难度:☆;(涉及浮点数运算)

这次这个浮点数直接进入我的知识盲区了,临时搜搜查查,算是大概弄懂了这个程序的序列号。

本次分析使用到的环境和工具如下:

  • 操作系统:Windows 10 2004(物理机)
  • 工具:x32dbg
  • IDE:Visual Studio 2019

软件分析

image-20201007162115765

跟上一个CM一样,是用户名+序列号的验证

那么这次的分析目标也是:实现验证的破解,以及分析出来序列号的算法

分析目标1:暴力破解

这个的暴力破解跟上一个一样,查找字符串,然后把跳转给修改了

image-20201007162648085

je改成了jne或者nop即可

分析目标2:注册机

之前分析了一大堆没分析出来,看了大佬们的题解,仿佛懂了什么,现在重新来分析

VB反汇编常见函数功能:https://www.cnblogs.com/bbdxf/p/3780187.html

因为这个程序和上一个很相似,至少算得第一个数字的过程是一样的,所以我们从导入函数计算字符串长度的那个call开始往下分析

image-20201007194736564

刚开始这一块跟上一个程序是一样的,获取字符串长度,长度*一个数+首字母ascii值,然后十六进制转十进制

用户名abc,那第一个数字算出来是266761

我前面犯的一个错,要知道这些函数只是实现一些功能,而加密的逻辑不在这些函数里面,不用往里面分析

然后往下步过,注意观察x32dbg右边提示的数字,如果出现了刚刚我们算的第一个数字,那就要注意了:

image-20201007195720276

往下走一会,就遇到了一个要把这个数字入栈调用函数的地方,这里入栈了的一个是我们第一个数字,另一个是一个地址

通过查阅资料,vb程序反汇编函数__vbaR8str的功能是: 将一个字符串转为双精度单精度浮点型(8个字节)的数值形式

一路步过下去,一共看见过3个数字:266763,800287,800302,而这个800302就是正确的序列号,所以在此推测,这里面经过了三次运算,最后得到了正确的值,然后去分析这几个数字出现的地方吧:

这一块代码的主要内容是:

image-20201007203737154

将266761转换成浮点型,存储在st(0)里,然后进行一个判断,这里判断是不跳转,所以浮点数10.0/5.0=2.0,也堆到st里,然后st1和st0相加,变成266763了,然后又转换成了字符串


接着往下看:

image-20201007204514869

第二段运算呢是,先把字符串变成浮点数,然后乘2.125,再减去2.0,得到800287

至于浮点数在内存中是怎么表示的,可以用这个网站来计算一下:

http://lostphp.com/hexconvert/


第三段计算

image-20201007205951429

跟前两段差不多,这次是+15.0

这里是双精度浮点型,注意是双精度,用转换器要选择双精度的,不然算不出来!

http://www.binaryconvert.com/result_double.html?decimal=045049053

用这个转换器就行


到此计算已经完成了,序列号的生成已经很清楚了

算法是

((字符串长度*15B38+首字母ASCII码值)+2.0) * 3.0 - 2.0 + 15.0

我们手动算一个来验算一下:

用户名:abcd
序列号为:
4 * 0x15B38 + 0x61 =  0x56D41
0x56D41 = 355649
(355649.0 +2.0)*3.0 = 1066953.0
1066953.0 - 2.0 + 15.0 = 1066966

验证一下:

image-20201007211731602

编写注册机

#include<stdio.h>
#include<windows.h>

int main() {
	// 获取用户名
	char username[MAXBYTE] = { 0 };
	printf("请输入用户名:"); scanf_s("%s",username,MAXBYTE);

	//计算序列号
	char szbuffer[MAXBYTE] = { 0 };
	int nSeries = (strlen(username) * 0x15B38 + username[0] + 2) * 3 + 13;
	printf("序列号是:%d\r\n",nSeries);

	system("pause");
	return 0;
}

效果演示:

image-20201007212422893

总结

这次的实践让我认识到了我对浮点数一无所知,要去补一下基础知识了

这次我学习到新的分析思路:不要钻到某个调用里,看主要的逻辑,看函数的功能,借助往上的资料来了解反汇编函数是干嘛的,遇到问题多看看大家是怎么做的,能让人学到新思路,不要一门心思自己钻研,要多去看看别人的分享!


评论