负载恶意软件HawkEye的VB Inject样本分析

0x01 概述

恶意软件HawkEye的利用大多都是通过钓鱼邮件分发,利用office直接启动HawkEye主体或者一些经过加密的程序,本文中的VB Inject属于后者,也把重心放在了调试这个VB程序上。

文件基本信息如下:

VirusTotal上的该样本信息:

病毒名大多为VBKrypt或者VBInject。

0x02 行为监控

将自身复制到C:\User\user\AppData\Romaing\WindowsUpdate.exe,创建C:\User\user\AppData\Romaing\pid.txt,C:\User\user\AppData\Romaing\pidloc.txt,并将WindowsUpdate.exe加入自启动项。

用wireshark抓网络行为,发现该样本会访问http://whatismyipaddress.com/,并与yandex邮件服务器建立连接。

0x03 反调试

因为是个VB程序,首先就想到用VB decompile反编译。效果如下:

似乎是没不能看出什么,于是来调试一下。

步过这个call之后,会跳转到一个错误指令:

想到可能是因为反调试导致的,所以步入0x4012A1的call,然而里面的代码都是模块msvbvm60的,一个比较快能定位到主程序的办法就是通过VB decompile中显示的地址。于是我在0x4A07D6、0x4A0BC8下断。FormLoad中没有什么有用的信息,直接断到FormPaint。

这里做了一些字符串的操作,直接自动步过,然后来到下面这个call:

回车进去看到有调用DllFunctionCall,这里会调用RtlMoveMemory很多次,复制一段内存:

在循环结束的地方F4:

单步之后发现程序会在下图位置运行起来,进入错误指令:

跟进后,又来到下面的call(因为其他的call都有函数名__vbaxxx),回车进入后发现这个call也调用了DllFuncitonCall:

调用了EnumWindows,这个函数一个参数是回调函数,所以需要留意。

函数原型:

BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam );

lpEnumFunc是指向回调函数的指针,lParam是传递给回调函数的参数。

看此时栈的状态,第一个参数位于0x12F4D8,在该处下断。

然后F8->执行到用户代码,断到该处::

单步到后面的jmp之后跳到下面的地址:

这里call edx之后,跳到错误地址,该地址正确编码后的指令是:

地址为0x48EA92,但程序却跳到了0x48EA93:

注意到在call之前的一条adc指令,程序在这里加了1,导致跳转到0x48EA93,反反调试的话做到这里把这条指令nop掉就可以了,不过可以看看[ebx+2]的值是怎么决定的。

返回去看到这里,就知道为什么了。

fs:esi指向自身(TEB结构),偏移为3的地址处是BeingDebugged, 0x01是被调试中:

nop掉保存再调试。

0x04 运行时解密

从过了反调试的地址0x48EA92开始:

干扰指令很多,还有一部分硬编码。一直单步,遇到call都最好跟进,这段代码中的call不多:

调用DllFunctionCall得到EnumWindows的地址:

这里可以直接步过:

然后出现VirtualAlloc,然后同样DllFunctionCall得到VirtualAlloc地址,然后调用。

分配了内存1,推断是要解密自身代码写入到地址:

开始往这片内存写入内容,然后跳转到这个地址:

单步到下图,又有一个反调试,同样是通过TEB读取PEB BeingDebugged的值:

又调用一次VirtualAlloc分配内存2:

跟到下面又发现对PEB结构的访问,偏移为0x68。

其实不太清楚偏移0x68是什么,就查了一下:

PEB有一个名为NtGlobalFlag(偏移量为0x68)的字段,程序可以挑战识别它们是否正在被调试。通常,当未调试进程时,NtGlobalFlag字段包含值0x0。在调试进程时,该字段通常包含值0x70。

此时这个值正好为0x70,所以这个je不能跳。

继续单步跟,会调用很多次DllFuncitonCall,可以看到获取了许多API的地址,如ShellExecuteW,WriteFile,CreateFile,VirtualProtect,CreateProcess等。

接下来又分配了内存3,地址为:

来看看分配的这三块内存的状态:

目前除了刚分配那个不能执行,其他的都可读可写可执行:

往内存0x3430000赋值:

开始解码:

解码完成后,有点PE头的样子了,只是少了标志性的”MZ”:

调用GetCommandLineW,以获取的路径为参数创建子进程:

调用ZwAllocateVirtualMemory在指定进程分配内存:

将0x5A赋值给0x343600不完整的PE文件,后面还会写入’M’。

然后调用ZwWriteVirtualMemory写入内存空间,写入的内容地址正是0x343600。

父进程将解密出来要执行的PE写入子进程的内存,然后中止当前进程。

0x05 样本主体

在之前的行为监控中,注意到,样本在C:\User\user\AppData\Romaing\目录下生成了三个文件 pid.txt,pidloc.txt,WindowsUpdate.exe。这些功能都是通过解密出来的PE实现的。样本的VB代码只相当于一个外壳,运行时解密、创建子进程、注入进程等。提取出来的这个PE载入ExeinfoPE,发现这个程序是.NET Reactor类型的代码混淆。

这里我用了de4dot-mod反混淆工具,不用工具直接动态调试也可以。

去除反混淆后生成的文件变成了528KB,原文件大小为65512KB,用PEID打开,可以看到导入表只有一个动态链接库mscoree.dll,函数是_CoreExeMain。

接下来尝试用.NET的反编译工具dnSpy试试。

反编译成功后,发现该程序是恶意软件HawkEye,用于凭据窃取,包括电子邮件Web浏览器,Bitcoin钱包,反病毒检查,键盘记录等。

*本文原创作者:Macc,本文属于FreeBuf原创奖励计划,未经允许禁止转载

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2018-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云霄雨霁

概念题知识点总结

1990
来自专栏信安之路

使用 Wave 文件绕过 CSP 策略

CSP 全称 Content Security Policy,即内容安全策略。CSP 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括 XSS 和注入...

1220
来自专栏云计算教程系列

如何在Ubuntu 14.04上使用wrk对HTTP延迟进行基准测试

本文重点介绍称为开源HTTP基准测试工具WRK,它可以在高负荷下测量HTTP服务的延迟。

4550
来自专栏JavaEdge

漫谈缓存更新之道

许多人在更新缓存时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载入缓存中。

2302
来自专栏逸鹏说道

【推荐】C#线程篇---你所不知道的线程池(4)

线程的创建和销毁都要耗费大量的时间,有什么更好的办法?用线程池! 太多的线程浪费内存资源,有什么更好的办法?用线程池! 太多线程有损性能,有什么更好的办法?用线...

3758
来自专栏漫漫前端路

写个 vue-loading-template 组件

源码(star ? start : start):github.com/jkchao/vue-…

4312
来自专栏前端儿

【转】http-equiv="X-UA-Compatible" 设置IE浏览器兼容模式详解

文件兼容性用于定义让IE如何编译你的网页。此文件解释文件兼容性,如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式。

3211
来自专栏owent

libatbus的几个藏得很深的bug

在写这篇文章前,我突然想到以前流行了一段时间的服务器面试题:当一个BUG只有几百万分之一的概率会出现,怎么办?这个问题在这个BUG里只是毛毛雨而已,因为这次的B...

883
来自专栏腾讯云安全的专栏

[经验分享]——XSS 入门介绍

2423
来自专栏JavaEdge

压测软件Jmeter使用实例(WIN7环境)百科我们为什么使用JmeterJmeter安装配置Sampler监听器(Listener)点击启动按钮,开启测试Jmeter自定义变量Redis的压测

3655

扫码关注云+社区

领取腾讯云代金券