首页 技术 正文
技术 2022年11月17日
0 收藏 949 点赞 2,575 浏览 6450 个字

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)。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,031
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,148
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,860