《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 通信與網(wǎng)絡(luò) > 業(yè)界動(dòng)態(tài) > 網(wǎng)絡(luò)安全編程:行為監(jiān)控HIPS

網(wǎng)絡(luò)安全編程:行為監(jiān)控HIPS

2021-07-31
來源:計(jì)算機(jī)與網(wǎng)絡(luò)安全
關(guān)鍵詞: HIPS 行為監(jiān)控

  現(xiàn)在有一種流行的防病毒軟件被稱作HIPS,中文名字為主機(jī)入侵防御系統(tǒng),比如EQ。該軟件可以在進(jìn)程創(chuàng)建時(shí)、有進(jìn)程對(duì)注冊(cè)表進(jìn)行寫入時(shí)或有驅(qū)動(dòng)被加載時(shí),給用戶予以選擇,選擇是否攔截進(jìn)程的創(chuàng)建、是否攔截注冊(cè)表的寫入、是否攔截驅(qū)動(dòng)的加載等功能。

  HIPS純粹是以預(yù)防為主,比如有陌生的進(jìn)程在被創(chuàng)建階段,就可以讓用戶禁止,這樣就避免了特征碼查殺的滯后性。對(duì)于殺毒軟件的特征碼查殺而言,如果殺毒軟件不更新病毒數(shù)據(jù)庫,那么依賴病毒特征碼的殺毒軟件就無法查殺新型的病毒,對(duì)新型的病毒就成為一個(gè)擺設(shè)。

  行為監(jiān)控的原理主要就是對(duì)相關(guān)的關(guān)鍵API函數(shù)進(jìn)行HOOK,比如進(jìn)程攔截。當(dāng)一個(gè)木馬程序要秘密啟動(dòng)的時(shí)候,對(duì)CreateProcessW()函數(shù)進(jìn)行了HOOK,在進(jìn)程被創(chuàng)建前,會(huì)詢問用戶是否啟動(dòng)該進(jìn)程,那么木馬的隱秘啟動(dòng)就被暴露出來了。對(duì)于沒有安全知識(shí)的大眾來說,使用HIPS可能有點(diǎn)困難,也許仍然會(huì)讓木馬運(yùn)行。因?yàn)椴皇敲總€(gè)使用計(jì)算機(jī)的人都對(duì)計(jì)算機(jī)有所了解,計(jì)算機(jī)對(duì)于他們而言可能只用來打游戲或看電影。這該如何做呢?現(xiàn)在通常使用的方法就是使用白庫和黑庫,也就是所謂的白名單和黑名單。在進(jìn)程被創(chuàng)建時(shí),把要?jiǎng)?chuàng)建的進(jìn)程到黑白庫中去匹配,然后做相應(yīng)的動(dòng)作,或者放行,或者攔截。

  下面來實(shí)現(xiàn)一個(gè)應(yīng)用層下的簡(jiǎn)單的進(jìn)程防火墻、注冊(cè)表防火墻的功能。

  1. 簡(jiǎn)單進(jìn)程防火墻

  進(jìn)程防火墻指的是放行/攔截準(zhǔn)備要?jiǎng)?chuàng)建的進(jìn)程。進(jìn)程的創(chuàng)建是依靠CreateProcessW()函數(shù)完成的。只要HOOK CreateProcessW()函數(shù)就可以實(shí)現(xiàn)進(jìn)程防火墻的功能。對(duì)于注冊(cè)表來說,要對(duì)非法進(jìn)程進(jìn)行刪除或?qū)懭胱?cè)表鍵值進(jìn)行管控,因此需要HOOK兩個(gè)注冊(cè)表函數(shù),分別是注冊(cè)表寫入函數(shù)RegSetValueExW()和注冊(cè)表刪除函數(shù)RegDeleteValueW()。由于使用了HOOK,那么就必然要涉及DLL的編寫。這里分DLL和EXE兩部分來進(jìn)行詳細(xì)的介紹。

  2. 實(shí)現(xiàn)HOOK部分的DLL程序的編寫

  因?yàn)橐獙?duì)目標(biāo)進(jìn)程進(jìn)行HOOK,因此要編寫DLL程序。創(chuàng)建一個(gè)DLL程序,并加入已封裝的ILHook.h頭文件和ILHook.cpp的實(shí)現(xiàn)文件。

  為了能在所有的基于消息的進(jìn)程中注入自己的DLL,必須使用Windows鉤子,這樣就可以將DLL輕易地注入基于消息的進(jìn)程中。代碼如下:

  #pragma data_seg(“.shared”)

  HHOOK g_hHook = NULL;

  #pragma data_seg()

  #pragma comment (linker, “.shared, RWS”)

  extern “C” __declspec(dllexport) VOID SetHookOn(HWND hWnd);

  extern “C” __declspec(dllexport) VOID SetHookOff();

  HWND g_ExeHwnd = NULL;

  LRESULT CALLBACK GetMsgProc(

  int code, // 鉤子編碼

  WPARAM wParam, // 移除選項(xiàng)

  LPARAM lParam // 消息

 ?。?/p>

  {

  return CallNextHookEx(g_hHook, code, wParam, lParam);

  }

  VOID SetHookOn(HWND hWnd)

  {

  g_ExeHwnd = hWnd;

  SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInst, 0);

  }

  VOID SetHookOff()

  {

  UnhookWindowsHookEx(g_hHook);

  g_hHook = NULL;

  }

  以上函數(shù)用來定義導(dǎo)出函數(shù),用于加載完成HOOK功能的DLL文件。這里利用WH_ GETMESSAGE鉤子類型。

  定義3個(gè)CILHook類的對(duì)象,分別用來對(duì)CreateProcessW()函數(shù)、RegSetValueExW()函數(shù)和RegDeleteValueW()函數(shù)進(jìn)行掛鉤。具體定義如下:

  CILHook RegSetValueExWHook;

  CILHook CreateProcessWHook;

  CILHook RegDeleteValueWHook;

  HOOK部分是在DllMain()函數(shù)中完成的,具體代碼如下:

  BOOL APIENTRY DllMain( HANDLE hModule,

  DWORD ul_reason_for_call,LPVOID lpReserved)

  {

  switch ( ul_reason_for_call )

  {

  case DLL_PROCESS_ATTACH:

  {

  g_hInst = (HINSTANCE)hModule;

  RegSetValueExWHook.Hook(“advapi32.dll”,

  “RegSetValueExW”,(PROC)MyRegSetValueExA);

  RegDeleteValueWHook.Hook(“advapi32.dll”,

  “RegDeleteValueW”,(PROC)MyRegDeleteValueW);

  CreateProcessWHook.Hook(“kernel32.dll”,

  “CreateProcessW”,(PROC)MyCreateProcessW);

  break;

  }

  case DLL_PROCESS_DETACH:

  {

  RegSetValueExWHook.UnHook();

  RegDeleteValueWHook.UnHook();

  CreateProcessWHook.UnHook();

  if ( g_hHook != NULL )

  {

  SetHookOff();

  }

  break;

  }

  }

  return TRUE;

  }

  放行/攔截部分是給用戶選擇的,那么就要給出提示讓用戶進(jìn)行選擇,至少要給出放行/攔截的類型,比如是注冊(cè)表寫入或是進(jìn)程的創(chuàng)建,還要給出是哪個(gè)進(jìn)程進(jìn)行的操作。要把這個(gè)信息反饋給用戶,這里定義一個(gè)結(jié)構(gòu)體,將該結(jié)構(gòu)體的信息發(fā)送給用于加載DLL的EXE文件,并讓EXE給出提示。結(jié)構(gòu)體定義如下:

  typedef struct _HIPS_INFO

  {

  WCHAR wProcessName[0x200];

  DWORD dwHipsClass;

  }HIPS_INFO, *PHIPS_INFO;

  定義一些常量用來標(biāo)識(shí)放行/攔截的類型,具體如下:

  #define HIPS_CREATEPROCESS 0x00000001L

  #define HIPS_REGSETVALUE 0x00000002L

  #define HIPS_REGDELETEVALUE 0x00000003L

  將這些定義好以后,就可以開始完成HOOK函數(shù)了。這里主要給出CreateProcessW()函數(shù)的HOOK實(shí)現(xiàn)。其余兩個(gè)函數(shù)的HOOK實(shí)現(xiàn),請(qǐng)大家自行實(shí)現(xiàn)。具體代碼如下:

  BOOL

  WINAPI

  MyCreateProcessW(

  __in_opt LPCWSTR lpApplicationName,

  __inout_opt LPWSTR lpCommandLine,

  __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,

  __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,

  __in BOOL bInheritHandles,

  __in DWORD dwCreationFlags,

  __in_opt LPVOID lpEnvironment,

  __in_opt LPCWSTR lpCurrentDirectory,

  __in LPSTARTUPINFOW lpStartupInfo,

  __out LPPROCESS_INFORMATION lpProcessInformation

  )

  {

  HIPS_INFO sz = { 0 };

  if ( wcslen(lpCommandLine) != 0 )

  {

  wcscpy(sz.wProcessName, lpCommandLine);

  }

  else

  {

  wcscpy(sz.wProcessName, lpApplicationName);

  }

  sz.dwHipsClass = HIPS_CREATEPROCESS;

  COPYDATASTRUCT cds = { NULL, sizeof(HIPS_INFO), (void *)&sz };

  BOOL bRet = FALSE;

  if ( SendMessage(FindWindow(NULL, “Easy Hips For R3”),

  WM_COPYDATA,GetCurrentProcessId(),(LPARAM)&cds) != -1 )

  {

  CreateProcessWHook.UnHook();

  bRet = CreateProcessW(lpApplicationName, lpCommandLine,

  lpProcessAttributes, lpThreadAttributes,

  bInheritHandles, dwCreationFlags,

  lpEnvironment, lpCurrentDirectory,

  lpStartupInfo, lpProcessInformation);

  CreateProcessWHook.ReHook();

  }

  return bRet;

  }

  這里使用了一個(gè)SendMessage()函數(shù),該函數(shù)用來發(fā)送一個(gè)WM_COPYDATA消息,將結(jié)構(gòu)體傳給了加載DLL的EXE程序,使EXE程序把提示顯示給用戶。

  SendMessage()函數(shù)的功能非常強(qiáng)大,其定義如下:

  LRESULT SendMessage(

  HWND hWnd,

  UINT Msg,

  WPARAM wParam,

  LPARAM lParam

 ?。?;

  該函數(shù)的第一個(gè)參數(shù)是目標(biāo)窗口的句柄,第二個(gè)參數(shù)是消息類型,最后兩個(gè)參數(shù)是消息的附加參數(shù),根據(jù)消息類型的不同而不同。

  以上代碼就是DLL程序的全部了,剩下兩個(gè)對(duì)注冊(cè)表操作的HOOK函數(shù),由大家自己完成。

  3. 行為監(jiān)控前臺(tái)程序的編寫

  先來看一下程序能達(dá)到的效果,再講解程序EXE部分的實(shí)現(xiàn)代碼,如圖1和圖2所示。

圖1  程序主界面

  圖2  攔截提示框

  從上面兩個(gè)圖可以看出,程序的確是可以攔截進(jìn)程的啟動(dòng)的。當(dāng)單擊“允許”按鈕后,進(jìn)程會(huì)被正常創(chuàng)建;當(dāng)單擊“取消”按鈕后,進(jìn)程將被阻止創(chuàng)建。這就是最終要完成的功能,來看看主要的實(shí)現(xiàn)代碼。

  EXE的部分主要就是如何來啟動(dòng)行為監(jiān)控功能,以及如何接收DLL程序通過SendMessage()函數(shù)發(fā)出的消息給用戶彈出提示框。進(jìn)行攔截的部分已經(jīng)在DLL程序中通過HOOK實(shí)現(xiàn)了,所以重點(diǎn)也就在界面上和消息的接收上。

  先看如何啟動(dòng)和停止行為的監(jiān)控。具體代碼如下:

  typedef VOID (*SETHOOKON)(HWND);

  typedef VOID (*SETHOOKOFF)();

  void CHipsDlg::OnBtnOn()

  {

  在此處添加處理程序的代碼

  m_hInst = LoadLibrary(“EasyHips.dll”);

  SETHOOKON SetHookOn = (SETHOOKON)GetProcAddress(m_hInst, “SetHookOn”);

  SetHookOn(GetSafeHwnd());

  FreeLibrary(m_hInst);

  m_BtnOn.EnableWindow(FALSE);

  m_BtnOff.EnableWindow(TRUE);

  }

  void CHipsDlg::OnBtnOff()

  {

  在此處添加處理程序的代碼

  m_hInst = GetModuleHandle(“EasyHips.dll”);

  SETHOOKOFF SetHookOff = (SETHOOKOFF)GetProcAddress(m_hInst, “SetHookOff”);

  SetHookOff();

  CloseHandle(m_hInst);

  FreeLibrary(m_hInst);

  m_BtnOn.EnableWindow(TRUE);

  m_BtnOff.EnableWindow(FALSE);

  }

  從代碼中不難看出,直接調(diào)用了DLL的兩個(gè)導(dǎo)出函數(shù),就可以開啟自己的打開。在關(guān)閉時(shí)為什么調(diào)用了CloseHandle()函數(shù)和FreeLibrary()函數(shù)呢?把FreeLibrary()函數(shù)去掉,然后單擊“停止”監(jiān)控行為,但還是處在被監(jiān)控的狀態(tài)下。因?yàn)榛謴?fù)Inline Hook是在DLL被卸載的情況。因此,在卸載時(shí),調(diào)用GetModuleHandle()獲得本進(jìn)程的DLL句柄后,雖然CloseHandle()了,但是只是減少了對(duì)DLL的引用計(jì)數(shù),并沒有真正釋放,必須再次使用FreeLibrary()函數(shù)才可以使DLL被卸載,從而恢復(fù)Inline Hook。

  EXE程序接收DLL消息的代碼如下:

  BOOL CHipsDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)

  {

  // 在此處添加處理程序的代碼

  CTips Tips;

  PHIPS_INFO pHipsInfo = (PHIPS_INFO)pCopyDataStruct->lpData;

  wcscpy(Tips.sz, pHipsInfo->wProcessName);

  Tips.DoModal();

  int nNum = m_HipsReports.GetItemCount();

  CString Str;

  Str.Format(“%d”, nNum);

  m_HipsReports.InsertItem(nNum, Str);

  SYSTEMTIME StTime;

  GetLocalTime(&StTime);

  Str.Format(“%04d/%02d/%02d %02d:%02d:%02d”,

  StTime.wYear,StTime.wMonth,StTime.wDay,

  StTime.wHour,StTime.wMonth,StTime.wSecond);

  m_HipsReports.SetItemText(nNum, 1, Str);

  Str.Format(“%S”, Tips.sz);

  m_HipsReports.SetItemText(nNum, 2, Str);

  switch ( pHipsInfo->dwHipsClass )

  {

  case HIPS_CREATEPROCESS:

  {

  Str = “進(jìn)程創(chuàng)建”;

  break;

  }

  case HIPS_REGSETVALUE:

  {

  break;

  }

  case HIPS_REGDELETEVALUE:

  {

  break;

  }

  }

  m_HipsReports.SetItemText(nNum, 3, Str);

  Str.Format(“%s”, Tips.bRet ? “放行” : “攔截”);

  m_HipsReports.SetItemText(nNum, 4, Str);

  if ( Tips.bRet )

  {

  return 0;

  }

  else

  {

  return -1;

  }

  return CDialog::OnCopyData(pWnd, pCopyDataStruct);

  }

  這部分代碼就是對(duì)WM_COPYDATA消息的一個(gè)響應(yīng),整個(gè)代碼基本是對(duì)界面進(jìn)行了操作。在代碼中有一個(gè)CTips類的對(duì)象,這個(gè)類是用來自定義窗口的。該窗口就是用來提示放行和攔截的窗口,其主要代碼如下:

  void CTips::OnBtnOk()

  {

  // 在此處添加處理程序的代碼

  bRet = TRUE;

  EndDialog(0);

  }

  void CTips::OnBtnCancel()

  {

  // 在此處添加處理程序的代碼

  bRet = FALSE;

  EndDialog(0);

  }

  DLL程序中的SendMessage()函數(shù)的返回要等待WM_COPYDATA的消息結(jié)束,并從中獲得返回值來決定下一步是否執(zhí)行,因此這里只要簡(jiǎn)單地返回TRUE或FALSE即可。

  對(duì)于行為監(jiān)控就介紹這么多。這個(gè)例子演示了如何通過Inline Hook達(dá)到對(duì)進(jìn)程創(chuàng)建、注冊(cè)表操作的管控。當(dāng)然,這里的代碼并不能管控所有的進(jìn)程,而且這里的行為監(jiān)控過于簡(jiǎn)單,很容易被惡意程序突破。這里主要是通過實(shí)例來完成對(duì)行為監(jiān)控原理的介紹,希望可以起到拋磚引玉的作用。




電子技術(shù)圖片.png

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請(qǐng)及時(shí)通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。