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:\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的更多相关文章
- Spring Cloud Hystrix理解与实践(一):搭建简单监控集群
前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring ...
- 【java开发系列】—— spring简单入门示例
1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...
- Springmvc整合tiles框架简单入门示例(maven)
Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...
- hadoop环境安装及简单Map-Reduce示例
说明:这篇博客来自我的csdn博客,http://blog.csdn.net/lxxgreat/article/details/7753511 一.参考书:<hadoop权威指南--第二版(中文 ...
- Web Service简单入门示例
Web Service简单入门示例 我们一般实现Web Service的方法有非常多种.当中我主要使用了CXF Apache插件和Axis 2两种. Web Service是应用服务商为了解决 ...
- Ext简单demo示例
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- GDAL中MEM格式的简单使用示例
GDAL库中提供了一种内存文件格式--MEM.如何使用MEM文件格式,主要有两种,一种是通过别的文件使用CreateCopy方法来创建一个MEM:另外一种是图像数据都已经存储在内存中了,然后使用内存数 ...
- html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例
这篇文章主要介绍了html5本地存储的localstorage .本地数据库.sessionStorage简单使用示例,需要的朋友可以参考下 html5的一个非常cool的功能,就是web stora ...
- hydra简单使用示例
本内容为网上收集整理,仅作为备忘!! hydra简单使用示例: 破解https: # hydra -m /index.php -l muts -P pass.txt 10.36.16.18 https ...
随机推荐
- hdu 1370 Biorhythms
中国剩余定理……. 链接http://acm.hdu.edu.cn/showproblem.php?pid=1370 /**************************************** ...
- PHP WAMP关闭notice等提示
这是xdebug的的错误报告.在开发环境下,可以考虑将其开启,但是在部署到真实应用环境下应该将其关掉. 找到你的php.ini 在最后几行注释掉所有关于xdebug的东西,重启apache即可!
- NET 使用HtmlAgilityPack抓取网页数据
刚刚学习了XPath路径表达式,主要是对XML文档中的节点进行搜索,通过XPath表达式可以对XML文档中的节点位置进行快速定位和访问,html也是也是一种类似于xml的标记语言,但是语法没有那么严谨 ...
- Win7 下硬盘安装Linux Mint 17
下载Linux Mint 17镜像,放到C盘根目录:解压出mint.iso文件中casper目录下的vmliunz和initrd.lz两个文件,同样放在C盘的根目录里. 在Win7上安装EasyBCD ...
- JS操作Radio与Select
//radio的chang事件,以及获取选中的radio的值 $("input[name=radioName]").on("change", function( ...
- compiler 学习
一款强大的编译器LLVM:http://llvm.org/docs/GettingStarted.html#layout http://llvm.org/docs/LangRef.html http: ...
- C++Builder和VC的比较
C++Builder和VC的比较 其实很久以前我就想写这篇文章,其原因一方面是因为笔者深深感觉到C++ Builder的确是一个先进与强大的程式开发工具,但更最重要的一点是,我深信C++ Builde ...
- [leetcode] Path sum路径之和
要求给定树,与路径和,判断是否存在从跟到叶子之和为给定值的路径.比如下图中,给定路径之和为22,存在路径<5,4,11,2>,因此返回true;否则返回false. 5 / \ 4 8 / ...
- SQL效率问题
关于in和or的效率对比:http://blog.chinaunix.net/uid-20639775-id-3416737.html 在没有索引的情况下,in的效率高 SQL语句效率:http:// ...
- android rabbitMQ
http://www.cnblogs.com/wufawei/archive/2012/03/31/2427823.html http://www.raywenderlich.com/5527/get ...