总字符数: 32.14K
代码: 29.49K, 文本: 2.64K
预计阅读时间: 1.07 小时
获取沙箱环境
检查CPU是否支持虚拟化
1 | def check_cpu_virtualization(): |
获取系统语言
1 | def check_language(): |
获取进程信息
1 | def get_process_count(): |
获取CPU信息
1 | def get_cpu_info(): |
获取开机时间
1 | def check_start_time(): |
获取虚拟环境DLLS
1 | def check_sandbox_dlls(): |
获取当前用户
1 | def get_user(): |
获取硬盘信息
1 | def get_disk_info(): |
获取MAC信息
1 | def get_all_mac_addresses(): |
获取USB设备
1 | def get_usb_devices(): |
获取历史文件
1 | def get_recent_files(): |
Systeminfo
1 | def get_system_info(): |
获取已安装软件
1 | def get_installed_software(): |
上传
1 | def upload_file(url, cookie, info): |
Main
1 | def main(): |
反调试
反虚拟化是指检测恶意软件是否运行在虚拟机/沙盒上而不是物理机器上,这可以通过多种方式完成:
检查屏幕分辨率:如果你在一个自动沙盒上,一些简单的指标,如屏幕分辨率可能会让你放弃。
检查I/O设备(鼠标,键盘等):自动沙盒不会有I/O设备,因为它们不用于日常机器或虚拟机,它们仅用于分析恶意软件。
检查正在运行的进程或系统上的文件:简单地枚举机器上当前正在运行的进程将给你提示,如果它是一个只运行默认进程的沙箱,或者是一个具有许多基本使用应用程序的实际机器。
使用
GetTickCount()
用于确定PE是否正在调试,通过确定运行二进制文件所需的时间并在执行过程中重新检查它.您可以查看是否有断点延迟执行:添加两个任意
GetTickCount()函数,存储T并硬编码.
- T是您的程序从第一个函数调用到第二个函数调用的时间,假设为50秒。然后,您可以在目标机器上执行恶意软件时添加检查,如果T超过50秒,这意味着有人可能正在调试您的exe。(您可能会为不同处理器之间的性能差异添加误差幅度)
Cpuid
__Cpuid():这是一个函数,如果检测到Hypervisor供应商,它将为我们提供有关Hypervisor供应商的信息
1 |
|
参数1是一个整型数组,通常有四个元素,用于存储从EAX、EBX、ECX和EDX寄存器返回的值。
参数2是一个整数,用于指定要查询的 CPUID 信息的功能参数(即功能号)
- 0: 返回最大支持的功能号,以及厂商ID字符串。
- 1: 返回处理器的版本信息、特征标志等。
1 | BOOL CheckCpuid1() { |
如果我们将leef从0x1更改为0x40000000,我们将获得供应商信息。
1 | void CheckCpuid2() { |
最终函数
1 |
|
注册表
HyperV :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters
在hostname和Physical Hostname中,您可以找到物理主机名和主机的域名。
VirtualBox:对于
VirtualBox,只有在使用
VirtualBox的客户机上才能找到注册表项
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\VBOX__
VMware:HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware Tools
1 |
|
RegOpenKeyExA:
RegOpenKeyExA是 Windows API 中的一个函数,用于打开一个注册表项并获得一个句柄,打开的注册表项可以用来查询或设置值。HKEY hKey: 要打开的注册表项的根键。
LPCSTR lpSubKey: 要打开的子项的名称。
DWORD ulOptions: 保留,通常为 0。
REGSAM samDesired: 指定所需的访问权限。
PHKEY phkResult: 指向接收打开的注册表项句柄的变量的指针。
RegCloseKey:
RegCloseKey用于关闭打开的注册表项句柄。HKEY hKey: 要关闭的注册表项的句柄。
RegQueryValueExA:
RegQueryValueExA用于检索指定注册表项中的某个值。HKEY hKey: 包含要检索的值的注册表项的句柄。
LPCSTR lpValueName: 要检索的值的名称。
LPDWORD lpReserved: 保留,必须为 NULL。
LPDWORD lpType: 指向接收值类型的变量的指针。
LPBYTE lpData: 指向接收数据的缓冲区的指针。
LPDWORD lpcbData: 指向接收数据大小的变量的指针。
RegGetValueA:
RegGetValueA从注册表中检索值。与RegQueryValueExA不同,它可以获取嵌套的子项值。HKEY hKey: 包含要检索值的注册表项的句柄。
LPCSTR lpSubKey: 要打开的子项的名称。
LPCSTR lpValue: 要检索的值的名称。
DWORD dwFlags: 指定如何检索信息。
LPDWORD pdwType: 指向接收值类型的变量的指针。
PVOID pvData: 指向接收数据的缓冲区的指针。
LPDWORD pcbData: 指向接收数据大小的变量的指针。
反调试
反调试是阻止恶意软件分析师调试/逆向我们的恶意软件的行为.
反调试技术,即BeingDebugged,但在讨论这个技术之前,需要先了解一下PEB(Process Environment Block:进程环境块).
PEB(Process Environment Block):
PEB是Windows操作系统中的一个数据结构,用于存储关于当前进程状态和环境的信息。每个进程在其自身的地址空间中有一个PEB
PEB包含的信息包括:
- 进程加载的模块(DLL)
- 进程参数(例如命令行参数)
- 环境变量
- 进程的运行时数据
- 以及其他关于进程的元数据
1 | typedef struct _PEB { |
BeingDebugged
1 |
|
DebugBreak
DebugBreak():debugbreak是我们的第二个反调试技术,其中DebugBreak()函数会导致在当前进程中引发断点异常。这允许调用线程用信号通知调试器处理异常。因此,我们依赖于GetExceptionCode()函数的返回,它将告诉我们异常是否由调试器处理.
1 |
|
ContextLogRegisters
1 |
|
终止分析工具
1 |
|
常规手段
检查语言
1 |
|
检查用户名
1 |
|
检查开机时间
1 |
|
检查MAC地址
1 |
|
检查进程
1 |
|
检查CPU
可以使用GetSystemInfo进行CPU 检查。此函数返回⼀个SYSTEM_INFO结构,其中包含有关系统的信息,包括处理器数量.
1 |
|
检查RAM
1 |
|
检查USB
1 |
|
检查文件名
沙箱通常会将文件重命名为⼀种分类方法(例如,将其重命名为其 MD5 哈希)。此过程通常会导致一个包含字母和数字混合的任意文件名.
如果文件名中包含的数字超过 3 个,则ExeDigitsInNameCheck将假定它位于沙箱中并返回 TRUE
1 |
|
检查DLLS
1 |
|
检查域环境
由于我们通常针对企业环境,因此可以假设用户的计算机是域的成员。让我们检查机器的域加入状态:
1 |
|
检查屏幕分辨率
虚拟化环境很少使用多个监视器(尤其是沙箱)。虚拟显示器也可能具有非典型的屏幕尺寸(特别是当安装到主机屏幕但不是全屏模式时-请注意带有栏和选项卡的管理程序窗口)。
1 |
|