0%

记一次以DLL程序作后门的样本分析

前言

最近快被自己懒哭了,自从这学期结束后这段时间里感觉全都在玩,但实际也没玩的痛快,时间倒是过的挺快,不行,我最近得调整一下。

最近在看《恶意代码分析实战》这本书,把高级静态分析看完了,看到课后有一个样本不错,挺有意思,挺经典的,决定拿来完整分析一波。

正文

这次的样本总共两个:

Lab07-03.exe MD5 : BD62DAB79881BC6EC0F6BE4EEF1075BC

Lab07-03.dll MD5 : 290934C61DE9176AD682FFDD65F0A669

基本静态分析

首先查看一下两个样本中的strings:

先看DLL程序的(部分):

UfQn76.png

这里觉得有意思的字符串有:

exec

sleep

hello

127.26.152.13

可以看到有一个IP地址,这个恶意代码有可能连接到这个地址。同时也有exec,sleep,hello这些字符串,这些等会在ida pro中查看具体信息。

然后看一下exe程序的字符串(部分):

UfQw4S.png

这里有意思的字符串多了起来:

kerne132.dll

kernel32.dll

.exe

C:\*

C:\windows\system32\kerne132.dll

kernel32.

Lab07-03.dll

C:\windows\system32\kernel32.dll

WARNING_THIS_WILL_DESTROY_YOUR_MACHINE

字符串kerne132.dll和kernel32.dll很像,但是是用数字1替换了字母l,里面出现的目录信息告诉有可能用kerne132.dll代替掉了kernel32.dll,但是具体还是得到反汇编里面分析具体功能。而C:\*则告诉我们这个恶意代码有可能在c盘下找什么东西,最后字符串WARNING_THIS_WILL_DESTROY_YOUR_MACHINE,这个应该是《恶意代码分析实战》这本书作者加上的,用来标识这个程序代码为用来学习的人工制品。

现在放到PEID里面看一下基本的静态信息:

先看DLL程序的:
UflCDI.png

其实可看到东西差不多,这个DLL没有加壳,奇怪的作为DLL程序,没有导出函数,它不能被被另一个程序所导入,尽管程序还是可以调用一个LoadLibrary来载入一个DLL程序,但是这一点还是比较值得注意的,然后可以看到DLL程序的导入函数,除了注意和网络相关的ws2_32.dll之外,还要注意其导入了kernel32.dll中的CreatProcess函数,这说明这个程序有可能创建另一个进程。

再看看EXE程序的:

UflY24.png

这里发现几个有意思的导入函数:

CreateFileA

CreateFileMappingA

MapViewOfFile

IsBadReadPtr

UnmapViewOfFile

CloseHandle

FindFirstFileA

FindClose

FindNextFileA

CopyFileA

这些函数告诉的信息不少,这个程序有可能打开一个文件,并且映射到内存中去。同时FindFirstFileA和FindNextFileA函数又说明这个程序可能搜索目录,并使用CopyFileA来复制它找到的文件。而且可以看到这个EXE程序并没有导入Lab07-03.dll,LoadLibrary或者GetProAddress,这一点说明这个程序并没有加载那个DLL程序,这一点是比较可疑的。

高级静态分析

接下来,尝试将两个文件导入到ida pro里面反汇编分析:

首先看一下DLL程序,因为这个程序比较简单:

UflWqI.png

ida pro这里定位到DllMain的位置,可以看到DllMain这里有很多代码,按照逻辑顺序可以看一下:

UfRi5V.png

这里首先用__alloca_probe函数申请了很大一片栈空间

UfRYKH.png

之后又通过OpenMutexA函数检查有没有SADFHUHF这个互斥量,没有的话就通过CreateMutexA函数建立这个互斥量,这个的目的是让同一时刻只有一个该程序的实例在运行。

UffFcF.png

之后通过socket连接到一个远程主机127.26.152.13,可以看到0x50h就是十进制80,那么就是连接到远程主机的80端口。

UffU4P.png

之后可以看到send发送了buf缓冲区里面的数据,buf指向的是字符串hello,这是一个受害主机连上远程服务器的第一件做的事情,目的就是让远程服务器知道受害主机已经准备好接收命令。

Uffd9f.png

之后又重新用buf来保存接收数据的,调用recv函数来等待服务器的命令。

Ufh82T.png

之后来比较缓冲区内接收到的来自远程服务器的命令和在程序硬编码中的字符串sleep,如果相等,那么

UfhNqJ.png

程序就会调用sleep函数睡眠0x60000h秒,之后返回到受害主机发送hello之前,再次发送hello,等待新一轮的命令。

UfhHsg.png

当和sleep对比不成功的时候,缓冲区数据就会和exec进行对比。

UTwdFf.png

当对比exec成功后,则会调用CreateProcessA函数来调用一个新进程,这里最主要的是这个lpCommandLine参数,这个指明要创建的进程,而lpCommandLine参数保存在edx中,而edx则是从栈上的局部变量CommandLine传进来的

UTwDSg.png

而局部变量CommandLine在之前的程序没有被调用过,但是可以从局部变量栈空间布局上找到线索,可以看到的是局部变量buf是从0x1000h上开始接收数据的,而CommandLine则是在栈上0x0FFBh开始的。这一下就知道CommandLine从哪里来的了,buf和CommandLine中间有五个字节大小的空间来保存接收的命令,后面部分则是给与CommandLine来指定要创建的进程,不难想象,受害主机从服务器接收到的命令格式大致为:exec xxxxxxx

UfTq5d.png

之后如果sleep和exec命令都没对比成功后,则会看是否为字符q退出命令,如果是则程序退出,不是则睡眠0x60000h时间,然后返回程序发送hello,等待接收新一轮的命令。

这个DLL程序比较简单,目的也很明确,就是一个后门程序,实现后门功能,这允许攻击者通过发送回复给80端口上的一个数据包,来启动一个系统上的可执行文件。但是问题的关键在于,这个DLL程序如何启动运行,这一点就要查看exe程序是如何运行的了。

接下来,分析exe程序:

UoxjRP.png

程序一开始先检测argc参数,检测程序启动时是否有两个参数,如果不是2个参数,程序就退出

UTmpUx.png

之后这个程序会把argv[1]放到EAX,并且和放到ESI寄存器的WARNING_THIS_WILL_DESTROY_YOUR_MACHINE字符串进行比较,只有相同时程序继续执行。

那么此时程序正确的执行方式就是在命令行中输入:

Lab07-03.exe WARNING_THIS_WILL_DESTROY_YOUR_MACHINE

继续看下去:

UTuoVA.png

UTuTUI.png

接下来连续调用CreateFileACreateFileMappingA以及MapViewOfFile,这里打开的是kernel32.dll以及Lab07-03.dll,把这两个文件调用内存进行操作,之后是一连续的复杂的对内存的读写操作,靠静态分析这里已经会很难而且没有必要,所以先绕过这段,看之后的程序运行。

UTKwJP.png

绕过一大段对内存的比较,计算偏移或者写入内存的操作代码,接下来可以看到使用CloseHandle函数完成了对那两个文件的操作,然后调用了CopyFileA函数,函数复制Lab07-03.dll并把它放到了C:\\windows\\system32\\kerne132.dll,注意这里是数字1,猜测放到这里是为了顶替kernel32.dll,但是如何顶替还得看下面一个值得关注的子函数sub_4011E0这个子函数有一个参数在调用之前压入栈中,就是字符串C:\\*

UTJoVO.png

用ida pro的f5功能查看子函数sub_4011E0的伪代码,从上面可以看到是调用FindFirstFileA函数在C盘内查找文件,当是一个文件夹的时候,子函数迭代调用,继续查找子文件夹中,而当文件后缀为.exe(在上面代码中asc_403030指向的就是.exe字符串),则此时会执行sub_4010A0子函数。那么子函数sub_4011E0的功能就明晰了,就是在C盘下找exe文件。现在来查看sub_4010A0子函数有什么功能:

UTYQJJ.png

这个sub_4010A0子函数会把子函数sub_4011E0传进来的exe文件名当CreateFileA参数,然后调用CreateFileMappingAMapViewOfFile函数,把文件在内存中映射好便于修改,而sub_4010A0子函数的核心代码功能就是上图所示,会在文件中找Str2字符串,这个字符串指向的则是kernel32.dll

UTYWFg.png

找到之后调用memcpy函数把dword_403010覆盖到之前kernel32.dll字符串的位置上,而dword_403010这个全局变量保存的是:

UTt639.png

这里ida pro没有识别出来这个是个字符串,可以按A键转化为ASCII码

UTtfHK.png

那么就好理解了,就是把在C盘找到的exe文件中的kernel32.dll替换成kerne132.dll,这样在启动这些exe文件的时候,原本会载入kernel32.dll,但是此时就会载入kerne132.dll,就实现了后门程序的启动。但是还有一个问题就是这些改动难道不会影响原来文件的使用吗?毕竟载入的dll文件改了,那些原本调用的kernel32.dll导入函数还能调用吗?

这里就想到刚才在Lab07-03.exe程序中绕过分析了把kernel32.dll以及Lab07-03.dll这两个文件调用内存进行操作的过程,现在准备动态运行分析一下:

UTNTaT.png

打开procmon,设置过滤条件

UTUPiD.png

然后再命令行敲入Lab07-03.exe WARNING_THIS_WILL_DESTROY_YOUR_MACHINE

UTUFRH.png

可以看到进程Lab07-03.exe启动后全是再C盘遍历查找exe文件

UTUlWQ.png

然后在C:\WINDOWS\system32文件夹下发现了kerne132.dll(这也太难区分了。。)

UTwsyj.png

用PEID查看它的导出表,可以发现不再是没有导出函数了,而是导出了原本kernel32.dll的导出函数,是重定向的导出函数,所以实际的功能还是再kernel32.dll中。而检查kernel32.dll的MD5发现前后没有修改过。

UTai7V.png

在C盘找到一个原本导入kernel32.dll的exe文件,查看现在的导入表,可以发现变成了kerne132.dll,那么就说明后门程序已经植入成功了。

总结

这次的两个样本Lab07-03.exe和Lab07-03.dll

其中样本Lab07-03.dll,则是一个后门程序,允许攻击者通过在127.26.152.13:80的远程服务器和样本进行通讯,可以执行的命令有:sleep,exec xxxxxx,q,每次样本发送hello来表示自己准备好接收新一轮的命令。

而另一个样本Lab07-03.exe是一个将后门程序Lab07-03.dll植入的样本,它的功能就是通过特殊的启动命令——在命令行输入Lab07-03.exe WARNING_THIS_WILL_DESTROY_YOUR_MACHINE启动程序。然后把Lab07-03.dll和kernel32.dll调入到内存中,对Lab07-03.dll进行修改,在Lab07-03.dll加入重定位的导出函数,导入函数重定位到kernel32.dll中,所以具体的功能还是在kernel32.dll中实现。再然后把Lab07-03.dll重命名为kerne132.dll进行混淆,放入到C:\WINDOWS\system32文件夹下。最后,在C盘搜索遍历exe文件,在exe文件中找到字符串kernel32.dll的位置,并用kerne132.dll替换它,这意味这个exe文件每一次启动都会试图加载后门程序,但因为kerne132.dll含有所有的kernel32.dll的导出函数,这样不至于原来的exe文件无法运行原有的功能。

(好不容易做完了,本来想写博客的是一个实战的样本,但是拖着拖着就忘了当时分析那个样本的思路了,重新完整分析耗时耗力,所以就挑了一个最近在看的书上的实验样本,也算是对之前学习的一个记录总结)