反虚拟机和反沙箱相关

admin 2024年1月4日09:30:20评论25 views字数 4063阅读13分32秒阅读模式

通过关注系统环境来检测沙箱或虚拟机。导致不运行恶意代码,而是运行其他无害的代码。

RAM/CPU

一般来说虚拟的内存和CPU的数量都是有限的,但是这里不建议加虚拟机的反调试,因为有时候我们去打项目的时候难免会遇到Vcenter搭建的,但是话又说回来,一般来说使用Vcenter创建的虚拟机里面都跑一些正常的业务,内存这些也就不会很小。

比如说我们可以检测CPU处理器的数量是否低于或等于2,并且RAM是否低于4GB,如果低于的话那么我们直接运行正常的代码就可以了比如说可以MessageBoxA弹框之类的。

如下代码:

#include <stdio.h>#include <windows.h>
int main() { SYSTEM_INFO info; MEMORYSTATUSEX status; GetSystemInfo(&info); printf("处理器: %un", info.dwNumberOfProcessors); status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); printf("内存: %I64u MBn", status.ullTotalPhys / (1024 * 1024));
return 0;}

这里的SYSTEM_INFO,它是一个结构类型,它里面包含了系统资源的相关信息,我们可以利用它来检索CPU的数量。MEMORYSTATUSEX也是一个结构,里面包含了内存的状态等等,然后通过调用GetSystemInfo函数来检索关硬件的信息,最后再调用GlobalMemoryStatusEx函数检索有关系统内存状态的信息。

反虚拟机和反沙箱相关

我们来查看虚拟机的内存和CPU。

反虚拟机和反沙箱相关

获取到之后就可以判断了,如果处理器小于4个,并且内存小于4GB的话,执行正常代码。

反虚拟机和反沙箱相关

#include <stdio.h>#include <windows.h>
int main() { SYSTEM_INFO info; MEMORYSTATUSEX status; GetSystemInfo(&info); printf("处理器: %un", info.dwNumberOfProcessors); status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); printf("内存: %I64u MBn", status.ullTotalPhys / (1024 * 1024)); if (info.dwNumberOfProcessors < 8 && (status.ullTotalPhys / (1024 * 1024)) < 4096) { MessageBoxA(NULL, "执行正常代码", "执行正常代码", NULL); } else { MessageBoxA(NULL, "执行shellcode", "执行shellcode", NULL);
} return 0;}

通过查询VM文件反虚拟机

虚拟机需要一些特定的文件才能跑起来,无论是Vmware还是VirtualBox都有自己的特定文件,我们可以查询这些文件的路径来判断是否被分析。

这里可以使用Windows API来实现。

如下代码:

首先通过LoadLibrary去加载NTDLL.DLL模块。

HMODULE ntdllTest = LoadLibrary(L"ntdll.dll");

获取到DLL之后通过GetProcAddress去动态获取函数的地址。

#include <stdio.h>#include <windows.h>#include <winternl.h>
typedef NTSTATUS(NTAPI* pNtOpenFile) ( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions);typedef VOID(NTAPI* pRtlInitUnicodeString) ( PUNICODE_STRING DestinationString, PCWSTR SourceString);
int main() { //通过LoaderLibrary先去加载NTDLL.DLL模块 HMODULE ntdllTest = LoadLibrary(L"ntdll.dll"); pNtOpenFile NtOpenFile = (pNtOpenFile)GetProcAddress(ntdllTest, "NtOpenFile"); pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(ntdllTest, "RtlInitUnicodeString"); getchar();}

反虚拟机和反沙箱相关

紧接着指定要读取的文件。

 UNICODE_STRING dirName; RtlInitUnicodeString(&dirName,L"C:\Users\Admin\Desktop\1.txt");

然后去搜索文件,不区分大小写。

InitializeObjectAttributes(&objectAttributes, &dirName, OBJ_CASE_INSENSITIVE, nullptr, nullptr);

最后打开文件,如果打开成功的话,那么就执行正常代码,如果打开失败的话,那么就执行shellcode。

完整代码:

#include <stdio.h>#include <windows.h>#include <winternl.h>
typedef NTSTATUS(NTAPI* pNtOpenFile) ( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions);typedef VOID(NTAPI* pRtlInitUnicodeString) ( PUNICODE_STRING DestinationString, PCWSTR SourceString);
int main() { //通过LoaderLibrary先去加载NTDLL.DLL模块 HMODULE ntdllTest = LoadLibrary(L"ntdll.dll"); pNtOpenFile NtOpenFile = (pNtOpenFile)GetProcAddress(ntdllTest, "NtOpenFile"); pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(ntdllTest, "RtlInitUnicodeString"); HANDLE hFile = NULL; NTSTATUS status; UNICODE_STRING dirName; IO_STATUS_BLOCK ioStatusBlock; RtlInitUnicodeString(&dirName,L"C:\Users\Admin\Desktop\1.txt"); OBJECT_ATTRIBUTES objectAttributes; InitializeObjectAttributes(&objectAttributes, &dirName, OBJ_CASE_INSENSITIVE, nullptr, nullptr); status = NtOpenFile(&hFile, FILE_READ_DATA, &objectAttributes, &ioStatusBlock, FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(status)) { MessageBoxA(NULL, "执行shellcode", "shellcode", NULL); } else { MessageBoxA(NULL, "执行正常代码", "执行正常代码", NULL);
}
getchar();}


反虚拟机和反沙箱相关

那么这里的话就可以将C:UsersAdminDesktop1.txt 更改为特定的一些文件,比如VMware 3D 驱动程序,vm3dum64.dll,VMware 虚拟 SCSI 驱动程序 vmscsi.sys等等。

反虚拟机和反沙箱相关

通过Sleep进行规避

我们可以利用延时来规避沙箱。我们可以使用NtDelayExecution来进行延迟。

#include <iostream>#include <Windows.h>#include <string>#include <winternl.h>typedef  NTSTATUS(NTAPI* pNtDelayExecution) (  BOOL Alertable,   PLARGE_INTEGER DelayInterval);
int main(){ //获取NTDLL的基地址 HMODULE hmodule = GetModuleHandleA("NTDLL.DLL"); pNtDelayExecution NtDelayExecution = (pNtDelayExecution)GetProcAddress(hmodule, "NtDelayExecution");
LARGE_INTEGER delay; delay.QuadPart = -50000000; //睡眠5秒 NTSTATUS status = NtDelayExecution(FALSE, &delay);
printf("sucess");}

其实是和Sleep函数是差不多的,这里延迟了5秒,我们在写loader的时候延迟几分钟即可。

原文始发于微信公众号(Relay学安全):反虚拟机和反沙箱相关

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月4日09:30:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   反虚拟机和反沙箱相关http://cn-sec.com/archives/2362239.html

发表评论

匿名网友 填写信息