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 ...
随机推荐
- [STL]单词转换
如果单词转换文件的内容是: 'em themcuz becausegratz grateful i Inah nopos ...
- 包含中文的字符串中截取前N个字符
package com.wangzhu.string; import java.io.UnsupportedEncodingException; public class SubStringDemo1 ...
- 安装eclipse for JavaEE 后的一些设置
以下的设置是相对于一个workspace而设置的,如果更换了workspace则要重新设置. 1. 设置Text Editors: 2. 设置Content Assist 的快捷键(比较方便) 3. ...
- import java.util.Scanner;
一.扫描控制台输入 当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,,,,,,,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象 ...
- QT里使用sqlite的问题,好多坑
1. 我使用sqlite,开发机上好好的,测试机上却不行.后来发现是缺少驱动(Driver not loaded Driver not loaded),代码检查了又检查,发现应该是缺少dll文件(系统 ...
- 如何在Android应用程序中使用传感器模拟器SensorSimulator
原文地址; 如何在Android应用程序中使用传感器模拟器 - 移动平台应用软件开发技术 - 博客频道 - CSDN.NET http://blog.csdn.net/pku_android/arti ...
- Django模型修改及数据迁移
Migrations Django中对Model进行修改是件麻烦的事情,syncdb命令仅仅创建数据库里还没有的表,它并不对已存在的数据表进行同步修改,也不处理数据模型的删除. 如果你新增或修改数据模 ...
- mac用virtualbox 装win7联网及分辨率设置
1.关掉虚拟机,进入设置 2.选择网络->NAT方式->高级->控制芯片选择 1000MT 桌面,其他默认勾选 通过安装增强功能,可以随意改变分辨率,但是系统和远程连接后,东西都被缩 ...
- Linux命令之chmod 及+s 参数(临时以所有者权限执行)
转自: http://blog.csdn.net/shaobingj126/article/details/7031221 chmod用于改变文件或目录的访问权限.用户用它控制文件或目录的访问权限.该 ...
- HTML 中的meta标签中的http-equiv与name属性使用介绍
meta是html语言head区的一个辅助性标签.也许你认为这些代码可有可无.其实如果你能够用好meta标签,会给你带来意想不到的效果,meta标签的作用有:搜索引擎优化(SEO),定义页面使用语言, ...