一. 整体介绍
1. 加载执行
通过白加黑使用合法软件加载恶意dll
利用回调机制加载Shellcode
使用VirtualAllocExNuma分配内存空间;
使用VirtualProtect修改内存保护为PAGE_EXECUTE_READWRITE;
将Shellcode地址作为EnumCalendarInfoA的第一个参数传入(该参数本应是一个回调函数地址)
因为是回调函数,所以在执行完这个EnumCalendarInfoA之后就会去执行这个参数对应的函数
2. 持久化
(貌似没有)
3. 防御规避
通过PEB获得kernel32.dll的基地址
基于PEB获得kernel32基地址
通过API哈希匹配技术从而判断对应的函数
API哈希匹配技术
shellcode加密为ipv4地址
4. 功能实现
通过加载dll实现相应的功能
二. 具体实现
1. 加载执行
压缩包当中存在多个软件和一些dll文件,通过火绒剑进行检测发现没有找到问题,怀疑是存在一个沙箱检测功能,存在沙箱就直接关闭了。暂时没有找到什么好的方法可以直接定位到恶意程序所处的位置,所以就先按照文章当中的说法,针对dll文件进行分析。
这里的方式是采取白加黑,exe程序是一个正常的程序,应该是Wondershare软件,这个软件的hash和在官网上下载的软件的hash是一致的,说明程序本身是没有问题的。那么问题应该就是出在了dll文件当中,在压缩包当中存在多个dll文件,查看程序的导入表,发现只有一个压缩包当中的dll文件出现了,就是drstat.dll。那么应该就可以确定,在程序运行的时候通过篡改了dll的加载顺序,导致程序加载了恶意dll文件从而实现木马的功能。
使用IDA载入dll程序,分析其导出表,发现其中的函数除了dr_data_stop函数之外,其余全部都是空壳,没有实现相关功能。现在分析的关键就是dr_data_stop函数。这里需要动静结合进行分析,静态分析可以直接使用IDA载入dll文件进行分析,动态分析则是需要通过xdbg进行分析。在符号当中的dll文件当中选择相关的导出函数下断点。
dll文件首先是调用了GetTickCount函数、Sleep函数和BeeP函数,在文章当中说这几个函数可以实现反沙箱检测,但是我在代码逻辑当中没有看到程序在检测到异常之后拒绝执行的代码,感觉还是存在一些问题。哪怕存在沙箱检测,然后确实没有做到相关函数的功能,但是程序的逻辑还是正常执行的,感觉就是一个最基础的延时来规避沙箱检测,但是这个GetTickCount函数和BeeP函数都没什么作用了。
2. 持久化
无
3. 防御规避
后面的思路就很比较简单了,采用了很常规的LoadLibrary、GetPorcAddress函数等进行相关函数的载入,但是有一点很厉害的就是为了规避检测,程序是将函数名等字符串信息存储在栈当中,通过16进制信息进行复制,看汇编代码什么都看不出来,但是IDA在反编译的时候将其全部编译了出来,逆向分析的时候大大降低了难度。
加载的函数包括:VirtualAllocExNuma(开辟虚拟空间)、VirtualProtect(修改保护属性)、EnumCalendarInfoA(枚举日历信息)、HeapAlloc(堆空间开辟)、SystemFunction036(
RtlGenRandom
函数的导出名,Windows 的加密安全随机数生成器)、RtlIpv4StringToAddressA(IPv4字符串转二进制数据)。
但是还有关键的一个信息就是shellcode并不是以明码的形式直接存储在程序当中,而是经过了加密存储在程序当中,首先需要采取解密得到真正的shellcode。在程序当中存在大量的IPV4地址的字符串信息,通过一个循环进行解码然后再解密,最终的结果为shellcode。
在实现了相关的shellcode解码之后接下来就要进行解密操作,这个是通过一个异或实现的,直接将字符串信息和0x6f进行异或,得到最终的shellcode。
但是发现shellcode存储的位置和我们实际开辟的空间不是同一个位置,因为shellcode是通过heapalloc开辟的空间存储的,后续通过一个字符串的拷贝实现了将数据拷贝到实际可执行的地址当中。并且这个拷贝的位置不是咱们开辟空间的起始地址,而是通过随机函数产生了一个随机数,拷贝到基地址加上随机数的位置。
最后通过使用EnumCalendarInfoA函数来注册回调函数实现了最终的功能,然后回调函数地址就是shellcode地址,通过这种方法实现防止api检测。
接下来我们就要分析这个回调函数什么时候会被调用:遍历指定区域下的所有日历,然后将第一个月份作为参数传递到注册的回调函数当中,作为参数进行回调函数的调用。
EnumCalendarInfoA(
0x18a00, // lpCalInfoEnumProc (回调函数指针)
0x800i64, // Locale (区域设置标识符)
0xFFFFFFFFi64, // Calendar (日历标识符)
1i64 // CalType (信息类型)
);
日历类型遍历
枚举所有可用日历系统(如公历GREGORIAN、回历ISLAMIC等)
针对每种日历执行后续操作
月份信息收集
只收集每年第一个月份的名称(相当于英语"January")
对于公历系统固定返回"January",其他日历系统返回其首月名称
回调函数触发
每个有效的(日历系统,月份名称)组合都会触发回调
调用模式:
0x18a00("January", CALID)
在得到shellcode之后我们需要分析shellcode的功能,但是前提是掌握其如何载入函数以及载入函数的作用,将shellcode复制出来保存到文件当中,然后使用ida将文件载入,用c转化为代码,然后再用p转化为函数,这样就可以正常分析了。
但是这个时候直接看IDA反编译的代码其实还是很奇怪,根本看不到到底实现了什么功能,最好的方法就是再跟踪调试一下。
三. 正向开发
基于回调函数的shellcode执行
API哈希匹配技术
基于PEB获得kernel32基地址
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf
客服小蜜蜂(微信:freebee1024)