I. Preface
Today's anti-virus software provides the "Behavior Monitoring" function. This function allows you to receive a prompt when a suspicious process is created, or when a sensitive location in the registry is written, so that you can choose whether to intercept the corresponding suspicious operations, to achieve the purpose of active defense. In this way, we can avoid the lag of traditional anti-virus software relying on signatures to scan and kill viruses. Behavior Monitoring tools can stop malicious programs when they have not yet been formally harmed.
Behavior Monitoring tools are often used when virus exclusive tools are created. For example, the well-known process monitor launched by Microsoft is a model of such tools. By monitoring the various behaviors of viruses running in virtual machines, we can take corresponding countermeasures to compile a specific killing tool (a complete set of processes based on a virus-specific killing tool, I will describe it in detail in later articles in this series ). What I wrote this time is to implement a monitoring program similar to process monitor. Of course, I will focus more on the program principle, the program actually compiled in this article cannot be compared with Process Monitor (because process monitor, on the one hand, hooks some of our uncommon functions, on the other hand, it should use some kernel-level technologies, which will be discussed in my future articles ). Of course, I believe that readers will constantly improve it and customize their own security tools.
Ii. Principles of Behavior Monitoring
The implementation of any program function must call the corresponding API function. Therefore, to monitor the program's behavior, you need to hook and analyze the called API function. I have discussed two types of Hook Technology in my previous articles. One is inline hook (for details, see article 012nd on Anti-Virus Defense: using inline hook for active defense). the other is the IAT Hook Technology (for details, see reverse engineering Article 004th: display Chinese characters in the calculator Program (below). With these two hook technologies, You can intercept the API functions in the program. The principle of behavior monitoring is to hook sensitive API functions, and then users can choose whether to intercept them, so as to prevent malicious programs from damaging our system.
Specific to this program, for the sake of simplicity of the discussion, I will only retrieve the CreateProcess () used for Process Creation () this API function (you can enrich program functions based on the principles described in this chapter ). Because hook is used, it is necessary to involve the compiling of DLL. To inject our DLL into all message-based processes, you must use Windows hooks.
It should be noted that the methods described in Article 012nd on anti-virus attack and defense: Using inlinehook for active defense only defend against one program, however, this time I plan to hook all the CreateProcess () functions in the system. This requires the global Hook method in windows. Windows provides many hooks, one of which is very useful, that is, the type of hook wh_getmessage. It can easily inject DLL files into all message-based programs to implement the functions compiled by DLL.
After the above analysis, we have made it clear that the implementation of this program requires writing a DLL program for injection, and then writing an EXE program for foreground control.
Iii. Compiling DLL programs
Here we need to create a simple win32dynamic Link Library Project, and compile the "cinlinehook. H and cinlinehook. CPP "is added to this project (For details, refer to Article 012nd on Anti-Virus Defense: using inline hook for active defense), and then add the following code:
// Easypm. CPP: defines the entry point for the DLL application. // # include "stdafx. H "# include" inlinehook. H "# include <stdio. h> # pragma data_seg (". shared ") hhook g_hhook = NULL; hwnd g_exehwnd = NULL; # pragma data_seg () # pragma comment (linker ,". shared, RWS ") extern" C "_ declspec (dllexport) void sethookon (hwnd); extern" C "_ declspec (dllexport) void sethookoff (); cinlinehook createprocesswhook; hinsta NCE g_hinst = NULL; // defines some constants to identify the type. This part can be added based on the program's perfection # define pm_createprocess 0x00000001l // defines a struct, send the information of this struct to the EXE file used to load the DLL, and let the EXE prompt typedef struct _ pm_info {wchar wprocessname [0x200]; DWORD dwpmclass;} pm_info, * ppm_info; define (_ in_opt lpwstr lpapplicationname, _ inout_opt lpwstr lpcommandline, _ in_opt lpsecurity_attributes lpprocessattributes, _ in_opt lpsecurity_attributes LPT Keys, _ in bool binherithandles, _ in DWORD dwcreationflags, _ in_opt lpvoid labels, _ in_opt lpcwstr lpcurrentdirectory, _ in begin lpstartupinfo, _ out lpprocess_information lpprocessinformation) {pm_info SZ = {0}; If (wcslen (lpcommandline )! = 0) {wcscpy (SZ. wprocessname, lpcommandline);} else {wcscpy (SZ. wprocessname, lpapplicationname);} Sz. dwpmclass = pm_createprocess; copydatastruct CDS = {null, sizeof (pm_info), (void *) & SZ}; bool Bret = false; // note that the second parameter of findwindow should be filled with "caption" in the main window of the program // The sendmessage () function here is used to send a wm_copydata message, the struct // is passed to the EXE program that loads the DLL, so that the EXE program displays the corresponding information to the user. If (sendmessage (findwindow (null, "easypm"), wm_copydata, getcurrentprocessid (), (lparam) & CDs )! =-1) {createprocesswhook. unhook (); Bret = createprocessw (lpapplicationname, lpcommandline, delimiter, delimiter, binherithandles, dwcreationflags, lpenvironment, lpcurrentdirectory, lpstartupinfo, lpprocessinformation); createprocesswhook. rehook ();} return Bret;} 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; createprocesswhook. hook ("kernel32.dll", "createprocessw", (Proc) mycreateprocessw); break;} case dll_process_detach: {createprocesswhook. unhook (); If (g_hhook! = NULL) {sethookoff () ;}break ;}return true ;}// hook function lresult callback getmsgproc (INT code, // hook code wparam, // removal option lparam // message) {return callnexthookex (g_hhook, code, wparam, lparam);} void sethookon (hwnd) {g_exehwnd = hwnd; // install the wh_getmessage hook to monitor the messages delivered to the Message Queue. setwindowshookex (wh_getmessage, getmsgproc, g_hinst, 0);} void sethookoff () {// uninstall the hook handler (g_hhook ); g_hhook = NULL ;}
The above is the code of all DLL programs. It is not complicated. I have added corresponding comments. You can add code of other API functions on this basis to monitor our system more comprehensively.
4. Creation of the Program Interface
This program requires a "list control" and three "buttons" controls:
Figure 1 Creation of the Program Interface
Then, add a variable named "m_pmreports" to the "List Control" control, and add the variables named "m_btnon" and "m_btnoff" to the "Start" and "stop" Buttons respectively. And add the following initialization code:
Typedef void (* sethookon) (hwnd); typedef void (* sethookoff) (); void ceasypmdlg: initpmreports () {counts () | lvs_ex_gridlines); counts (0, "No."); m_pmreports.insertcolumn (1, "Time"); m_pmreports.insertcolumn (2, "process"); m_pmreports.insertcolumn (3, "type"); m_pmreports.setcolumnwidth (0, 40 ); m_pmreports.setcolumnwidth (1,160); m_pmreports.setcolumnwidth (2,200); m_pmreports.setcolumnwidth (3,200);} void ceasypmdlg: onbtnon () {// todo: add your control notification handler code here m_hinst = loadlibrary ("easypm. DLL "); sethookon = (sethookon) getprocaddress (m_hinst," sethookon "); sethookon (getsafehwnd (); freelibrary (m_hinst); false ); m_btnoff.enablewindow (true);} void ceasypmdlg: onbtnoff () {// todo: add your control notification handler code here m_hinst = getmodulehandle ("easypm. DLL "); Response handler = (sethookoff) getprocaddress (m_hinst," sethookoff "); sethookoff (); closehandle (m_hinst); freelibrary (m_hinst); Response (true ); m_btnoff.enablewindow (false);} void ceasypmdlg: onbtnclear () {// todo: add your control notification handler code here m_pmreports.deleteallitems ();}
Finally, we need to declare it at the corresponding position. We will not repeat it here.
5. Write the main program
The main program is mainly used to receive DLL messages. The Code is as follows:
# Define pm_createprocess construct struct _ pm_info {wchar wprocessname [0x200]; DWORD dwpmclass;} pm_info, * ppm_info; bool metadata: oncopydata (cwnd * pwnd, copydatastruct * pcopydatastruct) {// todo: add your message handler code here and/or call default wchar SZ [2048]; ppm_info ppminfo = (ppm_info) pcopydatastruct-> lpdata; wcscpy (SZ, ppminfo-> wprocessname); int nnum = m_pmreports.getitemcount (); cstring STR; // display serial number Str. format ("% d", nnum); m_pmreports.insertitem (nnum, STR); // obtain the system time systemtime sttime; getlocaltime (& sttime); Str. format ("% 04d/% 02d/% 02d % 02d: % 02d: % 02d", sttime. wyear, sttime. wmonth, sttime. wday, sttime. whour, sttime. wmonth, sttime. wsecond); // display the time m_pmreports.setitemtext (nnum, 1, STR); // display the process name. Note that the process name must be capitalized because it is a wide character. format ("% s", SZ); m_pmreports.setitemtext (nnum, 2, STR); // display type, the case statement switch (ppminfo-> dwpmclass) {Case pm_createprocess: {STR = "CreateProcess"; break;} can be improved based on the addition of the hook function ;}} m_pmreports.setitemtext (nnum, 3, STR); Return cdialog: oncopydata (pwnd, pcopydatastruct );}
This part of the code is a response to the wm_copydata message, which is basically an operation on the interface. Because the message ing is used, you also need to declare it at the corresponding position. First, add it under begin_message_map (ceasypmdlg, cdialog:
ON_WM_COPYDATA()
Add the following content under "// {afx_msg (ceasypmdlg)" in the header file "easypmdlg. H:
afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
The above is all the code. After compilation, You can compile the link. Do not forget to put the previously compiled "easypm. dll" in the same directory as the local exe program.
6. program testing
Here, I first run the program, click the "Start" button on the interface, and then open the "Notepad", "Drawing", and "Calculator" programs in turn, as shown in:
Figure 2 monitor started programs
We can see that our program has successfully monitored all open programs. It should be noted that the 4th programs are the QQ tools I use.
VII. SummaryOur code cannot monitor all processes, and our programs are too simple to be broken by malicious programs. However, this program is just a prototype, and I hope it can serve as a reference. This program can also be added to the process Interception Function. Interested readers can complete it on their own.
007th security tools: Development of behavior monitoring tools