溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

反虛擬機技術(shù)虛擬機硬件化處理過檢測

發(fā)布時間:2020-08-03 12:57:23 來源:網(wǎng)絡(luò) 閱讀:7633 作者:股海封喉 欄目:軟件技術(shù)

過檢測虛擬機下載:

k7.8x64下載地址①:https://yunpan.#/surl_ydaQm3pwpEk
k7.8x64下載地址②:https://pan.baidu.com/s/1iaCU-FZLs5ScEE3PPK1fLA

過檢測說明介紹:

惡意代碼編寫者經(jīng)常使用反虛擬機技術(shù)逃避分析,這種技術(shù)可以檢測自己是否運行在虛擬機中。如果惡意代碼探測到自己在虛擬機中運行,它會執(zhí)行與其本身行為不同的行為,其中最簡單的行為是停止自身運行。近年來,隨著虛擬化技術(shù)的使用不斷增加,采用反虛擬機技術(shù)的惡意代碼數(shù)量逐漸下降。惡意代碼編寫者已經(jīng)開始意識到,目標主機是虛擬機,也并不意味著它就沒有**價值。隨著虛擬化技術(shù)的不斷發(fā)展和普通應(yīng)用,反虛擬機技術(shù)可能變得更加少見。這里研究最常見的反虛擬機技術(shù)(包括VMware、virtualbox和virtualpc,重點是最常用的VMware),并且介紹一些如何防御它們的辦法。一、檢測虛擬機痕跡1.根據(jù)MAC地址
通常,MAC地址的前三個字節(jié)標識一個提供商。以00:05:69、00:0c:29和00:50:56開始的MAC地址與VMware相對應(yīng);以00:03:ff開始的MAC地址與virtualpc對應(yīng);以08:00:27開始的MAC地址與virtualbox對應(yīng)。
BOOL CheckVMWare()
{
string mac;
get_3part_mac(mac);
if (mac=="00-05-69" || mac=="00-0c-29" || mac=="00-50-56")
{
return TRUE;
}
else
{
return FALSE;
}
}BOOL CheckVirtualPC()
{
string mac;
get_3part_mac(mac);
if (mac=="00-03-ff")
{
return TRUE;
}
else
{
return FALSE;
}
}BOOL CheckVirtualBox()
{
string mac;
get_3part_mac(mac);
if (mac=="08-00-27")
{
return TRUE;
}
else
{
return FALSE;
}
}typedef struct ASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff[30];
} ASTAT,
PASTAT;void get_3part_mac(string &mac)
{
NCB Ncb;
ASTAT Adapter;
UCHAR uRetCode;
LANA_ENUM lenum;
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBENUM;
Ncb.ncb_buffer = (UCHAR )&lenum;
Ncb.ncb_length = sizeof(lenum);
uRetCode = Netbios(&Ncb);
for (int i = 0; i < lenum.length; i++)
{
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = lenum.lana[i];
uRetCode = Netbios(&Ncb);
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = lenum.lana[i];
strcpy((char
)Ncb.ncb_callname, "");
Ncb.ncb_buffer = (unsigned char
)&Adapter;
Ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios(&Ncb);
if (uRetCode == 0)
{
char tmp[128];
sprintf(tmp, "%02x-%02x-%02x",
Adapter.adapt.adapter_address[0],
Adapter.adapt.adapter_address[1],
Adapter.adapt.adapter_address[2]
);
mac = tmp;
}
}
}
2.基于主板序列號、主機型號、系統(tǒng)盤所在磁盤名稱等其他硬件信息
//通過WMI獲取主機信息
BOOL ManageWMIInfo(string &result, string table, wstring wcol)
{
HRESULT hres;
char bord[1024];
//初始化COM
hres = CoInitialize(0);
//獲得WMI連接COM接口
IWbemLocator pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID
) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< "Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return false;
}
//通過連接接口連接WMI的內(nèi)核對象名ROOT//CIMV2
IWbemServices pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return false;
}
//設(shè)置請求代理的安全級別
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
//通過請求代理來向WMI發(fā)送請求
IEnumWbemClassObject
pEnumerator = NULL;
string select = "SELECT FROM "+ table;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(select.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for Network Adapter Configuration failed."
<< " Error code = 0x”"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
//循環(huán)枚舉所有的結(jié)果對象
ULONG uReturn = 0;
IWbemClassObject
pclsObj;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
VariantInit(&vtProp);
hr = pclsObj->Get(wcol.c_str(), 0, &vtProp, 0, 0);
if(!FAILED(hr))
{
CW2A tmpstr1(vtProp.bstrVal);
strcpy_s(bord,200,tmpstr1);
result = bord;
}
VariantClear(&vtProp);
}
//釋放資源
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
pclsObj->Release();
CoUninitialize();
return true;
}BOOL CheckVMWare()
{
string table = "Win32_BaseBoard";
wstring wcol = L"SerialNumber";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret == "None")
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL CheckVMWare()
{
string table = "Win32_DiskDrive";
wstring wcol = L"Caption";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("VMware") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL CheckVMWare()
{
string table = "Win32_computersystem";
wstring wcol = L"Model";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("VMware") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}BOOL CheckVirtualBox()
{
string table = "Win32_computersystem";
wstring wcol = L"Model";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("VirtualBox") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}BOOL CheckVirtualBox()
{
string table = "Win32_DiskDrive";
wstring wcol = L"Caption";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("VBOX") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}

BOOL CheckVirtualPC()
{
string table = "Win32_DiskDrive";
wstring wcol = L"Caption";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("Virtual HD") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL CheckVirtualPC()
{
string table = "Win32_computersystem";
wstring wcol = L"Model";
string ret;
ManageWMIInfo(ret, table, wcol);
if (ret.find("Virtual Machine") != string::npos)
{
return TRUE;
}
else
{
return FALSE;
}
}
3.根據(jù)當前進程信息
通過進程快照讀取當前進程信息,查找是否存在虛擬機中特有的進程,如VMware中的vmware.exe和VirtualBox中的VBoxService.exe。
BOOL CheckVMWare()
{
DWORD ret = 0;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bMore = Process32First(hProcessSnap, &pe32);
while(bMore)
{
if (strcmp(pe32.szExeFile, "vmware.exe")==0)
{
return TRUE;
}
bMore = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return FALSE;
}BOOL CheckVirtualBox()
{
DWORD ret = 0;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bMore = Process32First(hProcessSnap, &pe32);
while(bMore)
{
if (strcmp(pe32.szExeFile, "VBoxService.exe")==0)
{
return TRUE;
}
bMore = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return FALSE;
}
4.根據(jù)特定的文件夾或文件信息
通過查找磁盤中是否存在特定的文件夾或文件,判斷當前是否在虛擬機中。VMware虛擬機中通常會有路徑C:\Program Files\VMware\VMware Tools\;VirtualBox虛擬機中通常會有路徑C:\Program Files\Oracle\VirtualBox Guest Additions\。

BOOL CheckVMware()
{
if (PathIsDirectory("C:\Program Files\VMware\VMware Tools\") == 0)
{
return FALSE;
}
else
{
return TRUE;
}
}BOOL CheckVirtualBox()
{
if (PathIsDirectory("C:\Program Files\Oracle\VirtualBox Guest Additions\") == 0)
{
return FALSE;
}
else
{
return TRUE;
}
}
5.根據(jù)特定注冊表信息
通過讀取主機具有虛擬機特性的注冊表位置來判斷是否處于虛擬機環(huán)境中。針對VMware可以判斷注冊表項HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe;針對VirtualBox可以判斷注冊表項HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest Additions。當然,注冊表中能被檢測出的位置很多,這里只是舉個例子。

BOOL CheckVMWare()
{
HKEY hkey;
if (RegOpenKey(HKEY_CLASSES_ROOT, "\Applications\VMwareHostOpen.exe", &hkey) == ERROR_SUCCESS)
{
return TRUE;
}
else
{
return FALSE;
}
}BOOL CheckVirtualBox()
{
HKEY hkey;
if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\Oracle\VirtualBox Guest Additions", &hkey) == ERROR_SUCCESS)
{
return TRUE;
}
else
{
return FALSE;
}
}
6.根據(jù)特定服務(wù)名
通過獲取主機當前具有VMware特性的服務(wù)信息,判斷當前主機是否為虛擬機。在VMware中通常會存在VMware物理磁盤助手服務(wù)和VMware Tools服務(wù)等;在VirtualBox中通常會存在VirtualBox Guest Additions Service服務(wù)等。

BOOL CheckVMWare()
{
int menu = 0;
//打開系統(tǒng)服務(wù)控制器
SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if(SCMan == NULL)
{
cout << GetLastError() << endl;
printf("OpenSCManager Eorror/n");
return -1;
}
//保存系統(tǒng)服務(wù)的結(jié)構(gòu)
LPENUM_SERVICE_STATUSA service_status;
DWORD cbBytesNeeded = NULL;
DWORD ServicesReturned = NULL;
DWORD ResumeHandle = NULL;
service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024 64);
//獲取系統(tǒng)服務(wù)的簡單信息
bool ESS = EnumServicesStatusA(SCMan, //系統(tǒng)服務(wù)句柄
SERVICE_WIN32, //服務(wù)的類型
SERVICE_STATE_ALL, //服務(wù)的狀態(tài)
(LPENUM_SERVICE_STATUSA)service_status, //輸出參數(shù),系統(tǒng)服務(wù)的結(jié)構(gòu)
1024
64, //結(jié)構(gòu)的大小
&cbBytesNeeded, //輸出參數(shù),接收返回所需的服務(wù)
&ServicesReturned, //輸出參數(shù),接收返回服務(wù)的數(shù)量
&ResumeHandle); //輸入輸出參數(shù),第一次調(diào)用必須為0,返回為0代表成功
if(ESS == NULL)
{
printf("EnumServicesStatus Eorror/n");
return -1;
}
for(int i = 0; i < ServicesReturned; i++)
{
if (strstr(service_status[i].lpDisplayName, "VMware Tools")!=NULL || strstr(service_status[i].lpDisplayName, "VMware 物理磁盤助手服務(wù)")!=NULL)
{
return TRUE;
}
}
//關(guān)閉服務(wù)管理器的句柄
CloseServiceHandle(SCMan);
return FALSE;
}BOOL CheckVirtualPC()
{
int menu = 0;
//打開系統(tǒng)服務(wù)控制器
SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if(SCMan == NULL)
{
cout << GetLastError() << endl;
printf("OpenSCManager Eorror/n");
return -1;
}
//保存系統(tǒng)服務(wù)的結(jié)構(gòu)
LPENUM_SERVICE_STATUSA service_status;
DWORD cbBytesNeeded = NULL;
DWORD ServicesReturned = NULL;
DWORD ResumeHandle = NULL;
service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024 64);
//獲取系統(tǒng)服務(wù)的簡單信息
bool ESS = EnumServicesStatusA(SCMan, //系統(tǒng)服務(wù)句柄
SERVICE_WIN32, //服務(wù)的類型
SERVICE_STATE_ALL, //服務(wù)的狀態(tài)
(LPENUM_SERVICE_STATUSA)service_status, //輸出參數(shù),系統(tǒng)服務(wù)的結(jié)構(gòu)
1024
64, //結(jié)構(gòu)的大小
&cbBytesNeeded, //輸出參數(shù),接收返回所需的服務(wù)
&ServicesReturned, //輸出參數(shù),接收返回服務(wù)的數(shù)量
&ResumeHandle); //輸入輸出參數(shù),第一次調(diào)用必須為0,返回為0代表成功
if(ESS == NULL)
{
printf("EnumServicesStatus Eorror/n");
return -1;
}
for(int i = 0; i < ServicesReturned; i++)
{
if (strstr(service_status[i].lpDisplayName, "Virtual Machine")!=NULL)
{
return TRUE;
}
}
//關(guān)閉服務(wù)管理器的句柄
CloseServiceHandle(SCMan);
return FALSE;
}BOOL CheckVirtualBox()
{
int menu = 0;
//打開系統(tǒng)服務(wù)控制器
SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if(SCMan == NULL)
{
cout << GetLastError() << endl;
printf("OpenSCManager Eorror/n");
return -1;
}
//保存系統(tǒng)服務(wù)的結(jié)構(gòu)
LPENUM_SERVICE_STATUSA service_status;
DWORD cbBytesNeeded = NULL;
DWORD ServicesReturned = NULL;
DWORD ResumeHandle = NULL;
service_status = (LPENUM_SERVICE_STATUSA)LocalAlloc(LPTR, 1024 64);
//獲取系統(tǒng)服務(wù)的簡單信息
bool ESS = EnumServicesStatusA(SCMan, //系統(tǒng)服務(wù)句柄
SERVICE_WIN32, //服務(wù)的類型
SERVICE_STATE_ALL, //服務(wù)的狀態(tài)
(LPENUM_SERVICE_STATUSA)service_status, //輸出參數(shù),系統(tǒng)服務(wù)的結(jié)構(gòu)
1024
64, //結(jié)構(gòu)的大小
&cbBytesNeeded, //輸出參數(shù),接收返回所需的服務(wù)
&ServicesReturned, //輸出參數(shù),接收返回服務(wù)的數(shù)量
&ResumeHandle); //輸入輸出參數(shù),第一次調(diào)用必須為0,返回為0代表成功
if(ESS == NULL)
{
printf("EnumServicesStatus Eorror/n");
return -1;
}
for(int i = 0; i < ServicesReturned; i++)
{
if (strstr(service_status[i].lpDisplayName, "</span>VirtualBox Guest")!=NULL)<span style="font-size:10px;">
{
return TRUE;
}
}
//關(guān)閉服務(wù)管理器的句柄
CloseServiceHandle(SCMan);
return FALSE;
}
7.根據(jù)時間差
由于在虛擬機中,代碼的運行速度通常不如真實主機。所以惡意代碼通過運行一段特定的代碼來比較這段代碼在虛擬機和真實主機之中的相對運行時間,以此來判斷是否處于虛擬機之中。
BOOL CheckVMWare()
{
asm
{
rdtsc
xchg ebx,eax
rdtsc
sub eax,ebx
cmp eax,0xFF
jg detected
}
return FALSE;
detected:
return TRUE;
}BOOL CheckVirtualPC()
{
asm
{
rdtsc
xchg ebx,eax
rdtsc
sub eax,ebx
cmp eax,0xFF
jg detected
}
return FALSE;
detected:
return TRUE;
}BOOL CheckVirtualBox()
{
asm
{
rdtsc
xchg ebx,eax
rdtsc
sub eax,ebx
cmp eax,0xFF
jg detected
}
return FALSE;
detected:
return TRUE;
}
二、查找漏洞指令
虛擬機監(jiān)視器監(jiān)視虛擬機的運行,它運行在宿主操作系統(tǒng),并為客戶機操作系統(tǒng)提供一個完整的虛擬平臺。與此同時,虛擬機監(jiān)視器也存在一些可以被惡意代碼探測到虛擬化的安全缺陷。在內(nèi)核模式下,VMware使用二進制翻譯技術(shù)進行指令的模擬。運行于內(nèi)核態(tài)的某些特權(quán)指令被解釋和模擬,所以它們不在物理處理器上運行。相反,在用戶模式下,代碼直接在處理器上運行,幾乎所有與硬件交互的指令,要么是特權(quán)指令,要么會產(chǎn)生內(nèi)核態(tài)陷阱指令或中斷指令。VMware截獲所有中斷并處理它們,以便虛擬機仍然認為這是一個正常機器。然而在x86體系結(jié)構(gòu)中,一些指令在獲取硬件相關(guān)的信息時并不產(chǎn)生異常,如sidt、sgdt、sldt、cpuid等等。為了正確虛擬這些指令,VMware需要在所有指令上進行二進制翻譯,因此造成巨大的性能損失。為了避免執(zhí)行全指令模擬造成的巨大性能損失,VMware允許一些特定指令在沒有正確虛擬化的前提下運行。最終,這意味著某些指令序列在VMware虛擬機而不是在物理機中運行時返回不同的結(jié)果。處理器使用某些關(guān)鍵的結(jié)構(gòu)與表,它們會被加載與真實系統(tǒng)不同的偏移量,而這正是未進行全虛擬化的副作用。中斷描述表(IDT)是CPU內(nèi)部的一個數(shù)據(jù)結(jié)構(gòu),操作系統(tǒng)使用它來確保正確響應(yīng)中斷和異常。在x86體系結(jié)構(gòu)下,所有的內(nèi)存獲取,或是通過全局描述表(GDT)獲得,或是通過本地描述表(LDT)獲得。這些表中包含段描述符,它們提供每一個段的詳細存取信息,其中包含段基地址類型、長度,以及存取權(quán)限等等。IDT、GDT和LDT是CPU內(nèi)部的寄存器,它們分別存放著各自表的基地址和大小。有三條敏感指令(sidt、sgdt和sldt)可以讀取這些表的位置,并且將相應(yīng)的寄存器存入內(nèi)存地址。因為這些指令可以隨時被用戶態(tài)代碼調(diào)用,且不會產(chǎn)生陷阱,也未被VMware正確虛擬化,所以這些異常都可能被用來探測VMware的存在。1.使用Red Pill反虛擬機技術(shù)
Red Pill通過運行sidt指令獲取IDTR寄存器的值。虛擬機監(jiān)視器必須重新定位Guest系統(tǒng)的IDTR,來避免與Host系統(tǒng)的IDTR沖突。因為在虛擬機中運行sidt指令時,虛擬機監(jiān)視器不會得到通知,所以會返回虛擬機的IDTR。Red Pill通過測試這種差異來探測Vmware的使用。這種方法存在一個缺陷,由于IDT的值只針對處于正在運行的處理器而言,在單CPU中它是個常量,但當它處于多CPU時就可能會受到影響了,因為每個CPU都有其自己的IDT,這樣問題就自然而然的產(chǎn)生了。針對此問題,Offensive
Computing組織成員提出了兩種應(yīng)對方法,其中一種方法就是利用Red Pill反復地在系統(tǒng)上循環(huán)執(zhí)行任務(wù),以此構(gòu)造出一張當前系統(tǒng)的IDT值變化統(tǒng)計圖,但這會增加CPU負擔;另一種方法就是windows API函數(shù)SetThreadAffinityMask()將線程限制在單處理器上執(zhí)行,當執(zhí)行此測試時只能準確地將線程執(zhí)行環(huán)境限制在本地處理器,而對于將線程限制在VM處理器上就可能行不通了,因為VM是計劃在各處理器上運行的,VM線程在不同的處理器上執(zhí)行時,IDT值將會發(fā)生變化,因此此方法也很少被使用。2.使用No Pill反虛擬機技術(shù)
sgdt和sldt指令探測VMware的技術(shù)通常被稱為No Pill。
BOOL CheckVMWare()
{
ULONG xdt = 0 ;
ULONG InVM = 0;
asm
{
push edx
sidt [esp-2]
pop edx
nop
mov xdt , edx
}
if (xdt > 0xd0000000)
{

    InVM = 1;
}
else
{
    InVM = 0;
}
__asm
{
    push edx
    sgdt [esp-2]
    pop edx
    nop
    mov xdt , edx
}
if (xdt > 0xd0000000)
{
    InVM += 1;
}

if (InVM == 0)
{
return FALSE;
}
else
{
return TRUE;
}
}
通過禁用VMware加速可以防止No Pill技術(shù)的探測。3.查詢I/O端口
VMware使用虛擬化的I/O端口完成宿主系統(tǒng)與虛擬機之間的通信,以便支持諸如復制和粘貼功能。這個端口可以被查詢,然后與一個神秘數(shù)比較,以確定VMware的使用。
這種技術(shù)成功的關(guān)鍵在于x86體系結(jié)構(gòu)中的in指令,它從一個源操作數(shù)指定的端口復制數(shù)據(jù)到目的操作數(shù)指定的內(nèi)存地址。VMware會監(jiān)視in指令的執(zhí)行,并捕獲目的通信端口為0x5668(VX)的I/O。VMware會檢查第二個操作數(shù)是否是VX,在這種情況發(fā)生時,EAX寄存器載入的值是0x564D5868(VMXh),ECX寄存器必須被載入你希望在端口上執(zhí)行相應(yīng)操作的值,值0xA表示get VMware version type,0x14代表get the memory size。它們都可以被用來探測VMware,但0xA更受歡迎,因為它能確定VMware的版本。如代碼所示setz指令在magic數(shù)與VMXh匹配時設(shè)置返回值rc為1,如果在真實的機器上運行會觸發(fā)EXCEPTION_EXECUTE_HANDLER異常,在異常處理中設(shè)置返回值rc為0。
BOOL CheckVMWare()
{
bool rc = true;
try
{
asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0
mov ecx, 10
mov edx, 'VX'
in eax, dx
cmp ebx, 'VMXh'
setz [rc]
pop ebx
pop ecx
pop edx
}
}
except(EXCEPTION_EXECUTE_HANDLER)
{
rc = false;
}
return rc;
}
對付這種反虛擬化技術(shù)的最簡單方法是使用NOP指令替換in指令,或修補條件跳轉(zhuǎn),使得它不論比較結(jié)果如何,都執(zhí)行到未探測到虛擬機的程序分支。4.使用str指令
在保護模式下運行的所有程序在切換任務(wù)時,對于當前任務(wù)中指向TSS的段選擇器將會被存儲在任務(wù)寄存器中,TSS中包含有當前任務(wù)的可執(zhí)行環(huán)境狀態(tài),包括通用寄存器狀態(tài),段寄存器狀態(tài),標志寄存器狀態(tài),EIP寄存器狀態(tài)等等,當此項任務(wù)再次被執(zhí)行時,處理器就會其原先保存的任務(wù)狀態(tài)。每項任務(wù)均有其自己的TSS,而我們可以通過STR指令來獲取指向當前任務(wù)中TSS的段選擇器。這里STR(Store task register)指令是用于將任務(wù)寄存器 (TR) 中的段選擇器存儲到目標操作數(shù),目標操作數(shù)可以是通用寄存器或內(nèi)存位置,使用此指令存儲的段選擇器指向當前正在運行的任務(wù)的任務(wù)狀態(tài)段
(TSS)。在虛擬機和真實主機之中,通過STR讀取的地址是不同的,當?shù)刂返扔?x0040xxxx時,說明處于虛擬機中,否則為真實主機。
BOOL CheckVMWare()
{
unsigned char mem[4] = {0};
asm str mem;
if ((mem[0] == 0x00) && (mem[1] == 0x40))
{
return TRUE;
}
else
{
return FALSE;
}
}
在IDA PRO中,可以使用下面的腳本查找我們前面提到的指令。from idautils import
from idc import

heads = Heads(SegStart(ScreenEA()), SegEnd(ScreenEA()))
antiVM = []
for i in heads:
if (GetMnem(i) == "sidt" or GetMnem(i) == "sgdt" or GetMnem(i) == "sldt" or GetMnem(i) == "smsw" or GetMnem(i) == "str" or GetMnem(i) == "in" or GetMnem(i) == "cpuid"):
antiVM.append(i)

print "Number of potential Anti-VM instructions: %d" % (len(antiVM))

for i in antiVM:
SetColor(i, CIC_ITEM, 0x0000ff)
Message("Anti-VM: %08x\n" % i)要在IDA PRO中運行腳本,選擇File->Script File,可以看到下面的輸出。

這個輸出表明腳本檢測到了三條漏洞指令類型。滾動到IDA PRO的反匯編窗口,我們看到三條紅色高亮顯示的指令sidt、str和sldt。5.使用無效的操作碼
每臺機器都有一組定義的指令,通常稱為指令集架構(gòu)(Instruction Set Architecture)。當遇到無效指令(不存在于ISA中)時,機器引發(fā)無效操作碼異常。軟件可以處理異常(使用通常的try/catch機制),也可以讓操作系統(tǒng)處理異常,或者在最壞的情況下崩潰機器。VirtualPC使用一堆無效指令來允許虛擬機和VirtualPC之間連接。當VirtualPC的虛擬機想要與VirtualPC通信時,程序設(shè)置異常處理程序(try/catch塊),在調(diào)用VM軟件之前設(shè)置所需的參數(shù),發(fā)出特殊的無效操作碼指令。VM軟件將識別此無效操作碼并相應(yīng)地操作,如果VirtualPC存在則不引起異常,并且如果VirtualPC不存在則產(chǎn)生異常。最后,程序的catch塊將處理異常并檢查返回的VM軟件的參數(shù)??傊?,VirtualPC使用無效的操作碼機制作為后門。
DWORD IslnsideVPC_exceptionFilter(LPEXCEPTION_POINTERS ep)
{
PCONTEXT ctx=ep->ContextRecord;
ctx->Ebx = -1; //未運行在VPC中
ctx->Eip += 4; //跳過”call VPC”操作
return EXCEPTION_CONTINUE_EXECUTION;
}BOOL CheckVirtualPC()
{
bool rc = TRUE;
try
{
asm
{
push ebx
mov ebx, 0
mov eax, 1
emit 0fh
emit 3fh
emit 07h
emit 0bh
test ebx, ebx
setz[rc]
pop ebx
}
}
__except(IslnsideVPC_exceptionFilter(GetExceptionInformation()))
{
rc = FALSE;
}
return rc;
}
三、基于社會工程學的技巧1.檢測電腦中常用軟件的使用情況
名為Intelligent Software Solutions Inc.doc的惡意軟件樣本文件使用了下面的反虛擬機技巧,SHA256值為048fc07fb94a74990d2d2b8e92c099f3f986af185c32d74c857b07f7fcce7f8e。

RecentFiles對象表示系統(tǒng)最近打開過的歷史文檔。通常,安裝了word程序的用戶可能會打開超過2個或更多數(shù)量的文檔。然而,當該惡意軟件植入到新創(chuàng)建的虛擬機和word環(huán)境中后,總是狀況不斷,不能正常運行。每次測試時手動打開一兩次,總是出現(xiàn)程序異常。即使是保存了虛擬機鏡像狀態(tài),重啟調(diào)試分析后,惡意程序仍然不能正常執(zhí)行。從DKTxHE函數(shù)功能可以看出,惡意軟件以RecentFiles數(shù)量來判斷是否身處VM環(huán)境中,如果在VM環(huán)境中,它將不會執(zhí)行任何惡意行為。之后,隨意創(chuàng)建了3個不同名稱的word文檔,逐一打開并關(guān)閉,讓歷史文檔數(shù)量為3,最終成功運行并檢測到了惡意軟件。2.探測殺毒軟件公司相關(guān)的IP地址
同樣是上面的惡意軟件,它在另一個子程序中使用了下面的反虛擬機技巧。首先,它通過向遠程地址https://www.maxmind.com/geoip/v2.1/city/me發(fā)出某種認證請求,之后設(shè)置請求信息中的HTTP Refer屬性和User-Agent值,訪問鏈接https://www.maxmind.com/en/locate-my-ip-address以此獲取宿主系統(tǒng)的地址信息。獲取信息封裝于JSON格式文件中,包含國家、城市、或者與IP相關(guān)的組織機構(gòu)等信息。
{
"location": {
"latitude": 30.7858,
"longitude": -102.1232,
"metro_code": 705,
"accuracy_radius": 5,
"time_zone": "America/Los_Angeles"
},
"continent": {
"names": {
"ja": "北アメリカ",
"pt-BR": "América do Norte",
"de": "Nordamerika",
"es": "Norteamérica",
"ru": "Северная Америка",
"fr": "Amérique du Nord",
"zh-CN": "北美洲",
"en": "North America"
},
"code": "NA",
"geoname_id": 6255149
},
"city": {
"names": {
"pt-BR": "Oakland",
"de": "Oakland",
"es": "Oakland",
"ja": "オークランド",
"en": "Oakland",
"ru": "Окленд",
"fr": "Oakland",
"zh-CN": "奧克蘭"
},
"geoname_id": 5378538
},
"postal": {
"code": "94619"
},
"country": {
"names": {
"ru": "США",
"fr": "états-Unis",
"zh-CN": "美國",
"en": "United States",
"ja": "アメリカ合衆(zhòng)國",
"es": "Estados Unidos",
"pt-BR": "Estados Unidos",
"de": "USA"
},
"iso_code": "US",
"geoname_id": 6252001
},
"traits": {
"organization": "Comcast Cable",
"isp": "Comcast Cable",
"ip_address": "123.123.123.123",
"autonomous_system_organization": "Comcast Cable Communications, LLC",
"domain": "comcast.net",
"autonomous_system_number": 7922
},
"registered_country": {
"geoname_id": 6252001,
"names": {
"zh-CN": "美國",
"ru": "США",
"fr": "états-Unis",
"en": "United States",
"ja": "アメリカ合衆(zhòng)國",
"pt-BR": "Estados Unidos",
"de": "USA",
"es": "Estados Unidos"
},
"iso_code": "US"
},
"subdivisions": [
{
"geoname_id": 5332921,
"names": {
"ru": "Калифорния",
"fr": "Californie",
"zh-CN": "加利福尼亞州",
"en": "California",
"ja": "カリフォルニア州",
"pt-BR": "Califórnia",
"es": "California",
"de": "Kalifornien"
},
"iso_code": "CA"
}
]
}
在以上示例文件中,IP信息的organization字段顯示為美國Comcast寬帶網(wǎng)絡(luò)供應(yīng)商。惡意軟件發(fā)出訪問請求后,獲取到宿主系統(tǒng)的相關(guān)信息將存儲于某個數(shù)組中。如果獲取到的組織機構(gòu)名稱與以下JSON文件中的任何機構(gòu)字符串匹配,惡意軟件將發(fā)生異常并停止運行。
Amazon
anonymous
BitDefender
BlackOakComputers
Blue Coat
BlueCoat
Cisco
cloud
Data Center
DataCenter
DataCentre
dedicated
ESET, Spol
FireEye
ForcePoint
Fortinet
Hetzner
hispeed.ch
hosted
Hosting
Iron Port
IronPort
LeaseWeb
MessageLabs
Microsoft
MimeCast
NForce
Ovh Sas
Palo Alto
ProofPoint
Rackspace
security
Server
Strong Technologies
Trend Micro
TrendMicro
TrustWave
VMVault
Zscaler
當然,上述列表中的機構(gòu)名稱在代碼中是經(jīng)過混淆的。

四、虛擬機逃逸
VMware等軟件中或多或少都存在一些安全漏洞,可以利用這些漏洞使宿主操作系統(tǒng)崩潰或者是在宿主操作系統(tǒng)中運行代碼。當主機系統(tǒng)被感染后,一些公開可用的工具可以用來對VMware等軟件進行***。

總結(jié)
當遇到的惡意代碼似乎不能運行時,在使用調(diào)試或反匯編惡意代碼搜索其反虛擬機探測代碼之前,應(yīng)該考慮使用一個卸載了VMware Tools的虛擬機。VMware中有一些未文檔化的功能可以幫助減輕反虛擬機技術(shù)的探測。將下面的代碼放到VMware的.vmx文件中,以減輕虛擬機被探測的可能。
isolation.tools.getPtrLocation.disable = "TRUE"
isolation.tools.setPtrLocation.disable = "TRUE"
isolation.tools.setVersion.disable = "TRUE"
isolation.tools.getVersion.disable = "TRUE"
monitor_control.disable_directexec = "TRUE"
monitor_control.disable_chksimd = "TRUE"
monitor_control.disable_ntreloc = "TRUE"
monitor_control.disable_selfmod = "TRUE"
monitor_control.disable_reloc = "TRUE"
monitor_control.disable_btinout = "TRUE"
monitor_control.disable_btmemspace = "TRUE"
monitor_control.disable_btpriv = "TRUE"
monitor_control.disable_btseg = "TRUE"
參數(shù)directexec可以使用戶模式下的代碼被模擬執(zhí)行而不是直接在硬件上運行,因此它可以挫敗一些反虛擬機技術(shù)。前四條設(shè)置被VMware后門命令使用,它們的作用是使得運行在Guest系統(tǒng)中的VMware Tools不能獲取宿主系統(tǒng)的信息。這些設(shè)置會禁用VMware Tools的一些有用功能,并可能對虛擬機性能有嚴重負面影響。所以,僅當其他技術(shù)無效時再添加這些選項。當然,也可以將惡意代碼在其他虛擬環(huán)境或者物理主機上運行。同反調(diào)試技術(shù)一樣,要想發(fā)現(xiàn)惡意代碼中的反虛擬機技術(shù)需要在長期調(diào)試過程中積累更多經(jīng)驗。例如,看到一個代碼在一個條件跳轉(zhuǎn)處過早終止,這可能就是反虛擬機技術(shù)造成的結(jié)果。一如既往地警惕這種類型的問題,然后查看其之前的代碼,來確定它到底執(zhí)行了什么操作。和反調(diào)試技術(shù)一樣,通過修改條件跳轉(zhuǎn)指令或者使用NOP指令覆蓋來繞過相關(guān)探測。
最后讓我們總結(jié)一下提到的內(nèi)容。騰訊2016游戲安全技術(shù)競賽有一道題,大概意思就是給一個exe,要求編寫一個Tencent2016C.dll,并導出多個接口函數(shù) CheckVirtualPCX、CheckVMWareX、CheckVirtualBoxX。X為1-100之間的數(shù)字。函數(shù)功能是檢測自己是否處于相應(yīng)的虛擬機中,是返回TRUE,否則返回FALSE。函數(shù)的原型都是typedef BOOL (WINAPI* Type_CheckXXXXXX)();。編譯好dll之后,放在Tencent2016C.exe的同目錄,運行Tencent2016C.exe,點擊檢測按鈕,在物理機中運行時函數(shù)接口輸出為0,在VMware虛擬機、VirtualBox虛擬機和VirtualPC虛擬機中運行時,相關(guān)的接口輸出1。我們把提到的知識綜合一下完成這道題目。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI