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:\Windows\SysWOW64文件夹中)

好的,现在切入正题。

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

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

 typedef DWORD (WINAPI *PFNTCREATETHREADEX)
(
OUT PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID Unknown
); BOOL IsVistaOrLater()
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if( osvi.dwMajorVersion >= )
{
return TRUE;
}
return FALSE;
} BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
HANDLE hThread = NULL;
FARPROC pFunc = NULL;
if( IsVistaOrLater() ) // Vista, 7, Server2008
{
pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx");
if( pFunc == NULL )
{
ErrorReport(GetLastError());
}
((PFNTCREATETHREADEX)pFunc)(&hThread,
0x1FFFFF,
NULL,
hProcess,
pThreadProc,
pRemoteBuf,
FALSE,
NULL,
NULL,
NULL,
NULL);
if( hThread == NULL )
{
ErrorReport(GetLastError());
}
}
else // 2000, XP, Server2003
{
hThread = CreateRemoteThread(hProcess,
NULL,
,
pThreadProc,
pRemoteBuf,
,
NULL);
if( hThread == NULL )
{
ErrorReport(GetLastError());
}
}
if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
{
ErrorReport(GetLastError());
}
return TRUE;
}

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

M结构体如下构造:

 struct WinExec
{
_In_ CHAR lpCmdLine[0x400];
_In_ UINT uCmdShow;
}; struct CopyFileW
{
_In_ TCHAR lpExistingFileName[0x400];
_In_ TCHAR lpNewFileName[0x400];
_In_ BOOL bFailIfExists;
}; typedef struct _tag_info
{
DWORD time;
DWORD Return;
DWORD Info_Type; union{
struct WinExec WinExec_;
struct CopyFileW CopyFileW_;
}; }taginfo, *ptaginfo; #define WINEXEC_INFO 1
#define COPYFILEW 2

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

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

hook.h

 #pragma once

 #ifndef _M_X64
#pragma comment(lib, "EasyHook32.lib")
#else
#pragma comment(lib, "EasyHook64.lib")
#endif UINT WINAPI MyWinExec(
_In_ LPCSTR lpCmdLine,
_In_ UINT uCmdShow
); typedef UINT (WINAPI * ptrWinExec)(
_In_ LPCSTR lpCmdLine,
_In_ UINT uCmdShow
); extern ptrWinExec realWinExec; BOOL WINAPI MyCopyFileW(
_In_ LPCTSTR lpExistingFileName,
_In_ LPCTSTR lpNewFileName,
_In_ BOOL bFailIfExists
); typedef BOOL (WINAPI *ptrCopyFileW)(
_In_ LPCTSTR lpExistingFileName,
_In_ LPCTSTR lpNewFileName,
_In_ BOOL bFailIfExists
); extern ptrCopyFileW realCopyFileW;

hook.h

head.h

 #include "easyhook.h"
#include "Hook.h"
#include <Shlwapi.h>
#include <stdio.h> #pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "winmm.lib") ptrWinExec realWinExec = NULL; //真实地址
ptrCopyFileW realCopyFileW = NULL; TRACED_HOOK_HANDLE hHookWinExec = new HOOK_TRACE_INFO();
TRACED_HOOK_HANDLE hHookCopyFileW = new HOOK_TRACE_INFO(); ULONG HookWinExec_ACLEntries[] = {};
ULONG HookCopyFileW_ACLEntries[] = {}; HANDLE hNamedPipe;//命名管道句柄 DWORD StartTime = ;//应用程序起始时间 #define sizeofpipe 0x800 //管道的大小 void CreateNamedPipeInServer();//声明函数 部分内容非关键内容没有列出来
void ErrorReport(DWORD errorid);

head.h

DllMain.cpp

 #include "Header.h" 

 int PrepareRealApiEntry()
{
HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");
if (!(realWinExec = (ptrWinExec)GetProcAddress(hKernel32, "WinExec")) ||
!(realCopyFileW = (ptrCopyFileW)GetProcAddress(hKernel32, "CopyFileW")))
{
ErrorReport(GetLastError());
}
return ;
} void DoHook()
{
LhInstallHook(realWinExec, MyWinExec, NULL, hHookWinExec);
LhSetExclusiveACL(HookWinExec_ACLEntries, , hHookWinExec); LhInstallHook(realCopyFileW, MyCopyFileW, NULL, hHookCopyFileW);
LhSetExclusiveACL(HookCopyFileW_ACLEntries, , hHookCopyFileW);
} void DoneHook()
{
// this will also invalidate "hHook", because it is a traced handle...
LhUninstallAllHooks(); // this will do nothing because the hook is already removed... LhUninstallHook(hHookWinExec);
LhUninstallHook(hHookCopyFileW); // now we can safely release the traced handle
delete hHookWinExec;
hHookWinExec = NULL; delete hHookCopyFileW;
hHookCopyFileW = NULL; // even if the hook is removed, we need to wait for memory release
LhWaitForPendingRemovals();
} BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
StartTime = timeGetTime();
CreateNamedPipeInServer();
if (PrepareRealApiEntry() != )
{
return FALSE;
}
DoHook(); break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
} case DLL_PROCESS_DETACH:
{
DoneHook();
break;
}
}
return TRUE;
}

hook_fakefunction.cpp

 BOOL WINAPI MyCopyFileW( //Mystery of Panda
_In_ LPCTSTR lpExistingFileName,
_In_ LPCTSTR lpNewFileName,
_In_ BOOL bFailIfExists
)
{
//进入真实函数前,跳转到此处
bool status = false;
status = (realCopyFileW)(lpExistingFileName, lpNewFileName, bFailIfExists);//执行真正的CopyFileW函数
ptaginfo tagstruct;//上述M结构体
ZeroMemory(tagstruct, sizeof(tagstruct));
if (!(tagstruct = (ptaginfo)malloc(sizeof(_tag_info))))
{
return status;
}
HANDLE hThread;
tagstruct->time = timeGetTime() - StartTime;//填充结构体开始
tagstruct->Return = status;
tagstruct->Info_Type = COPYFILEW;
if (lpExistingFileName != NULL) //检查参数 在实际调试中发现如果不检查参数,DLL可能会崩溃
{
wcscpy(tagstruct->CopyFileW_.lpExistingFileName, lpExistingFileName);
}
else
{
free(tagstruct);
return status;
}
tagstruct->CopyFileW_.bFailIfExists = bFailIfExists;
if (lpNewFileName != NULL) //检查参数
{
wcscpy(tagstruct->CopyFileW_.lpNewFileName, lpNewFileName);
}
else
{
free(tagstruct);
return status;
}
//填充结构体完毕
hThread = CreateThread(NULL, , (LPTHREAD_START_ROUTINE)WritePipe, (ptaginfo)tagstruct, , );//创建线程发送数据到管道
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
free(tagstruct);
return status;
} UINT WINAPI MyWinExec(
_In_ LPCSTR lpCmdLine,
_In_ UINT uCmdShow
)
{
...
}

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

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

 typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY {
ULONG Attribute; // PROC_THREAD_ATTRIBUTE_XXX,参见MSDN中UpdateProcThreadAttribute的说明
SIZE_T Size; // Value的大小
ULONG_PTR Value; // 保存4字节数据(比如一个Handle)或数据指针
ULONG Unknown; // 总是0,可能是用来返回数据给调用者
} PROC_THREAD_ATTRIBUTE_ENTRY, *PPROC_THREAD_ATTRIBUTE_ENTRY; typedef struct _NT_PROC_THREAD_ATTRIBUTE_LIST {
ULONG Length; // 结构总大小
NT_PROC_THREAD_ATTRIBUTE_ENTRY Entry[];
} NT_PROC_THREAD_ATTRIBUTE_LIST, *PNT_PROC_THREAD_ATTRIBUTE_LIST;
NTSTATUS NtCreateUserProcess(
OUT PHANDLE ProcessHandle,
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK ProcessDesiredAccess,
IN ACCESS_MASK ThreadDesiredAccess,
IN POBJECT_ATTRIBUTES ProcessObjectAttributes OPTIONAL,
IN POBJECT_ATTRIBUTES ThreadObjectAttributes OPTIONAL,
IN ULONG CreateProcessFlags,
IN ULONG CreateThreadFlags,
IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
IN PVOID Parameter9,
IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList
);

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

EasyHook远注简单监控示例 z的更多相关文章

  1. Spring Cloud Hystrix理解与实践(一):搭建简单监控集群

    前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring ...

  2. 【java开发系列】—— spring简单入门示例

    1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...

  3. Springmvc整合tiles框架简单入门示例(maven)

    Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...

  4. hadoop环境安装及简单Map-Reduce示例

    说明:这篇博客来自我的csdn博客,http://blog.csdn.net/lxxgreat/article/details/7753511 一.参考书:<hadoop权威指南--第二版(中文 ...

  5. Web Service简单入门示例

    Web Service简单入门示例     我们一般实现Web Service的方法有非常多种.当中我主要使用了CXF Apache插件和Axis 2两种. Web Service是应用服务商为了解决 ...

  6. Ext简单demo示例

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  7. GDAL中MEM格式的简单使用示例

    GDAL库中提供了一种内存文件格式--MEM.如何使用MEM文件格式,主要有两种,一种是通过别的文件使用CreateCopy方法来创建一个MEM:另外一种是图像数据都已经存储在内存中了,然后使用内存数 ...

  8. html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例

    这篇文章主要介绍了html5本地存储的localstorage .本地数据库.sessionStorage简单使用示例,需要的朋友可以参考下 html5的一个非常cool的功能,就是web stora ...

  9. hydra简单使用示例

    本内容为网上收集整理,仅作为备忘!! hydra简单使用示例: 破解https: # hydra -m /index.php -l muts -P pass.txt 10.36.16.18 https ...

随机推荐

  1. POJ1426Find The Multiple

    http://poj.org/problem?id=1426 题意 : 输入一个数n,找n的倍数m,这个m所满足的条件是,每一位数只能由0或1组成,在题目的旁边用红色的注明了Special Judge ...

  2. intellij idea 12、13 win8 下 中文输入覆盖的问题(搜狗输入法或者其他输入法)

    最近升级到idea12,发现中文输入存在问题,输入中文的时候会出现空格,并且覆盖后面的字符,这个问题让我很郁闷. 假设idea的安装位置为:D:\Program Files\JetBrains\Int ...

  3. Web中的监听器【Listener】

    Servlet监听器:Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext.HttpSession和ServletRequest等域对象的创建与销毁事件,以及 ...

  4. lintcode :搜索旋转排序数组

    题目 搜索旋转排序数组 假设有一个排序的按未知的旋转轴旋转的数组(比如,0 1 2 4 5 6 7 可能成为4 5 6 7 0 1 2).给定一个目标值进行搜索,如果在数组中找到目标值返回数组中的索引 ...

  5. Python图片转换成矩阵,矩阵数据转换成图片

    # coding=gbk from PIL import Image import numpy as np # import scipy def loadImage(): # 读取图片 im = Im ...

  6. Use windows batch script to create menu

    Background Recently, I find that we need  to  type some very long gradle commands to run build, chec ...

  7. ASP.NET中App_Code,App_Data等文件夹的作用

    http://www.cnblogs.com/shiyu007/archive/2007/12/04/982264.html 1.  Bin文件夹 Bin文件夹包含应用程序所需的,用于控件.组件或者需 ...

  8. HTML5入门7---"session的会话缓存"和"localStorage的cookie"缓存数据

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  9. Android ActionBar的Overlay模式如何不遮盖顶部内容的问题

    关于actionbar的overlay模式请参考 如何让android的actionbar浮动且透明 一文.这篇文章讲的是如何在这种模式下让actionbar不遮住顶部的内容. 这 一般是这样的场景, ...

  10. Tomcat 管理页面

    一.配置刚下载的解压版的apache-tomcat,启动后,通过浏览器访问:http://127.0.0.1:8080/(或者http://localhost:8080)然后点击下图的Server s ...