专栏名称: 计算机与网络安全
信息安全公益宣传,信息安全知识启蒙。
目录
相关文章推荐
命里有票  ·  用DeepSeek和豆包分别计算了一个日期问 ... ·  昨天  
命里有票  ·  用DeepSeek和豆包分别计算了一个日期问 ... ·  昨天  
话沈阳  ·  京东、美团、饿了么相继官宣! ·  昨天  
话沈阳  ·  京东、美团、饿了么相继官宣! ·  昨天  
兵团零距离  ·  十二师政府产业引导母基金正式成立 ·  昨天  
兵团零距离  ·  十二师政府产业引导母基金正式成立 ·  昨天  
51好读  ›  专栏  ›  计算机与网络安全

网络安全编程:行为监控HIPS

计算机与网络安全  · 公众号  · 互联网安全  · 2021-06-13 08:58

正文

一次性 付费 进群, 长期 免费 索取资料。

回复公众号: 微信群 可查看进群流程。


微信公众号:计算机与网络安全

ID:Computer-network


现在有一种流行的防病毒软件被称作HIPS,中文名字为主机入侵防御系统,比如EQ。该软件可以在进程创建时、有进程对注册表进行写入时或有驱动被加载时,给用户予以选择,选择是否拦截进程的创建、是否拦截注册表的写入、是否拦截驱动的加载等功能。

HIPS纯粹是以预防为主,比如有陌生的进程在被创建阶段,就可以让用户禁止,这样就避免了特征码查杀的滞后性。对于杀毒软件的特征码查杀而言,如果杀毒软件不更新病毒数据库,那么依赖病毒特征码的杀毒软件就无法查杀新型的病毒,对新型的病毒就成为一个摆设。

行为监控的原理主要就是对相关的关键API函数进行HOOK,比如进程拦截。当一个木马程序要秘密启动的时候,对CreateProcessW()函数进行了HOOK,在进程被创建前,会询问用户是否启动该进程,那么木马的隐秘启动就被暴露出来了。对于没有安全知识的大众来说,使用HIPS可能有点困难,也许仍然会让木马运行。因为不是每个使用计算机的人都对计算机有所了解,计算机对于他们而言可能只用来打游戏或看电影。这该如何做呢?现在通常使用的方法就是使用白库和黑库,也就是所谓的白名单和黑名单。在进程被创建时,把要创建的进程到黑白库中去匹配,然后做相应的动作,或者放行,或者拦截。

下面来实现一个应用层下的简单的进程防火墙、注册表防火墙的功能。

1. 简单进程防火墙

进程防火墙指的是放行/拦截准备要创建的进程。进程的创建是依靠CreateProcessW()函数完成的。只要HOOK CreateProcessW()函数就可以实现进程防火墙的功能。对于注册表来说,要对非法进程进行删除或写入注册表键值进行管控,因此需要HOOK两个注册表函数,分别是注册表写入函数RegSetValueExW()和注册表删除函数RegDeleteValueW()。由于使用了HOOK,那么就必然要涉及DLL的编写。这里分DLL和EXE两部分来进行详细的介绍。

2. 实现HOOK部分的DLL程序的编写

因为要对目标进程进行HOOK,因此要编写DLL程序。创建一个DLL程序,并加入已封装的ILHook.h头文件和ILHook.cpp的实现文件。

为了能在所有的基于消息的进程中注入自己的DLL,必须使用Windows钩子,这样就可以将DLL轻易地注入基于消息的进程中。代码如下:
#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, // 移除选项 LPARAM lParam // 消息 ){ 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;}
以上函数用来定义导出函数,用于加载完成HOOK功能的DLL文件。这里利用WH_ GETMESSAGE钩子类型。

定义3个CILHook类的对象,分别用来对CreateProcessW()函数、RegSetValueExW()函数和RegDeleteValueW()函数进行挂钩。具体定义如下:
CILHook RegSetValueExWHook;CILHook CreateProcessWHook;CILHook RegDeleteValueWHook;
HOOK部分是在DllMain()函数中完成的,具体代码如下:
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;}
放行/拦截部分是给用户选择的,那么就要给出提示让用户进行选择,至少要给出放行/拦截的类型,比如是注册表写入或是进程的创建,还要给出是哪个进程进行的操作。要把这个信息反馈给用户,这里定义一个结构体,将该结构体的信息发送给用于加载DLL的EXE文件,并让EXE给出提示。结构体定义如下:
typedef struct _HIPS_INFO{ WCHAR wProcessName[0x200]; DWORD dwHipsClass;}HIPS_INFO, *PHIPS_INFO;
定义一些常量用来标识放行/拦截的类型,具体如下:
#define HIPS_CREATEPROCESS 0x00000001L#define HIPS_REGSETVALUE 0x00000002L#define HIPS_REGDELETEVALUE 0x00000003L
将这些定义好以后,就可以开始完成HOOK函数了。这里主要给出CreateProcessW()函数的HOOK实现。其余两个函数的HOOK实现,请大家自行实现。具体代码如下:
BOOLWINAPIMyCreateProcessW( __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;}
这里使用了一个SendMessage()函数,该函数用来发送一个WM_COPYDATA消息,将结构体传给了加载DLL的EXE程序,使EXE程序把提示显示给用户。

SendMessage()函数的功能非常强大,其定义如下:
LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
该函数的第一个参数是目标窗口的句柄,第二个参数是消息类型,最后两个参数是消息的附加参数,根据消息类型的不同而不同。
以上代码就是DLL程序的全部了,剩下两个对注册表操作的HOOK函数,由大家自己完成。

3. 行为监控前台程序的编写

先来看一下程序能达到的效果,再讲解程序EXE部分的实现代码,如图1和图2所示。
图1  程序主界面

图2  拦截提示框

从上面两个图可以看出,程序的确是可以拦截进程的启动的。当单击“允许”按钮后,进程会被正常创建;当单击“取消”按钮后,进程将被阻止创建。这就是最终要完成的功能,来看看主要的实现代码。

EXE的部分主要就是如何来启动行为监控功能,以及如何接收DLL程序通过SendMessage()函数发出的消息给用户弹出提示框。进行拦截的部分已经在DLL程序中通过HOOK实现了,所以重点也就在界面上和消息的接收上。

先看如何启动和停止行为的监控。具体代码如下:
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");






请到「今天看啥」查看全文