全网首发!逆向分析学生机房管理助手7.4随机进程名算法

本文详细介绍了如何分析学生机房管理助手7.4版本的随机进程名算法,包括脱壳、去除控制流混淆、分析代码等步骤。通过NETReactorSlayer工具成功去除混淆,并解析出随机名生成逻辑,最终提供了解决方案。
摘要由CSDN通过智能技术生成

一到九月份,学生机房管理助手就直接开始窜稀式更新,连更两个版本,这使我弄不到7.3的样本,只能分析7.4了。大伙有7.3样本欢迎联系我。
7.2版本分析见最新支持7.2!用C++干掉讨厌的学生机房管理助手

此文章大致是按照我研究的思路来写的,这样写得容易些,如果阅读比较困难,请见谅,谢谢。
开始分析:

概述

7.4版本截图

截图

先尝试运行样本,可以发现,还是jfglzs.exe和prozs.exe在运行,只是prozs.exe的随机名算法更换了。扫描prozs.exe:

Die扫描

脱壳

几乎没啥变化,那就丢进de4dot脱个壳吧(这里是GUI版本加上吾爱破解的de4dot)

第一次脱壳

呃,失败了。将混淆类型(-p参数)改成.NET Reactor 4.x试看看吧:

第二次脱壳

还是有报错,但是起码保存了一半,抱着侥幸心理瞅瞅dnSpy可以反编译么:

打开源代码1

可以看到结构与7.2相似(可看我分析文章),进入Form1_Load()方法:

源代码2
代码很长,且与我们之前看到的不同:多个switch()和跳转语句,很明显是做了控制流混淆,而de4dot修为不够,对这个写得和OLG一样的程序无从下手!
其实我们如果就根据这些代码一个个检查、跳转,也可以大致还原出它的逻辑(我最初就是这样做的),可是太麻烦又太容易出错。

去除控制流混淆

根据Die扫描结果,此程序使用了.NET Reactor 4.8-4.9的壳,而有一个工具,NETReactorSlayer(https://github.com/SychicBoy/NETReactorSlayer),专治这类不听话的壳!!!

我们把带有控制流混淆的哪个de4dot脱到一半的程序丢进去,仅勾选去除控制流混淆(第二列第一个选项),进行处理(如果把源程序拖进去并全部勾选,会出现所有方法为空的问题,而将de4dot处理过的给它处理就没事):

去除混淆

非常成功啊,那么我们再拖进dnSpy看看,控制流混淆已经没啦,节省了我们很多时间!

分析代码

我们知道prozs.exe的随机名随日期不同而变化,那么在Form1_Load()方法中找到涉及DateAndTime的语句即可:

源代码3

可以看见一系列求余操作,这告诉我们,这便是算法所在地!!
将其简化并翻译成C++代码即可。

可是这里面是不是有些问题?几个字符串加起来,没赋值给一个字符串变量,而是赋值给了num5,这是怎么回事?往下看:

源代码4

原来实际名称是string_1,它在284行定义:

this.string_1 = num5 + Class7.smethod_11(44);

是表示那4个字符拼起来的num5和一个奇怪方法的和,进入这个方法看看:

源代码5

哦!脑壳疼,原来是给定一数字经过一堆算法处理,返回一个字符串。后面一大堆我就不放出来ex大伙了,只要知道传进的整数和返回值有唯一对应关系即可。

接下来string_1的来历即可理解成:4个经过算法计算的字符的和(被赋给一整数)加上一个字符串常量。字符串常量的值是多少呢?我本来想打断点调试,可是应该是此脱壳后程序不完整的缘故,调试不了。那么我们就实际上机操作,揣测一下这些字符经过了怎样的处理。

插曲,反混淆时的错误

现在先注意这一点:如果你仔细观察上列“包含控制流混淆的代码”和“脱去控制流混淆的代码”,会在几个字符加起来的环节发现问题。我将代码贴过来对比(原程序代码控制流混淆已简化以方便观察):
未脱去混淆

//前面计算省略
if (num9 % 2 == 0)
{
	num5 = Conversions.ToString(Strings.Chr(118 + num7)) + 
		Conversions.ToString(Strings.Chr(85 + num3)) + 
		Conversions.ToString(Strings.Chr(108 + num5)) + 
		Conversions.ToString(Strings.Chr(75 + num10));
}else{
	num5 = Conversions.ToString(Strings.Chr(108 + num3)) + 
		Conversions.ToString(Strings.Chr(75 + num7)) + 
		Conversions.ToString(Strings.Chr(118 + num5)) + 
		Conversions.ToString(Strings.Chr(85 + num10));
}
//其后省略

已脱去混淆:

if (num3 % 2 == 0)
{
	num5 = Conversions.ToString(Strings.Chr(118 + num4)) + 
		Conversions.ToString(Strings.Chr(99)) + 
		Conversions.ToString(Strings.Chr(108 + num5)) + 
		Conversions.ToString(Strings.Chr(75 + num6));
}
else
{
	num5 = Conversions.ToString(Strings.Chr(124)) + 
		Conversions.ToString(Strings.Chr(75 + num4)) + 
		Conversions.ToString(Strings.Chr(118 + num5)) + 
		Conversions.ToString(Strings.Chr(85 + num6));
}

变量名的不同属反混淆引擎去除累赘代码后进行的化简,我们只需要知道脱混淆前和脱混淆后的变量名有对应关系就行。

真正的差异是,脱去混淆后部分字符的计算变为了直接给常量,而未脱混淆的则是有加法计算。
实际上这是反混淆引擎的失误,我们修正得到C++代码:

SYSTEMTIME time;
GetLocalTime(&time);//头文件windows.h
char c1, c2, c3, c4;
int n3 = time.wMonth * time.wDay, n4 = n3 % 7, n5 = n3 % 5, n6 = n3 % 3;
int n = n3 % 9;
if (n3 % 2 == 0) {
	c1 = 118 + n4,  c2 = 85 + n,  c3 = 108 + n5,  c4 = 75 + n6;
} else {
	c1 = 108 + n,  c2 = 75 + n4,  c3 = 118 + n5,  c4 = 85 + n6;
}
char c[5] = {c1, c2, c3, c4, '\0'};

分析字符串的处理

我根据反编译得到的算法,计算得出10月2日,4个字符为|WlM,实际上机测试,发现文件名为rMbC。粗略一看,完全不同,再看一下,发现第2与第4字符同为大写。将这些字符转换成ASCII号:
|WlM->124 87 108 77
rMbC->114 77 98 67
这样看,差异就显而易见了,原来那个神秘的处理其实就是给每个字符减去了10。而那句算法其实就是增加逆向难度,吓唬人罢了。
翻译成C++时,只需要将给每一个字符加上的那些数字都减10,即:

SYSTEMTIME time;
GetLocalTime(&time);//头文件windows.h
char c1, c2, c3, c4;
int n3 = time.wMonth * time.wDay, n4 = n3 % 7, n5 = n3 % 5, n6 = n3 % 3;
int n = n3 % 9;
if (n3 % 2 == 0) {
	c1 = 108 + n4,  c2 = 75 + n,  c3 = 98 + n5,  c4 = 65 + n6;
} else {
	c1 = 98 + n,  c2 = 65 + n4,  c3 = 108 + n5,  c4 = 75 + n6;
}
char c[5] = {c1, c2, c3, c4, '\0'};					

这样计算,才是最终结果。我们根据如上代码,将字符串c末尾加上“.exe”,跟jfglzs.exe一起结束进程,机房助手就没了!

还有一点要注意

我之前不知道,机房助手除了jfglzs.exe和prozs.exe互相保护外,还有一个zmserv服务,如果杀掉机房助手后不停止它,它会导致关机,而且是突然关机,断电般的关机,我找了半天原因才知道是这个服务搞的鬼。

停止服务代码(头文件windows.h):

SC_HANDLE sc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE zm = OpenService(sc, "zmserv", SERVICE_STOP);
SERVICE_STATUS ss = {};
ControlService(zm, SERVICE_CONTROL_STOP, &ss);
CloseServiceHandle(sc);
CloseServiceHandle(zm);

全文完。
这篇文章属全网首发,很多问题都是我自己解决的,写得那么辛苦,大伙给个点赞或收藏鼓励一下我吧!您的支持是我更新的动力。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值