吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 294|回复: 1
上一主题 下一主题
收起左侧

[PC样本分析] 一次银狐样本分析

[复制链接]
跳转到指定楼层
楼主
soma20 发表于 2026-5-5 16:17 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 soma20 于 2026-5-5 16:22 编辑

0x00 前言

最近突然心血来潮,想找个样本来分析一下,顺便学习了解一下免杀以及恶意样本的手法,在网上冲浪的时候找到了一个银狐样本,于是拿来分析一下

样本地址:WindowsEvent 病毒木马程序 - 吾爱破解 - 52pojie.cn

0x01 沙箱分析

将整个文件打包压缩,丢到沙箱看看情况

这里看一下沙箱跑出来的执行流程:

可以看到通过这个WindowsEvent.exe创建了命令行任务管理工具,然后外连下载。还有释放文件。

0x02 样本分析

一、WindowsEvent.exe

首先die查查成分:

目测就是使用汇编写的,然后没有导入表,那么可能通过PEB来获取外部函数地址了。废话不多说就直接进入分析。由于是汇编写的,这个入口非常的简单,大概就是下面这样:

init初始化

首先通过init函数来进行初始化

通过decrypt_str函数来进行字符串解密,然后通过自定义的GetDllBase函数获取Kernel32.dll 的基址。然后通过自定义给GetProcAddress函数获取必要的API地址存放到全局变量当中。

decrypt_str

这里来看看这个decrypt_str:

可以看到就是一个简单的异或解密,然后addr第一个元素是字符串的长度,这里直接写一个IDAPython脚本,然后解密一下:

def decrypt(addr):
    len = ida_bytes.get_byte(addr)
    plain = []
    for i in range(0, len, 1):
        cipher = ida_bytes.get_byte(addr + i + 1)
        plain.append(chr(cipher ^ 0x6A))

    print(f"str[{len}] -> {''.join(plain)}")

print("============================")
decrypt(0x4009E0)
decrypt(0x4009ED+1)
decrypt(0x4009FB)
decrypt(0x400A08)
decrypt(0x400A15)
decrypt(0x400A23)
decrypt(0x400A30)
decrypt(0x400A3A)
decrypt(0x400A5E)
print("============================")

解密之后的API信息如下:

===========================
str[12] -> kernel32.dll
str[11] -> CreateFileA
str[11] -> CloseHandle
str[11] -> GetFileSize
str[12] -> VirtualAlloc
str[11] -> VirtualFree
str[8] -> ReadFile
str[14] -> VirtualProtect
str[14] -> CreateProcessA
============================
GetDllBase

通过GetDllBase这个函数来获取制定dll名的基址


这里通过PEB来获取InMemoryOrderModuleList,再通过遍历这个双向链表,然后比较BaseDllName来找到指定的dll,从而获取指定dll的基址。

GetProcAddress

GetProcAddress就是通过自解析PE结构的导出表,来获取到指定API的外部地址。

check_fileName

初始化完成之后会调用check_fileName来检查当前执行的这个文件的文件名是否有被修改:

这个函数比较字符的时候,会将获取到的字符转成大写,然后再进行比较。通过分析可以发现,仅仅只是对进程名当中的indo片进行了校验,只有在这个校验通过的时候才会返回1,否则返回0。然后进程退出

函数功能

这里检查进程名可能是为了绕过分析。有些沙箱或者虚拟分析环境在运行样本时,进程名可能是随机生成的,或者带有特定字样。这里可能是在检测这些环境,并且进行绕过。

start_WinSafe

这个函数会尝试使用schtasks这个计划任务管理器来立即执行这个WinSafe的任务。不过本机上没有这个计划任务。可能是后续恶意代码执行之后才添加的,这里还不太清楚。

execShellCode

恶意程序通过这个函数来解密ShellCode并执行。

由于之前根据解密之后的字符串修复了一下全局变量的名称,这里看就非常的简单了。可以大体流程先是使用VirtualAlloc申请一个内存空间,然后将byte_400AA0这个位置的数据移动到申请的内存空间当中。接着就是对ShellCode当中的数据进行解密,解密算法就是有限域下先 (x + 119) ^ 0x62,最后在使用VirtualProtect修改内存权限,然后直接使用函数指针执行。

这里要注意一下,VirtualAllocVirtualProtect这两个函数的参数,通过参数可以分析在VirtualAllocVirtualProtect执行的过程中,申请的权限分别是可读可写可读可执行,而不是可读可写可执行。这样做的目的是绕过大部分杀软的检测。毕竟直接申请RWX内存是非常危险的操作。

通过分析知道了这个ShellCode的解密方法,那么就可以通过动态调试将这段shellCode dump下来分析,或者是直接获取数据然后解密写道文件当中。这里我选择后者,直接写一个IDAPython脚本来解密,然后顺便写到文件当中:

import idc
import idaapi
import ida_fpro
import os

# shellcode
start_addr = 0x400AA0
plain = []
for i in range(0x98B):
    ch = ida_bytes.get_byte(start_addr+i)
    dec = (((ch + 0x77) & 0xff) ^ 0x62) & 0xff
    plain.append(dec)
#print(cipher)
idb_dir = idc.get_idb_path()
dir_path = os.path.dirname(idb_dir)
print(dir_path)

output_path = os.path.join(dir_path, "shellCode.bin")

def save_file(data, filename):
    data_bytes = bytes(data)
    with open(filename,"wb") as f:
        f.write(data_bytes)
    return len(data_bytes)

filelen = save_file(plain, output_path)
print(f"数据已保存到 : {output_path}")
print(f"写入 {filelen} 字节")

分析到这里,看起来这个exe已经没有其他逻辑了。

总结

通过上述的分析,这个WindowsEvent.exe其实就是一个ShellCodeLoader,还需要对其中加载的ShellCode进行分析才行。

二、ShellCode部分

字符串信息

在使用IDAPython将ShellCode解密,并且写入文件之后,先进行一些信息收集。首先用strings看看能不能提取出来一些有用的字符串:

发现有些有趣的字符串,以及IP地址和域名。还有最下面一串看起来像是逆序了的结构化配置信息,这里使用python回复一下:

通过AI分析,这个字符串定义了这个样本的连接命令与控制服务器的全部参数,包含了三组独立的C2地址:

  • 主 C2(p1)156.234.119.138:443t1:1 可能指启用 TLS/SSL 加密)。
  • 备用 C2 1(p2)syumineyt.top:80t2:1 可能指使用 HTTP 明文)。
  • 备用 C2 2(p3)syumingeyt.top:8080t3:1 可能指使用 HTTP 或其他协议)。

IDA分析

接下来将这个ShellCode文件丢到IDA当中进行分析

上来首先就是最常见的使用PEB获取DllBase,这里用来判断是否找到正确字符串的方法是 hash 校验,通过计算字符串的hash值与目标字符串的hash值比较,如果比较成功则表示找到了这个字符串,这个也是shellcode当中常见的混淆。

解决方法:解决这种混淆的方法也比较简单。这里有两种方法:

  1. 首先就是一种比较复杂的方法,可以将hash算法还原一下,然后对一些常见的dll名称进行hash计算,来校验。对于函数名称的话,可以对目标dll文件进行导出表解析,然后对API名称进行hash计算,找出目标hash对应的API名称
  2. 另外一种比较简单的方法就是直接动态调试了,通过动态调试来直接获取到目标API的名称。ShellCode 的动态调试可以自己实现一个Loader来加载这段ShellCode

接着就是通过GetFuncByHash来获取API,

这一部分会逐步获取kernel32.dll 以及 ntdll.dll当中的一些API,具体如下:

GetFuncByHash

这个函数是用来获取外部模块提供的API的,这个函数使用了两种方法来获取API。如果参数2传入的是0,则会自己解析导出表来计算函数地址。而另外一种情况是参数2传入一个函数地址,这个函数就会使用传入的这个函数来获取API地址:

上图的上半部分是解析导出表的代码,这里就不放出来了。
根据上层函数的逻辑得出,在获取了GetProcAddress函数地址之后,后续的都是通过这个GetProcAddress函数来获取函数地址的。只不过在获取之前,还是会解析一遍导出表。

定位资源部分

接下来这个部分,也是笔者第一次了解到,刚看到的时候还有点懵。后来想想是个很不错的设计,这里通过汇编看看逻辑

首先会调用这个gotoNextIns的函数,函数如下,只有短短的两个指令:

将栈顶的值放到eax寄存器当中,此时栈顶是返回地址,也就是这个xor ecx, ecx指令的地址。所以这个函数其实是用了一个非常巧妙的方法,来获取下一条指令的地址。

接着会从这个指令地址遍历内存空间,直到找到一个连续的字符串codemark的位置。这个字符串不正是之前就通过strings找出来的吗?

从IDA当中的这个形式来看的话codemark这个地方以下的就是存放资源的地方,还可以看到ip地址,以及域名字符串。

那么其实这个codemark其实就是一个表示符,用于程序内部定位资源,这样比直接写死地址更加的灵活。

后续部分

在定位资源完成之后,会加载Ws2_32.dll,并且获取这个模块当中的一些API地址,大致如下:

结合这些API名称,根据一些经验分析,这个ShellCode可能也还是一个加载器。而且使用的是分离加载的模式,通过ws2库来下载另外一个ShellCode,然后执行真正的恶意逻辑。

木马下载部分

这个ShellCode使用了两种方式下载ShellCode。一种是原始的TCP协议(offset 0x33A),另一种是使用HTTP协议(offset 0x4DF)。这里使用动态调试跟进一下,看看使用的是哪一个方式。

经过动态调试之后发现使用的原始TCP协议进行下载,这里贴一下在汇编当中打的注释:

最终大概会在这个位置call ShellCode。由于已经连不上c2,无法下载木马,这里就没有没办法验证了。

三、Gurad.dll导出函数分析

既然exe部分已经分析的差不多了,那么这里就来看看这个dll到底干了什么。从导出表入手:

发现导出了一个MonitorAndRestart函数,来看看这个函数:

从这个函数调用API和行为来看,这个函数就是一个典型的持久化 + 守护进程的机制。

单例控制

首先通过创建全局互斥体"Global\\ProcessMonitorDLL_Mutex"来防止重复运行。防止多个监控线程/进程同时存在

监控进程

然后对目标进程进行监控,默认的进程名是WindowsEvent.exe,但是可以通过参数动态传入。

接下来会使用一个while循环来监控和拉起进程。首先通过findTargetProcess函数来检查目标进程是否存在。如果存在了跳转到LABEL_12的地方,休息1秒,然后继续检查。

findTargetProcess函数

这个函数是通过进程快照来检查目标进程是否存在:

如果进程不存在,则使用计划任务管理器来拉起任务:

schtasks /run /tn "WindowsEvent_Task"

启动之后使用WaitForSingleObject来等待5秒,然后获取执行结果。如果执行失败则打印日志,反之再次确认进程是否存在,不存在则记录日志。

如果CreateProcessW执行失败,则会执行:

sub_10001270();

该函数定义如下:

如果CreateProcessW失败,则会调用这个函数,然后提权,并且重启系统。

四、小结

这个样本其实就是个“分工很明确的工具人”。表面上的 WindowsEvent.exe 本身没干啥坏事,就是负责把一段加密的 ShellCode 解出来然后跑起来;真正的活是在后面那段 ShellCode 里,它会自己去系统里找 API、再去外网连服务器,把真正的木马程序下载下来在内存里直接执行(不落地,更隐蔽)。另外还配了一个 Guard.dll 做“保安”,一直盯着这个进程,只要被关掉就用计划任务拉起来,实在拉不起来就直接重启电脑,确保恶意程序还能活着。整体来看就是一个多阶段加载 + 网络下载 + 持久化守护的典型木马框架。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
qte123 发表于 2026-5-6 01:31
感谢分享,学习一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-6 02:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表