首页
论坛
课程
招聘
[调试逆向] [病毒木马] [原创]【逆向分析】远控木马白加黑劫持 dll反射注入分析 #30天写作挑战#
2020-9-19 16:36 2722

[调试逆向] [病毒木马] [原创]【逆向分析】远控木马白加黑劫持 dll反射注入分析 #30天写作挑战#

2020-9-19 16:36
2722

前言

病毒采用了白加黑劫持动态库、远程申请代码执行,内存解密数据dll反射注入的手段进行执行恶意远控代码,技术值得学习与分析。

 

白文件 Catholic Bishops call for urgent Cameroon peace talks.exe
动态库劫持 wwlib.dll
白文件 AvastProxy.exe
动态库劫持 wsc.dll
加密的数据文件 main.dat

Catholic Bishops call for urgent Cameroon peace talks.exe 白文件

Catholic Bishops call for urgent Cameroon peace talks.exe是微软的office word程序,wwlib.dll利用劫持技术执行恶意行为。IDA打开Catholic Bishops call for urgent Cameroon peace talks.exe,查看导出函数没有找到名为wwiib的模块,搜索字符串找到了获取这个模块的代码位置

 

wwlib.dll 劫持病毒文件

该dll行为主要是启动迷惑doc文件,然后请求数据块解密到内存执行,然后再此请求病毒文件。

 

IDA打开wwlib.dll文件,能够找到导出FMain函数,该函数功能为释放资源文件,隐藏doc文档文件,创建进程打开doc文件迷惑使用者看起来为普通的打开文档,放松警惕。

 

 

函数中使用大部分函数都使用的动态加载,GetProcAddress获取函数地址,然后调用函数

 

使用函数查找资源文件

 

讲dll使用工具打开会看到两个资源文件,分别是doc文档数据以及文件名称

 

释放doc资源后将文件设置为隐藏属性,然后打开doc文件。

 

打开doc文档后,程序请求解密字符串网址,请求数据。

 

解密出的网址hxxp://103.85.24.158/hk097.dat

 

解析网址请求文件

 

将请求的数据解密到申请的内存空间,然后更改内存块属性,执行代码

 

由于我再写文章的时候已经申请不到了这块代码数据,所以不能将这段行为记录下来了,好在在这之前,我执行了它,这段代码请求了一组文件,我将他们保存了下来,他同样是一组白加黑劫持病毒,分别为AvastProxy.exe、wsc.dll、main.dat,会将他们创建至C:\ProgramData\AvastProxyQUY位置,并设置该文件夹为隐藏属性。

AvastProxy.exe 白文件

AvastProxy.exe是Avast的杀毒软件下的某个程序,同样是被劫持利用加载病毒dll执行恶意代码。

wcs.dll劫持病毒文件

该文件主要作用是加载同目录下的main.dat数据文件,进行解密申请内存,加载执行。

 

在内存中获取当前目录拼接main.dat,读取文件大小,申请内存,读取文件到内存:

 

读到内存后,执行解密,申请文件大小的内存,动态获取VirtualProtect函数继续修改内存属性位可读可写可执行,然后进行调用执行

 

为了查看解密的是什么数据,使用OD加载AvastProxy.exe 文件(同目录下要有dll和dat文件),在VirtualProtect函数下断,回到用户地址,然后他的下一个call就是调用处。这里就是main.dat揭秘出来的数据代码。

main.dat数据文件

接下来跳转到的call的位置,就是main.dat解密后的数据,发现代码是4D5A,这应该就是PE文件的头部结构,由于4D5A代表的汇编指令经过下面构造,是仍然可以执行的,这也就是为什么当OEP为0时,程序运行是可行的。

 

汇编4D5A下方call ebx,跳转过去是4631d0位置。

 

将这段内存dump下来,使用IDA打开, rebase program选项将加载基址对其,发现call ebx的地址是导出函数ApzwTrKM

导出函数ApzwTrKM

这个导入函数实现了DLL反射注入,没有用系统的loadlibrary加载,而是自身解析结构将自己加载起来。

 

获取当前位置,循环向上查找4D5A标志确定位置,通过PE结构获取一些信息标志信息。

 

通过FS[30]结构查找当前进程加载模块:

 

将加载的模块名称简单计算一个类hash值,这个值会跟预先保留好的值进行比较,来获取想要的模块

 

这里预先保留了两个想要的模块名称hash值:

1
2
cmp     [ebp+name_hash], 6A4ABC5Bh ; 6A4ABC5B = Kernel32
cmp     [ebp+name_hash], 3CFA685Dh ; 3CFA685D = ntdll

通过解析模块PE结构找到导出表,同样通过计算hash得方式查找想要的函数

 

要找的函数为

1
2
3
4
5
cmp     [ebp+var_30], 534C0AB8h ;     534C0AB8 = NtFlushInstructionCache
cmp     [ebp+var_30], EC0E4E8Eh ;     EC0E4E8E = LoadLibraryA
cmp     [ebp+var_30], 7C0DFCAAh ;     7C0DFCAA = GetProcAddress
cmp     [ebp+var_30], 91AFCA54h ;     91AFCA54 = VirtualAlloc
cmp     [ebp+var_30], 7946C61Bh ;     7946C61B = VirtualProtect

然后获取函数的地址并调用,申请内存,大小是PE的imagebase字段 + 3C0000大小,为后面加载自身做准备,然后获取各个区段和PE结构信息进行装在自身。

 

加载完毕后开始填充IAT表:

 

修复重定位:

 

自实现加载后,修改代码段属性,然后跳转到dllmain进行执行

 

导出函数实现了自身加载自身,完成了系统函数Loadlibrary函数功能,然后跳转到DLLmain执行代码

dllmain主函数

主函数主要功能是创建一个远程连接,管道创建CMD进程实现shell控制,获取计算机一些信息,接受请求的到的的操作码实现各种功能,是一个远控类型的病毒。(样本大部分调用函数都采用了loadlibrary+getprocaddress获取函数地址调用,以及获取函数指针数组调用,所以我们尽量把看到的函数都命名好,方便阅读)

 

找到主函数,会判断参数数量,没有参数创建启动项、将自身和必要文件拷贝到指定目录,随然后随机参数启动自身并退出。

 

当有参数时,会判断一些进程是否存在,并杀死进程、删除文件机注册表,这里使用了改变特权,提高权限,这个病毒使用了两种:

SeDebugPrivilege

描述:通过任意账户请求调试和调整某个进程拥有的内存
攻击情景:特权提升;防护逃逸;凭据窃取

SeTcbPrivilege

描述:表示它的持有者是可信计算机的一部分。一些信任受保护的子系统被授予此特权。
攻击情景:特权提升

 

如果你想了解更多关于特权方面的知识,推荐阅读这个文章,上面记录了一些有用的特权知识

 

https://github.com/hatRiot/token-priv/blob/master/abusing_token_eop_1.0.txt

 

 

紧接会创建cmd shell控制线程,创建消息循环等等,这个线程是实现远控的主要函数:

 

线程中还会创建线程一个thread_Request_file线程,线程功能是请求数据

 

接受请求get_copmputer_info来获取计算机信息、计算机名称、用户名和曾、系统32/64为位等等。

 

使用管道绑定创建CMD进程,达到shell管理的目的,管道pipe 用于进程间通讯的一段共享内存。创建管道的进程称为服务器,连接到一个管道的进为管道客户机。

 

控制功能有遍历磁盘文件、操作文件、创建目录、创建进程等等:

 

样本的主要功能分析完了,样本可以通过发送请求获取目标信息,执行任意下发的文件。
样本使用了白加黑动态库劫持,dll反射内存加载,简单混淆函数等来躲避查杀。

 

样本已上传密码: infected

sha1

21980f1be5e60fd28e340fec103949d28453a3d4 AvastProxyQUY\AvastProxy.exe
1f0a08cd1c4b6558557ad31337f78153e4b55e0e AvastProxyQUY\wsc.dll
d736f06c8eaef035291db050b356ab38a49f0379 wwlib.dll
70c973c87f3c683b4239c0c38ee426ade5a7ac6f AvastProxyQUY\main.dat
534a7ea9c67bab3e8f2d41977bf43d41dfe951cf Catholic Bishops call for urgent Cameroon peace talks.exe


[看雪官方]《安卓高级研修班》线下班,网课(12月)班开始同步招生!!

最后于 2020-9-19 16:39 被Cc28256编辑 ,原因:
上传的附件:
收藏
点赞7
打赏
分享
最新回复 (8)
雪    币: 5
活跃值: 活跃值 (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
豪杰春香 活跃值 2020-9-19 20:59
2
0
谢谢分享
雪    币: 136
活跃值: 活跃值 (156)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 活跃值 2020-9-21 10:18
3
0
感谢分享
雪    币: 199
活跃值: 活跃值 (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Jvali 活跃值 2020-9-23 16:04
4
0
感谢分享
雪    币: 92
活跃值: 活跃值 (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
薛定谔消失的弦 活跃值 2020-9-24 17:53
5
0
蟹蟹分享
雪    币: 419
活跃值: 活跃值 (109)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
GhostValley 活跃值 2020-9-25 14:29
6
0
最后main.dat解密后的东西、应该是这么写出来的(YY):
1、正常写好一个DLL
2、在DLL末尾插入一段ShellCode、也就是上面的ApzwTrKM、同时记录下距离文件起始位置的偏移
3、16进制编辑器、修改NT头里没用的信息;其实4D 5A这两个字节码不是作者的本意、所以在调用这段ShellCode前要把4D 5A的操作给抵消掉。最后根据刚才的偏移量、减去这部分为了抵消的Opcode数、最终硬编码一个长度、Call到最后的这段ShellCode;
雪    币: 419
活跃值: 活跃值 (109)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
GhostValley 活跃值 2020-9-25 14:35
7
1
另外、我觉着"OEP是0,程序也是能运行"的说法、并不准确,YY:
原文里"读到内存后,执行解密,申请文件大小的内存,动态获取VirtualProtect函数继续修改内存属性位可读可写可执行"、其实文件读取到内存、又修改了内存页属性、更应该去把这部分当作二进制数据块、而抛开任何的数据结构(在这里就是PE结构)。所以、这个时候,看待这个数据块、不应该是再把OEP给弄到一起了。
最后的这个DLL的OEP、不需要去做什么改动。
雪    币: 4780
活跃值: 活跃值 (2033)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
Cc28256 活跃值 3 2020-9-26 09:48
8
1
GhostValley 另外、我觉着"OEP是0,程序也是能运行"的说法、并不准确,YY: 原文里"读到内存后,执行解密,申请文件大小的内存,动态获取VirtualProtect函数继续修改内 ...
确实他的OEP解密出来的不是0,我这里说的是OEP可以为0是因为4D 5A汇编经过构造能够跳转到正确的OEP的,这里只是说了一下OEP为什么可以为0,没有指该样本:D ,你的想法是对的,就是二进制数据块
雪    币: 419
活跃值: 活跃值 (109)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
GhostValley 活跃值 2020-9-27 15:45
9
0
Cc28256 确实他的OEP解密出来的不是0,我这里说的是OEP可以为0是因为4D 5A汇编经过构造能够跳转到正确的OEP的,这里只是说了一下OEP为什么可以为0,没有指该样本:D ,你的想法是对的,就是二进制数据 ...
“这里只是说了一下OEP为什么可以为0,没有指该样本” ---YY:
OEP所在的内存页应该有可执行权限、OEP可以位于.text段的开始。
可以把.text里的PointerToRawData指向开头、也许是这个意思吧。
游客
登录 | 注册 方可回帖
返回