zoukankan      html  css  js  c++  java
  • EasyHook远注简单监控示例 z

    http://www.csdn 123.com/html/itweb/20130827/83559_83558_83544.htm

    免费开源库EasyHook(inline hook),下面是下载地址

    http://easyhook.codeplex.com/releases/view/24401 把头文件 lib文件全拷贝在工程文件夹中,把dll拷贝在%system32%中(PS:

    64位 应该放在C:WindowsSysWOW64文件夹中)

    好的,现在切入正题。

    假设我们的工程是要监控Troj.exe的行为。A.exe为监控应用程序,A.exe先遍历当前进程,若找到Troj.exe则将B.dll远程线程注入到Troj.exe进程中

    PS: XP CreateRemoteThread win7用NT系列函数,如下:

     1 typedef DWORD (WINAPI *PFNTCREATETHREADEX)  
     2     (   
     3     OUT PHANDLE             ThreadHandle,     
     4     ACCESS_MASK             DesiredAccess,    
     5     LPVOID                  ObjectAttributes,     
     6     HANDLE                  ProcessHandle,    
     7     LPTHREAD_START_ROUTINE  lpStartAddress,   
     8     LPVOID                  lpParameter,      
     9     BOOL                    CreateSuspended,      
    10     DWORD                   dwStackSize,      
    11     DWORD                   dw1,   
    12     DWORD                   dw2,   
    13     LPVOID                  Unknown   
    14     );   
    15 
    16 BOOL IsVistaOrLater()  
    17 {  
    18     OSVERSIONINFO osvi;  
    19     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));  
    20     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
    21     GetVersionEx(&osvi);  
    22     if( osvi.dwMajorVersion >= 6 )  
    23     {
    24         return TRUE;  
    25     }
    26     return FALSE;  
    27 }  
    28 
    29 BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)  
    30 {  
    31     HANDLE      hThread = NULL;  
    32     FARPROC     pFunc = NULL;  
    33     if( IsVistaOrLater() )    // Vista, 7, Server2008  
    34     {  
    35         pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx");  
    36         if( pFunc == NULL )  
    37         {  
    38             ErrorReport(GetLastError()); 
    39         }  
    40         ((PFNTCREATETHREADEX)pFunc)(&hThread,  
    41             0x1FFFFF,  
    42             NULL,  
    43             hProcess,  
    44             pThreadProc,  
    45             pRemoteBuf,  
    46             FALSE,  
    47             NULL,  
    48             NULL,  
    49             NULL,  
    50             NULL);  
    51         if( hThread == NULL )  
    52         {  
    53             ErrorReport(GetLastError());
    54         }  
    55     }  
    56     else                    // 2000, XP, Server2003  
    57     {  
    58         hThread = CreateRemoteThread(hProcess,   
    59             NULL,   
    60             0,   
    61             pThreadProc,   
    62             pRemoteBuf,   
    63             0,   
    64             NULL);  
    65         if( hThread == NULL )  
    66         {  
    67             ErrorReport(GetLastError()); 
    68         }  
    69     }  
    70     if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )  
    71     {  
    72         ErrorReport(GetLastError());
    73     }  
    74     return TRUE;  
    75 }   

    注入成功后,DLL和A.exe建立命名管道进行进程间通信。例如,当Troj.exe调用CopyFileW被B.dll拦载时,发送相关数据(简称为M结构体)到A.exe文本控件上显示。

    M结构体如下构造:

     1 struct WinExec
     2 {
     3     _In_  CHAR lpCmdLine[0x400];
     4     _In_  UINT uCmdShow;
     5 };
     6 
     7 struct CopyFileW
     8 {
     9     _In_  TCHAR lpExistingFileName[0x400];
    10     _In_  TCHAR lpNewFileName[0x400];
    11     _In_  BOOL bFailIfExists;
    12 };
    13 
    14 typedef struct _tag_info
    15 {
    16     DWORD time;
    17     DWORD Return;
    18     DWORD Info_Type;
    19 
    20     union{
    21         struct WinExec WinExec_;
    22         struct CopyFileW CopyFileW_;
    23     };
    24 
    25 }taginfo, *ptaginfo;
    26 
    27 #define WINEXEC_INFO 1
    28 #define COPYFILEW 2

    我的这个实例很基础,就拦载Winexec函数和CopyFileW函数

    请先允许我展示几个头文件 

     hook.h

     1 #pragma once
     2 
     3 
     4 #ifndef _M_X64
     5 #pragma comment(lib, "EasyHook32.lib")
     6 #else
     7 #pragma comment(lib, "EasyHook64.lib")
     8 #endif
     9 
    10 UINT WINAPI MyWinExec(
    11     _In_  LPCSTR lpCmdLine,
    12     _In_  UINT uCmdShow
    13     );
    14 
    15 typedef UINT (WINAPI * ptrWinExec)(
    16     _In_  LPCSTR lpCmdLine,
    17     _In_  UINT uCmdShow
    18     );
    19 
    20 extern ptrWinExec realWinExec;
    21 
    22 BOOL WINAPI MyCopyFileW(
    23     _In_  LPCTSTR lpExistingFileName,
    24     _In_  LPCTSTR lpNewFileName,
    25     _In_  BOOL bFailIfExists
    26     );
    27 
    28 typedef BOOL (WINAPI *ptrCopyFileW)(
    29     _In_  LPCTSTR lpExistingFileName,
    30     _In_  LPCTSTR lpNewFileName,
    31     _In_  BOOL bFailIfExists
    32     );
    33 
    34 extern ptrCopyFileW realCopyFileW;
    hook.h

     head.h

     1 #include "easyhook.h"  
     2 #include "Hook.h"
     3 #include <Shlwapi.h>
     4 #include <stdio.h>
     5 
     6 #pragma comment(lib, "Shlwapi.lib")
     7 #pragma comment(lib, "winmm.lib")
     8 
     9 ptrWinExec              realWinExec = NULL; //真实地址
    10 ptrCopyFileW            realCopyFileW   = NULL;
    11 
    12 TRACED_HOOK_HANDLE      hHookWinExec = new HOOK_TRACE_INFO();
    13 TRACED_HOOK_HANDLE      hHookCopyFileW   = new HOOK_TRACE_INFO();
    14 
    15 ULONG                   HookWinExec_ACLEntries[1]   = {0};
    16 ULONG                   HookCopyFileW_ACLEntries[1]   = {0};
    17 
    18 HANDLE                  hNamedPipe;//命名管道句柄
    19 
    20 DWORD StartTime = 0;//应用程序起始时间
    21 
    22 #define sizeofpipe 0x800 //管道的大小
    23 
    24 void CreateNamedPipeInServer();//声明函数 部分内容非关键内容没有列出来
    25 void ErrorReport(DWORD errorid);
    head.h

    DllMain.cpp

     1 #include "Header.h" 
     2 
     3 int PrepareRealApiEntry()  
     4 {  
     5     HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");  
     6     if (!(realWinExec = (ptrWinExec)GetProcAddress(hKernel32, "WinExec")) ||
     7         !(realCopyFileW = (ptrCopyFileW)GetProcAddress(hKernel32, "CopyFileW")))
     8     {
     9         ErrorReport(GetLastError());
    10     }
    11     return 0;
    12 } 
    13 
    14 void DoHook()  
    15 {  
    16      LhInstallHook(realWinExec, MyWinExec, NULL, hHookWinExec);
    17      LhSetExclusiveACL(HookWinExec_ACLEntries, 1, hHookWinExec);
    18 
    19      LhInstallHook(realCopyFileW,  MyCopyFileW, NULL, hHookCopyFileW);
    20      LhSetExclusiveACL(HookCopyFileW_ACLEntries, 1, hHookCopyFileW);
    21 }  
    22 
    23 void DoneHook()  
    24 {  
    25     // this will also invalidate "hHook", because it is a traced handle...  
    26     LhUninstallAllHooks();  
    27 
    28     // this will do nothing because the hook is already removed...  
    29 
    30     LhUninstallHook(hHookWinExec);
    31     LhUninstallHook(hHookCopyFileW);
    32 
    33     // now we can safely release the traced handle  
    34     delete hHookWinExec;
    35     hHookWinExec = NULL;
    36 
    37     delete hHookCopyFileW;
    38     hHookCopyFileW = NULL;
    39 
    40     // even if the hook is removed, we need to wait for memory release  
    41     LhWaitForPendingRemovals();  
    42 }  
    43 
    44 BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )  
    45 {  
    46     switch (ul_reason_for_call)  
    47     {  
    48     case DLL_PROCESS_ATTACH:  
    49         {  
    50             StartTime = timeGetTime();
    51             CreateNamedPipeInServer(); 
    52             if (PrepareRealApiEntry() != 0)  
    53             {  
    54                 return FALSE;  
    55             }  
    56             DoHook();  
    57 
    58             break;  
    59         }  
    60     case DLL_THREAD_ATTACH:  
    61         {  
    62             break;  
    63         }  
    64     case DLL_THREAD_DETACH:  
    65         {  
    66             break;  
    67         }  
    68 
    69     case DLL_PROCESS_DETACH:  
    70         {  
    71             DoneHook();  
    72             break;  
    73         }  
    74     }  
    75     return TRUE;  
    76 }

    hook_fakefunction.cpp

     1 BOOL WINAPI MyCopyFileW( //Mystery of Panda
     2     _In_  LPCTSTR lpExistingFileName,
     3     _In_  LPCTSTR lpNewFileName,
     4     _In_  BOOL bFailIfExists
     5     )
     6 {
     7     //进入真实函数前,跳转到此处
     8     bool status = false;
     9     status = (realCopyFileW)(lpExistingFileName, lpNewFileName, bFailIfExists);//执行真正的CopyFileW函数
    10     ptaginfo tagstruct;//上述M结构体
    11     ZeroMemory(tagstruct, sizeof(tagstruct));
    12     if (!(tagstruct = (ptaginfo)malloc(sizeof(_tag_info))))
    13     {
    14         return status;
    15     }
    16     HANDLE hThread;
    17     tagstruct->time = timeGetTime() - StartTime;//填充结构体开始
    18     tagstruct->Return = status;
    19     tagstruct->Info_Type = COPYFILEW;
    20     if (lpExistingFileName != NULL) //检查参数 在实际调试中发现如果不检查参数,DLL可能会崩溃
    21     {
    22         wcscpy(tagstruct->CopyFileW_.lpExistingFileName, lpExistingFileName);
    23     }
    24     else
    25     {
    26         free(tagstruct);
    27         return status;
    28     }
    29     tagstruct->CopyFileW_.bFailIfExists = bFailIfExists;
    30     if (lpNewFileName != NULL) //检查参数
    31     {
    32         wcscpy(tagstruct->CopyFileW_.lpNewFileName, lpNewFileName);
    33     }
    34     else
    35     {
    36         free(tagstruct);
    37         return status;
    38     }
    39     //填充结构体完毕
    40     hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WritePipe, (ptaginfo)tagstruct, 0, 0);//创建线程发送数据到管道
    41     if (hThread)
    42     {
    43         WaitForSingleObject(hThread, INFINITE);
    44         CloseHandle(hThread);
    45     }
    46     free(tagstruct);
    47     return status;
    48 } 49 50 UINT WINAPI MyWinExec( 51 _In_ LPCSTR lpCmdLine, 52 _In_ UINT uCmdShow 53 ) 54 { 55 ... 56 }

    至此,这个简单监控示例就完成了。

    题外话:这只是应用层的最简单的钩子,可以轻易的被绕过。如果在应用层上想做的更深一点,例如监控troj.exe的进程创建,可以考虑钩R3上的NtCreateUserProcess函数,下面是网上逆出来的函数参数

     1 typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY {
     2     ULONG Attribute;    // PROC_THREAD_ATTRIBUTE_XXX,参见MSDN中UpdateProcThreadAttribute的说明
     3     SIZE_T Size;        // Value的大小
     4     ULONG_PTR Value;    // 保存4字节数据(比如一个Handle)或数据指针
     5     ULONG Unknown;      // 总是0,可能是用来返回数据给调用者
     6 } PROC_THREAD_ATTRIBUTE_ENTRY, *PPROC_THREAD_ATTRIBUTE_ENTRY;
     7 
     8 typedef struct _NT_PROC_THREAD_ATTRIBUTE_LIST {
     9     ULONG Length;       // 结构总大小
    10     NT_PROC_THREAD_ATTRIBUTE_ENTRY Entry[1];
    11 } NT_PROC_THREAD_ATTRIBUTE_LIST, *PNT_PROC_THREAD_ATTRIBUTE_LIST;
    12 NTSTATUS NtCreateUserProcess(
    13     OUT PHANDLE ProcessHandle,
    14     OUT PHANDLE ThreadHandle,
    15     IN ACCESS_MASK ProcessDesiredAccess,
    16     IN ACCESS_MASK ThreadDesiredAccess,
    17     IN POBJECT_ATTRIBUTES ProcessObjectAttributes OPTIONAL,
    18     IN POBJECT_ATTRIBUTES ThreadObjectAttributes OPTIONAL,
    19     IN ULONG CreateProcessFlags,
    20     IN ULONG CreateThreadFlags,
    21     IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
    22     IN PVOID Parameter9,
    23     IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList
    24 );

    不过只能作为统计创建进程数,不能在应用层上得到创建的进程信息(INVALID_HANDLE_VALUE)。

  • 相关阅读:
    [转]windows下mysql配置文件my.ini的位置
    [转]Oracle 11g不能导出空表的多种解决方法
    [转]ORACLE WITH AS 用法(相当于查询开始前构造临时表,提高效率)
    [转]基于WordPress的微信小程序支付功能开发
    从数据库优化到治病(2)治好心悸过程
    算命三十多年的资深命理师的人生感悟!
    从高维度看世界
    鸾书精华
    实用QPS和TPS高的高效分析方法
    windows 安装 mysql
  • 原文地址:https://www.cnblogs.com/zeroone/p/3754758.html
Copyright © 2011-2022 走看看