1. 程式人生 > >病毒檢測與防毒技術大揭祕8

病毒檢測與防毒技術大揭祕8

3.4.自我保護設計方案及編碼實現

實現此功能,同樣使用API Hook技術,與上面介紹過的病毒防護功能類似。只是這裡不再是攔截CreateProcess,而是要接管OpenProcess函式。

也許有的程式設計師朋友會有疑惑,做我我保護,也就是要防止自己的程序被非法結束程序,在程式設計中,結束程序所使用API函式是TerminateProcess,而不是OpenProcess,這裡為什麼會說通過攔截OpenProcess實現保護程序呢?這是由於TerminateProcess函式結束程序時,需要使用程序控制代碼做為輸入引數,結束傳入的指定控制代碼的程序。但在不同程序間控制代碼是無法傳遞的,因為即便是同一個檔案,在每個不同的程序中都會為它分配不同的控制代碼。好在程序ID是可以傳遞的,而在使用TerminateProcess函式結束程序前,會先呼叫OpenProcess開啟程序並把控制代碼傳遞給TerminateProcess,而OpenProcess函式的輸入引數恰好為程序ID。這也就是我們選擇攔截OpenProcess的原因了。

防止被結束程序的原理很簡單,將DLL注入其它程序後,接管程序的OpenProcess函式,在我們自己定義的新OpenProcess函式被呼叫時,判斷是否要開啟我們防毒軟體的程序,並且其操作是否是要將要程序結束程序操作,如果是,就終止這個行為。這樣便實現了保護,做到了程序防殺。

且看編碼實現,首先是DLL中攔截OpenProcess的部分。鑑於上文中又詳細介紹過攔截CreateProcess函式的方法,這裡就不再重複對程式碼做說明了,參考上文程式碼中的註釋說明即可。

#include <windows.h>
#include "stdio.h"
#include "stdlib.h"

#pragma data_seg(".Shared2") 
static DWORD g_PID2Protect=0;
#pragma data_seg() 
#pragma comment(linker, "/section:.Shared2,rws") 

HANDLE hProcess=0;
UCHAR OldCode2[5]={0}, NewCode2[5]={0};
ULONG FunAddr2=0;
HINSTANCE hMod=0;
HHOOK hHook=0;

BOOL HookStatus2(BOOL Status){
BOOL ret2=FALSE;
if (Status) {
ret2 = WriteProcessMemory(hProcess, (void *)FunAddr2, NewCode2, 5, 0);
if (ret2) return TRUE;}
else {
ret2 = WriteProcessMemory(hProcess, (void *)FunAddr2, OldCode2, 5, 0);
if (ret2) return TRUE;}
return FALSE;
}

HANDLE WINAPI OpenProcessCallBack(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId)
{
HANDLE hProc=NULL;
if(dwProcessId==g_PID2Protect && (dwDesiredAccess & PROCESS_TERMINATE!=0))
{
hProc=NULL;
}else{
HookStatus2(FALSE);
hProc= OpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId);
HookStatus2(TRUE);
}
return hProc;
}

BOOL HookOpenProcess(){

ULONG JmpAddr2=0;
FunAddr2 = (ULONG)GetProcAddress(LoadLibrary("Kernel32.dll"), "OpenProcess");
memcpy(OldCode2, (void *)FunAddr2, 5);
NewCode2[0] = 0xe9;
JmpAddr2 = (ULONG)OpenProcessCallBack - FunAddr2 - 5;
memcpy(&NewCode2[1], &JmpAddr2, 4);
HookStatus2(TRUE);
return TRUE;
}

BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call, LPVOID lpReserved)
{
hMod = (HINSTANCE)hModule;
if (ul_reason_for_call==DLL_PROCESS_ATTACH)
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
HookOpenProcess();
}

if (ul_reason_for_call==DLL_PROCESS_DETACH) 
{
HookStatus2(FALSE);
}

return TRUE;
}

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam){
return(CallNextHookEx(hHook,nCode,wParam,lParam));
}

BOOL WINAPI SafeGuardOFF(){
return(UnhookWindowsHookEx(hHook));
}

BOOL WINAPI SafeGuardON(DWORD uPID){

g_PID2Protect=uPID;

hHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)HookProc, hMod, 0);
if (hHook) 
{
return TRUE;
}else{
return FALSE;
}
}

由程式碼中可知,此DLL的匯出函式有兩個:SafeGuardON和SafeGuardOFF,SafeGuardON用於開啟防護,引數是被保護程序的ID;SafeGuardOFF用於關閉防護。

在上層應用程式中,呼叫方法如下:

函式宣告:

Private Declare Function ActiveDefenseON Lib "ActiveDefense.dll" (ByVal TargetHwnd As Long) As Boolean
Private Declare Function ActiveDefenseOFF Lib "ActiveDefense.dll" () As Boolean

DLl中的函式再次封裝為新函式:

Public Function ActiveDefense(ByVal bOperation As Boolean) As Boolean

Dim lPid As Long

獲取當前程序PID,也就是我們防毒軟體的程序ID:

lPid = GetCurrentProcessId

Dim bRet As Boolean If bOperation = True Then

開啟主動防禦:

bRet = ActiveDefenseON(lPid) If bRet Then ActiveDefense = True Else ActiveDefense = False End If Else

關閉主動防禦:

ActiveDefenseOFF End If

End Function

有此簡單封裝過的函式,當防毒軟體啟動時呼叫,傳入引數true便可開啟防護,關閉程式時呼叫傳入false便可停止防護。使用非常簡單。

注:作者:wing qq:6465660 本書理論及功能、程式碼源於防毒軟體:“Ty2y防毒軟體”,作者授意,文章可自由轉載,只需註明原出處即可,特此說明。