RARPasswordRecovery 逆向分析

Crack by 混入21的蒟蒻


暴力破解

运行安装包,安装对应的软件,拖入PE进行查壳分析,发现有一个 UPX 壳,直接利用 UPX.exe脱壳

脱去壳后拉入IDA分析

寻找对应的Register可以发现如下字符串 :

寻找对应的The Code you've entered invalid!之后我们利用对应的交叉引用进行查找有关函数而对程序进行分析,可以找到如下函数 :

之后跳转到图形界面进行分析 :

结合动态调试可以发现这 3 个函数会对程序获取到的密钥进行判断,如果为True则直接跳转到下面的The Code you've entered invalid!此时我们的注册环节就失败了,如果需要跳转到注册成功的界面那么我们需要在每一次的判断中都是False这样我们才能跳转到提示注册成功。

那么暴力破解这个就变得十分简单了,我们只需要更改对应的jz/jnz这两个跳转使其互换,那么就可以达到我们的目的了。

之后我们将补丁打上就完成了对应的注册暴力破解。


注册机

注册条件判断

在之前暴力破解时我们找到了对应的提示框显示的位置,可以明显的看到有一个if对 4 个表达式进行判断,如果要完成注册机的编写我们则需要让 4 个等式都成立即可,而这个也会是我们编写注册机的关键之处。


第一个条件

我们简单的动态调试一下发现只要第一个判断条件是对输入的数据长度进行判断,如果长度为 0 那么函数就会直接跳转到下面的The Code you've entered invalid!处,也就是意味着在第一个判断处我们仅需要保证输入的长度是大于0的就可以实现跳转到第二个条件中。


第二个条件

通过上图的汇编可以明显地发现有一个test函数,我们需要做的是让test函数的值为 1,也就是eax的值不为空,那么关键就是call里面的函数_wcsstr。我们点击进入该函数,进行分析。

通过图形化的界面我们可以看到程序的大致流程,我们通过输入进行测试,观察具体执行过程。

我们随意输入一串数字123456789进行测试,在流程中我们会在寄存器经常看到DA

经过一轮下来的动调发现,程序会一直在如下区间内一直循环 :

如果你常常看寄存器里的值你会发现在寄存器里你输入的值会一个个被pop掉(一直往下寻址),此时我们也通过浏览器查询_wcsstr函数作用企图获得一些灵感,在百度百科中介绍该函数是一个寻找的字符的一个函数 :

这或许就解释了在EDI寄存器中为什么我们的输入会一值向下寻址,可能就是在寻找寄存器中出现的DA ?我们更改一下我们的测试密钥更改成DADADADADA,再次对其进行测试。同样的我们在寄存器里会发现当读入我们的一个数据后出现了AOOSOFT-RAR-RECOVERY,感觉是不是有一点熟悉?

是不是少了一个D,不然就是程序的名字,我们继续按F8测试会发现在寄存器ECXAOSSOFT-RAR-RECOVERY会变成OSSOFT-RAR-RECOVERY但是继续调试过一个循环会发现又变成成了AOSSOFT-RAR-RECOVERY,但是读入A时又成了OSSOFT-RAR-RECOVERY,我们比那会很疑惑这个密钥是不是与程序的名字DAOSSOFT-RAR-RECOVERY有关系,我们再次改变密钥为DAdsaddasd4152,动调还是会发现ECXAOSSOFT-RAR-RECOVERY会变成OSSOFT-RAR-RECOVERY但是继续调试读入的数据是dOSSOFT-RAR-RECOVERY就变回了DA,因此我们确定了输入与密钥的部分关系——密钥开头DAOSSOFT-RAR-RECOVERY

至此我们就已经通过了两个条件了。


第三个条件

通过第二个条件时我们可以在寄存器里发现我们的输入会被存储于EAX寄存器中 :

同样的我们回到汇编层去分析程序 :

可以较为明显的看到,函数在第三个条件判断中运行了一次减法和一次右移的操作,我们要想通过,那么就需要保证在第二次测试的输入DAOSSOFT-RAR-RECOVERY保证后面有值进行运算减法和一次右移过后的值不为 0 就可以通过了,例如在DAOSSOFT-RAR-RECOVERY后添加一部分数字或者一部分字母,便可以通过第三个条件。


第四个条件

进入第四个条件时,通过汇编可以看到ECX的值等于EBX,同时将ECX入栈,下面有一个Call指令,调用了一个函数,而下面就是test al al,如果我们将鼠标放到al上,你会发现al的值为 0 ,那么意味着如果要进入到if语句内部那么al的只会在call的函数中发生改变,此时我们分析的重点便落到了call sub_417CE0 中。

进入该函数,我们转换成C的伪代码形式,进行判断该函数的作用。

进入后发现函数里面会有一大堆东西,其中大部分是去掉了函数名称,但是我们仍然可以在其中找到一些东西,wcshr__InterlockedDecrement两个函数名,经过百度我们可以了解到其相关信息。

wcshr

__InterlockedDecrement

百度后发现其类似于一种线程锁的东西?防止删除自己,因此我们便不用花费大量时间纠结于下面>的一堆if判断语句中。

通过分析wcshr函数内部有一个Stra和一个0x2Du,通过十六进制我们可以看到0x2Du的值为-,那么那条语句的作用便是在Stra中寻找-

前面是不是还有一些函数,它们的作用会是什么呢 ?

同样的在动态调试下我们通过单步步入和步出的组合进行观察和判断,并检测Stra的值,当我们动态调试过Stra处时将鼠标放在上面,你会发现Stra的函数值便是我们输入的值,但在经过后面两个函数过后你便会发现Stra变成固定开头后内容了。

之后便是我们的判断语句if,在判断条件中我们明显的可以看到判断的条件是Stra的长度要大于 3 ,之后再其中寻找-的位置返回给v2,如果寻找到了则会进行v1 = v2 - Stra,我们在动调下不难发现v1的长度便是固定开头后内容的长度减去Stra中带有-后边部分的长度。

在这个判断中我们需要做的就是让v1的值不为-10即可,之后的大多数函数都是不用进行过多的分析。


注册程序编写

经过上面的分析过后我们便可以成功的进行注册,程序会弹出来恭喜注册成功的提示 :

那么我们注册机应该怎么写呢?

我们再次简单的整理一下上述密钥的判断过程,可以得知密钥是以DAOSSOFT-RAR-RECOVERY为开头的,之后的输入都要满足之前的条件,要存在有-,使我们的最后一个条件成立——即v1不为-10即可。

分析过后我们便可以开始完成我们的编写,脚本如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
#include<cstring>
#include<windows.h>
#include<time.h>
using namespace std;
string rand_str(const int len)
{
/*初始化*/
string str; /*声明用来保存随机字符串的str*/
char c; /*声明字符c,用来保存随机生成的字符*/
int idx; /*用来循环的变量*/
/*循环向字符串中添加随机生成的字符*/
for(idx = 0;idx < len;idx ++)
{
/*rand()%26是取余,余数为0~25加上'a',就是字母a~z,详见asc码表*/
c = 'a' + rand()%26;
str.push_back(c); /*push_back()是string类尾插函数。这里插入随机字符c*/
}
return str; /*返回生成的随机字符串*/
}

int main(){
string str1,str2;
str1=rand_str(3);
str2=rand_str(3);
cout<<"您的密钥为:"<<"DAOSSOFT-RAR-RECOVERY"<<str1<<"-"<<str2<<endl;
return 0;
}

至此我们便完成了所有的破解工作。


魔改

那么对于这个程序我们是否可以魔改呢?

答案是肯定的。我们分析出来了程序的注册流程,我们便可以对其注册部分进行魔改,也可以对其输入输出的文本框进行修改。

改变密钥

我们根据上面的密钥分析我们可以得到对应的注册密钥是以DAOSSOFT-RAR-RECOVERY为开头的,那我们也可以更改对应的值,使其成为我们独有的加密。

我们找到DAOSSOFT-RAR-RECOVERY对应所在的位置,进行更改 :

之后进行测试 :

发现同样可以注册成功,完成我们的密钥魔改。

标题修改

我们同样的定位对应的数据位置,对其进行更改便可以达到与修改密钥一样的方式完成对应的修改过程,此处就不贴上对应的图了。


RARPasswordRecovery 逆向分析
https://equinox-shame.github.io/2022/03/14/RARPasswordRecovery 逆向分析/
作者
梓曰
发布于
2022年3月14日
许可协议