最近突然心血来潮,想找个样本来分析一下,顺便学习了解一下免杀以及恶意样本的手法,在网上冲浪的时候找到了一个银狐样本,于是拿来分析一下
样本地址:WindowsEvent 病毒木马程序 - 吾爱破解 - 52pojie.cn
样本sha256:1443f7eb60ceebe8752cbfd4029023d8da975d087556af8247011ddd7bf2336f
将整个文件打包压缩,丢到沙箱看看情况 
这里看一下沙箱跑出来的执行流程: 
可以看到通过这个WindowsEvent.exe创建了命令行任务管理工具,然后外连下载。还有释放文件。
首先die查查成分: 
目测就是使用汇编写的,然后没有导入表,那么可能通过PEB来获取外部函数地址了。废话不多说就直接进入分析。由于是汇编写的,这个入口非常的简单,大概就是下面这样: 
首先通过init函数来进行初始化 
通过decrypt_str函数来进行字符串解密,然后通过自定义的GetDllBase函数获取Kernel32.dll 的基址。然后通过自定义给GetProcAddress函数获取必要的API地址存放到全局变量当中。
这里来看看这个decrypt_str: 
可以看到就是一个简单的异或解密,然后addr第一个元素是字符串的长度,这里直接写一个IDAPython脚本,然后解密一下:
解密之后的API信息如下:
通过GetDllBase这个函数来获取制定dll名的基址 
这里通过PEB来获取InMemoryOrderModuleList,再通过遍历这个双向链表,然后比较BaseDllName来找到指定的dll,从而获取指定dll的基址。
GetProcAddress就是通过自解析PE结构的导出表,来获取到指定API的外部地址。 
初始化完成之后会调用check_fileName来检查当前执行的这个文件的文件名是否有被修改: 
这个函数比较字符的时候,会将获取到的字符转成大写,然后再进行比较。通过分析可以发现,仅仅只是对进程名当中的indo片进行了校验,只有在这个校验通过的时候才会返回1,否则返回0。然后进程退出
这里检查进程名可能是为了绕过分析。有些沙箱或者虚拟分析环境在运行样本时,进程名可能是随机生成的,或者带有特定字样。这里可能是在检测这些环境,并且进行绕过。
这个函数会尝试使用schtasks这个计划任务管理器来立即执行这个WinSafe的任务。不过本机上没有这个计划任务。可能是后续恶意代码执行之后才添加的,这里还不太清楚。 
恶意程序通过这个函数来解密ShellCode并执行。 
由于之前根据解密之后的字符串修复了一下全局变量的名称,这里看就非常的简单了。可以大体流程先是使用VirtualAlloc申请一个内存空间,然后将byte_400AA0这个位置的数据移动到申请的内存空间当中。接着就是对ShellCode当中的数据进行解密,解密算法就是有限域下先 (x + 119) ^ 0x62,最后在使用VirtualProtect修改内存权限,然后直接使用函数指针执行。
这里要注意一下,VirtualAlloc和VirtualProtect这两个函数的参数,通过参数可以分析在VirtualAlloc和VirtualProtect执行的过程中,申请的权限分别是可读可写和可读可执行,而不是可读可写可执行。这样做的目的是绕过大部分杀软的检测。毕竟直接申请RWX内存是非常危险的操作。
通过分析知道了这个ShellCode的解密方法,那么就可以通过动态调试将这段shellCode dump下来分析,或者是直接获取数据然后解密写道文件当中。这里我选择后者,直接写一个IDAPython脚本来解密,然后顺便写到文件当中:
分析到这里,看起来这个exe已经没有其他逻辑了。
通过上述的分析,这个WindowsEvent.exe其实就是一个ShellCodeLoader,还需要对其中加载的ShellCode进行分析才行。
在使用IDAPython将ShellCode解密,并且写入文件之后,先进行一些信息收集。首先用strings看看能不能提取出来一些有用的字符串: 
发现有些有趣的字符串,以及IP地址和域名。还有最下面一串看起来像是逆序了的结构化配置信息,这里使用python回复一下: 
通过AI分析,这个字符串定义了这个样本的连接命令与控制服务器的全部参数,包含了三组独立的C2地址:
接下来将这个ShellCode文件丢到IDA当中进行分析 

上来首先就是最常见的使用PEB获取DllBase,这里用来判断是否找到正确字符串的方法是 hash 校验,通过计算字符串的hash值与目标字符串的hash值比较,如果比较成功则表示找到了这个字符串,这个也是shellcode当中常见的混淆。
解决方法:解决这种混淆的方法也比较简单。这里有两种方法:
接着就是通过GetFuncByHash来获取API, 
这一部分会逐步获取kernel32.dll 以及 ntdll.dll当中的一些API,具体如下: 
这个函数是用来获取外部模块提供的API的,这个函数使用了两种方法来获取API。如果参数2传入的是0,则会自己解析导出表来计算函数地址。而另外一种情况是参数2传入一个函数地址,这个函数就会使用传入的这个函数来获取API地址: 
上图的上半部分是解析导出表的代码,这里就不放出来了。根据上层函数的逻辑得出,在获取了GetProcAddress函数地址之后,后续的都是通过这个GetProcAddress函数来获取函数地址的。只不过在获取之前,还是会解析一遍导出表。
接下来这个部分,也是笔者第一次了解到,刚看到的时候还有点懵。后来想想是个很不错的设计,这里通过汇编看看逻辑 
首先会调用这个gotoNextIns的函数,函数如下,只有短短的两个指令: 
将栈顶的值放到eax寄存器当中,此时栈顶是返回地址,也就是这个xor ecx, ecx指令的地址。所以这个函数其实是用了一个非常巧妙的方法,来获取下一条指令的地址。
[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
最后于 1天前
被x0rrrrr编辑
,原因: