0x00 基本信息

首先通过exeinfo确定该文件是一个exe vc++编译 有标准的winMain函数
image.png

可以在xp下跑,直接使用SysTracer.exe 查看一下行为:
image.png

这里可以看到,样本运行后,将会在启动目录下新建一个文件,然后在appdata目录下释放一个AaccroR3d2.exe.exe文件。

经过hash查询,可以知道appdata目录下释放的这个AaccroR3d2.exe.exe实际上就是原始的样本。
并且查看原始样本的运行目录,可以发现样本已经被删除,所以我们可以知道,样本运行后,会删除自身,然后将自身重命名并移动到%appdata%目录下。同时在启动目录下创建一个新文件。
尝试在win7下运行,可以知道创建的文件是一个快捷方式,指向在%appdata%路径下释放的文件
image.png

0x01 样本分析

IDA信息

IDA里面基本信息如下,可以看到样本的.text段很小,只有3000的大小,左边窗口的FunctionName也很少,并且最后还有一个自定义的DATA段,所以可以猜测样本的主要功能并不在.text段,而是在加密的DATA段中。
image.png

DATA段数据如下:
image.png

定位关键代码

image.png

winMain函数的结构很简单,几乎看不到恶意行为,但是其中调用了sub_401000函数,sub_401000函数一共800多行,并且有大量计算操作,所以我打算用调试器过来看看。

首先尝试直接winMain的起始地址00402DA0下断点跑过来
image.png

然后程序就跑飞了
image.png

然后终止
image.png

这就是说明,程序是没有跑到winMain函数的,这种有两种情况
1是winMain函数之前有反调试
2是样本的真实代码在winMain之前跑完了
两种情况都是修改了样本的CRT。

为了验证到底是哪种情况,我们可以结合SysTracer一起分析
我们首先用SysTracer加载od:
image.png

然后通过od加载exe,程序默认停在入口点
image.png

然后在WinMain设置断点并且清空SysTracer的当前日志
image.png

然后F9运行,可以发现od依旧没有断在winMain,但是SysTracer已经捕获到了之前的恶意行为。
所以可以说明该样本的关键代码在WinMain之前,根本就没有执行WinMain。
image.png

所以我们在start函数中看看程序到底是哪儿跳走的。
start函数如下:
image.png

从start函数f8单步往下走,发现在00402F9E处有一个 call initterm函数,F8过了之后程序od就陷入了运行状态。
image.png

_initterm函数目前可以不用知晓这里的原理,因为涉及到CRT的一些处理。
image.png

我们直接F7进入到initterm函数,是调用的系统的_initterm函数
image.png

然后F7往下,过来了之后是系统空间
image.png

不用管这里面到底做了什么操作,直接一直按住F8 往下走,直到回到用户空间
程序最后通过一个retn 返回到了用户的地址空间image.png

回来的地址是0041B82D (这里注意存一个快照,后面的代码IDA里面看不到,可能要调试多次)
image.png

我们在IDA里面可以看到该地址就是我们最开始分析的DATA段中
image.png

所以程序在之前的initterm中应该是执行了解密操作解密了DATA段的数据,然后跳入过来执行。

DATA段代码分析

样本首先会通过GetProcAddress获取SHGetFolderPath进行调用,以获取用户系统目录
image.png

成功获取到%appdata%目录
image.png

同样的操作,通过GetModuleFileName获取到程序当前的运行路径
image.png

然后通过lstrcmpiW比较一下当前运行的路径和指定的是否相同
image.png

如果不同则会通过MoveFile函数将文件移动到%appdata%目录下并重命名
image.png

移动之后,则会在启动菜单下创建该文件的快捷方式
image.png

image.png

然后调用CreateProcess函数创建一个新进程,启动的新进程就是释放在%appdata%目录下的AccroRd2.exe.exe
image.png

因为这里有对路径的判断,我们可以直接重新加载%appdata%目录下的AccroRd2.exe.exe看看会发生什么
还是通过之前的方法,让程序跑到比较文件这儿,这里可以看je跳转已经实现。
image.png

直接跳转到最后ret出当前函数:
image.png

所以这部分的代码功能就是将自身移动到%appdata%目录下并重命名,增加开始菜单的快捷方式。
我们看retn出去之后的代码。
image.png

retn回来的代码带有混淆了,od无法正常识别。
这种代码调的时候,多多注意EAX和堆栈

F8单步往下走,有很多jmp 和call
image.png

比如遇到这样的call 我们想知道GetProcAddress获取的是哪个API的地址,但是这里我们并不能直接鼠标往上滑去找push的参数。滑动鼠标这里的代码将会变成这样,无法找到call edi这行代码了。
image.png

从上面的图我们可以看到call edi的hex数据是FF D7
而下面这张图中,FF D7 已经识别错误,跟其他数据连起来,变成一个地址了。

所以这种混淆的代码,我们就往下走,call完之后多注意eax的值。

一直往下走,程序调用了CreateProcess函数
这里有两个关键参数,ModuleFileName和CommandLine
两个参数的值都是当前的这个程序路径。说明该程序会创新一个新的进程,新进程的参数就是当前程序的路径。
image.png

往下走,程序会分配两次内存
image.png

然后通过RltMoveMemory填充
image.png

填充后如下:
image.png

接着通过0041b752函数解密出一个PE文件
image.png

多次通过writeprocessmemory 改写进程内存
image.png

可以看到UPX0 UPX1的提示信息
image.png

image.png

这里的操作应该是解密数据

最后解密完成了之后会执行解密的代码并通过ExitProcess退出当前的程序

我们将这片内存dump出来。
image.png

exeinfo查壳可以看到是upx加壳的,和我们之前在内存中看到的一致
image.png

直接通过upx -d 进行脱壳
image.png

脱壳成功
image.png

dump PE分析

解密出来的PE入口如下
image.png

第一个函数sub_40392d没有什么实际意义
第二个函数sub_40c3c5是一个解密函数,内容如下:
image.png

第三个函数sub_40AC20也不用管 这种函数 可以F8直接过 有时间也可以调一下看下具体解密的内容
image.png

第四个函数sub_40A7AE会解密出通信的C2:prefetch.no-ip.biz:3360
image.png

然后就可以根据这个C2去网上查询该C2的相关信息 定位下家族什么的,需要注意这里要注意一下样本的时间和这个C2的有效时间。

然后程序在第五个函数sub_40A3CE创建了一个名为AxEXpdAb的互斥体
image.png

如果互斥体存在,说明程序已经存在,则退出进程
image.png

创建互斥体之后,程序通过设置
\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\注册表键值将自己设置为开机自启动
image.png

设置代理
image.png

恢复干净快照之后可以看到行为
程序会不停对我们在调试时候看到的C2地址发起dns请求。
请求的dns是prefetch.no-ip.biz
image.png

在奇安信的平台上查询可以看到该域名被打上了VBKrypt的标签
image.png

通过powershell在本地计算出hash后,在vt查询该文件hash可以知道该文件约为13年到15年之间上传
image.png