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. 深入浅出ES6(四):模板字符串

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 反撇号(`)基础知识 ES6引入了一种新型的字符串字面量语法,我们称之为模板字符 ...

  2. QTP之web常用对象

    web对象是我做自动化以来最早学习,最早接触的.对现在而言也是最熟悉不过的了,但是为了以后更稳健的前进,对基础的东西搞扎实,相信以后的路会顺畅许多,下边简单汇总下web的常用几类对象: Browser ...

  3. css中的:before与:after的简单使用

    直接上代码,不多说了! 画三角形 1). <style type="text/css"> .triangle{ width: 0; height: 0; /*borde ...

  4. 李洪强iOS开发之Foundation框架—结构体

    Foundation框架—结构体 一.基本知识 Foundation—基础框架.框架中包含了很多开发中常用的数据类型,如结构体,枚举,类等,是其他ios框架的基础. 如果要想使用foundation框 ...

  5. lintcode :旋转字符串

    题目: 旋转字符串 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 样例 对于字符串 "abcdefg". offset=0 => "abcdef ...

  6. 【Linux高频命令专题(11)】cp

    概述 cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是 ...

  7. org.json和json-lib比较

    经常会用到JSON格式才处理,尤其是在Http请求的时候,网上可以找到很多json处理的相关工具,如org.json和json-lib,下面两段源代码是分别使用这两个工具解析和构造JSON的演示程序. ...

  8. BNU OJ 33691 / LA 4817 Calculator JAVA大数

    留着当个模板用,在BNU上AC,在LA上RE……可能是java的提交方式不同??? 数和运算符各开一个栈. 表达式从左到右扫一遍,将数存成大数,遇到数压在 数的栈,运算符压在 运算符的栈,每当遇到右括 ...

  9. How to learn linux device driver

    To learn device driver development, like any other new knowledge, the bestapproach for me is to lear ...

  10. IOSSelector的用法

    1.首先,@selector 里面的方法不能传参数..不要相信网上的..都是复制粘贴的.2.分三步走:1.设置tag.2.设置btn的调用方法.3.使用参数2.看示例代码把..   UIButton ...