EasyHook远程代码注入
最近一段时间由于使用MinHook的API挂钩不稳定,经常因为挂钩地址错误而导致宿主进程崩溃。听同事介绍了一款智能强大的挂钩引擎EasyHook。它比微软的detours好的一点是它的x64注入支持是免费开源的。不想微软的detours,想搞x64还得购买。
好了,闲话不多说,先下载EasyHook的开发库,当然有兴趣的同学可以下载源码进行学习。下载地址:http://easyhook.codeplex.com/releases/view/24401。我给的这个是2.6版本的。
EasyHook提供了两种模式的注入管理。一种是托管代码的注入,另一种是非托管代码的注入。我是学习C++的,所以直接学习了例子中的非托管项目UnmanagedHook。里面给了一个简单的挂钩MessageBeep API的示例。我需要将其改造成支持远程注入的。下面先给出钩子DLL代码:
- // dllmain.cpp : 定义 DLL 应用程序的入口点。
- #include "stdafx.h"
- #include "HookApi.h"
- #include "easyhook.h"
- #include "ntstatus.h"
- ptrCreateFileW realCreateFileW = NULL;
- ptrCreateFileA realCreateFileA = NULL;
- HMODULE hKernel32 = NULL;
- TRACED_HOOK_HANDLE hHookCreateFileW = new HOOK_TRACE_INFO();
- TRACED_HOOK_HANDLE hHookCreateFileA = new HOOK_TRACE_INFO();
- NTSTATUS statue;
- ULONG HookCreateFileW_ACLEntries[1] = {0};
- ULONG HookCreateFileA_ACLEntries[1] = {0};
- int PrepareRealApiEntry()
- {
- OutputDebugString(L"PrepareRealApiEntry()\n");
- // 获取真实函数地址
- HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");
- if (hKernel32 == NULL)
- {
- OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") Error\n");
- return -6002;
- }
- OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") OK\n");
- realCreateFileW = (ptrCreateFileW)GetProcAddress(hKernel32, "CreateFileW");
- if (realCreateFileW == NULL)
- {
- OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") Error\n");
- return -6007;
- }
- OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") OK\n");
- realCreateFileA = (ptrCreateFileA)GetProcAddress(hKernel32, "CreateFileA");
- if (realCreateFileA == NULL)
- {
- OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") Error\n");
- return -6007;
- }
- OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") OK\n");
- return 0;
- }
- void DoHook()
- {
- OutputDebugString(L"DoHook()\n");
- statue = LhInstallHook(realCreateFileW,
- MyCreateFileW,
- /*(PVOID)0x12345678*/NULL,
- hHookCreateFileW);
- if(!SUCCEEDED(statue))
- {
- switch (statue)
- {
- case STATUS_NO_MEMORY:
- OutputDebugString(L"STATUS_NO_MEMORY\n");
- break;
- case STATUS_NOT_SUPPORTED:
- OutputDebugString(L"STATUS_NOT_SUPPORTED\n");
- break;
- case STATUS_INSUFFICIENT_RESOURCES:
- OutputDebugString(L"STATUS_INSUFFICIENT_RESOURCES\n");
- break;
- default:
- WCHAR dbgstr[512] = {0};
- wsprintf(dbgstr, L"%d\n", statue);
- OutputDebugString(dbgstr);
- }
- OutputDebugString(L"LhInstallHook(GetProcAddress(hKernel32, \"CreateFileW\"),MyCreateFileW,(PVOID)0x12345678,hHookCreateFileW); Error\n");
- return;
- }
- OutputDebugString(L"Hook CreateFileW OK\n");
- statue = LhInstallHook(realCreateFileA,
- MyCreateFileA,
- /*(PVOID)0x12345678*/NULL,
- hHookCreateFileA);
- if(!SUCCEEDED(statue))
- {
- switch (statue)
- {
- case STATUS_NO_MEMORY:
- OutputDebugString(L"STATUS_NO_MEMORY\n");
- break;
- case STATUS_NOT_SUPPORTED:
- OutputDebugString(L"STATUS_NOT_SUPPORTED\n");
- break;
- case STATUS_INSUFFICIENT_RESOURCES:
- OutputDebugString(L"STATUS_INSUFFICIENT_RESOURCES\n");
- break;
- default:
- WCHAR dbgstr[512] = {0};
- wsprintf(dbgstr, L"%d\n", statue);
- OutputDebugString(dbgstr);
- }
- OutputDebugString(L"LhInstallHook(GetProcAddress(hKernel32, \"CreateFileA\"),MyCreateFileA,(PVOID)0x12345678,hHookCreateFileA); Error\n");
- return;
- }
- OutputDebugString(L"Hook CreateFileA OK\n");
- // 一定要调用这个函数,否则注入的钩子无法正常运行。
- LhSetExclusiveACL(HookCreateFileA_ACLEntries, 1, hHookCreateFileA);
- LhSetExclusiveACL(HookCreateFileW_ACLEntries, 1, hHookCreateFileW);
- }
- void DoneHook()
- {
- OutputDebugString(L"DoneHook()\n");
- // this will also invalidate "hHook", because it is a traced handle...
- LhUninstallAllHooks();
- // this will do nothing because the hook is already removed...
- LhUninstallHook(hHookCreateFileA);
- LhUninstallHook(hHookCreateFileW);
- // now we can safely release the traced handle
- delete hHookCreateFileA;
- hHookCreateFileA = NULL;
- delete hHookCreateFileW;
- hHookCreateFileW = 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:
- {
- OutputDebugString(L"DllMain::DLL_PROCESS_ATTACH\n");
- // 准备好原始地址与目的地址
- int errCode = PrepareRealApiEntry();
- if (errCode != 0)
- {
- OutputDebugString(L"PrepareRealApiEntry() Error\n");
- return FALSE;
- }
- // 开始挂钩
- DoHook();
- break;
- }
- case DLL_THREAD_ATTACH:
- {
- OutputDebugString(L"DllMain::DLL_THREAD_ATTACH\n");
- break;
- }
- case DLL_THREAD_DETACH:
- {
- OutputDebugString(L"DllMain::DLL_THREAD_DETACH\n");
- break;
- }
- case DLL_PROCESS_DETACH:
- {
- OutputDebugString(L"DllMain::DLL_PROCESS_DETACH\n");
- // 卸载钩子
- DoneHook();
- break;
- }
- }
- return TRUE;
- }
- <pre name="code" class="cpp">// HookSvr.cpp
- #include "stdafx.h"
- #include "HookApi.h"
- #include "easyhook.h"
- HANDLE WINAPI MyCreateFileW(
- __in LPCWSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- )
- {
- HANDLE hHandle = NULL;
- // 执行钩子
- if (realCreateFileW == NULL)
- {
- OutputDebugString(L"realCreateFileW is NULL\n");
- return INVALID_HANDLE_VALUE;
- }
- else
- {
- OutputDebugString(L"realCreateFileW is not NULL\n");
- hHandle = (realCreateFileW)(lpFileName, dwDesiredAccess, dwShareMode,
- lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
- OutputDebugString(L"MyCreateFileW : ");
- OutputDebugString(lpFileName);
- OutputDebugString(L"\n");
- }
- return hHandle;
- }
- HANDLE WINAPI MyCreateFileA(
- __in LPCSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- )
- {
- HANDLE hHandle = NULL;
- // 执行钩子
- if (realCreateFileA == NULL)
- {
- OutputDebugString(L"realCreateFileA is NULL\n");
- return INVALID_HANDLE_VALUE;
- }
- else
- {
- OutputDebugString(L"realCreateFileA is not NULL\n");
- hHandle = (realCreateFileA)(lpFileName, dwDesiredAccess, dwShareMode,
- lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
- OutputDebugString(L"MyCreateFileW : ");
- OutputDebugStringA(lpFileName);
- OutputDebugString(L"\n");
- }
- return hHandle;
- }</pre><br>
- 钩子这一部分我弄了比较久,主要是API不熟悉,不过好在弄好了。
- <pre></pre>
- <p><br>
- </p>
- <p></p><pre name="code" class="cpp">// HookSvr.h
- #pragma once
- #include <Windows.h>
- #ifndef _M_X64
- #pragma comment(lib, "EasyHook32.lib")
- #else
- #pragma comment(lib, "EasyHook64.lib")
- #endif
- HANDLE WINAPI MyCreateFileW(
- __in LPCWSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- );
- typedef HANDLE (WINAPI *ptrCreateFileW)(
- __in LPCWSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- );
- extern ptrCreateFileW realCreateFileW;
- HANDLE WINAPI MyCreateFileA(
- __in LPCSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- );
- typedef HANDLE (WINAPI *ptrCreateFileA)(
- __in LPCSTR lpFileName,
- __in DWORD dwDesiredAccess,
- __in DWORD dwShareMode,
- __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- __in DWORD dwCreationDisposition,
- __in DWORD dwFlagsAndAttributes,
- __in_opt HANDLE hTemplateFile
- );
- extern ptrCreateFileA realCreateFileA;</pre><br>
- <br>
- <p></p>
- <p>接下来是注入工具,这里指提供核心代码。本来EasyHook还提供了一个叫<span style="color:black">Rh</span>InjectLibrary()方法直接注入,这种方法相当稳定,推荐使用。我本来也用它,但是发现注入会失败,所以就采用了比较通用的远程注入代码,如下:</p>
- <pre name="code" class="cpp">BOOL RtlFileExists(WCHAR* InPath)
- {
- HANDLE hFile;
- if((hFile = CreateFileW(InPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
- return FALSE;
- CloseHandle(hFile);
- return TRUE;
- }
- BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
- {
- TOKEN_PRIVILEGES tp;
- HANDLE hToken;
- LUID luid;
- if( !OpenProcessToken(GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
- &hToken) )
- {
- return FALSE;
- }
- if( !LookupPrivilegeValue(NULL, // lookup privilege on local system
- lpszPrivilege, // privilege to lookup
- &luid) ) // receives LUID of privilege
- {
- return FALSE;
- }
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Luid = luid;
- if( bEnablePrivilege )
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- else
- tp.Privileges[0].Attributes = 0;
- // Enable the privilege or disable all privileges.
- if( !AdjustTokenPrivileges(hToken,
- FALSE,
- &tp,
- sizeof(TOKEN_PRIVILEGES),
- (PTOKEN_PRIVILEGES) NULL,
- (PDWORD) NULL) )
- {
- return FALSE;
- }
- if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
- {
- //The token does not have the specified privilege.
- return FALSE;
- }
- return TRUE;
- }
- typedef DWORD (WINAPI *PFNTCREATETHREADEX)
- (
- 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 MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
- {
- HANDLE hThread = NULL;
- FARPROC pFunc = NULL;
- BOOL bHook;
- // 判断系统版本
- OSVERSIONINFO osvi;
- //BOOL bIsWindowsXPorLater;
- ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&osvi);
- if (osvi.dwMajorVersion == 6)
- {
- bHook = TRUE;
- }
- else
- {
- bHook = FALSE;
- }
- if(bHook) // Vista, 7, Server2008
- {
- pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateThreadEx");
- if( pFunc == NULL )
- {
- //GetLastError());
- return FALSE;
- }
- OutputDebugString(L"MyCreateRemoteThread");
- ((PFNTCREATETHREADEX)pFunc)(&hThread,
- 0x1FFFFF,
- NULL,
- hProcess,
- pThreadProc,
- pRemoteBuf,
- FALSE,
- NULL,
- NULL,
- NULL,
- NULL);
- if( hThread == NULL )
- {
- return FALSE;
- }
- }
- else // 2000, XP, Server2003
- {
- hThread = CreateRemoteThread(hProcess,
- NULL,
- 0,
- pThreadProc,
- pRemoteBuf,
- 0,
- NULL);
- if( hThread == NULL )
- {
- return FALSE;
- }
- }
- if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
- {
- return FALSE;
- }
- return TRUE;
- }
- BOOL InjectDll(DWORD dwPID, const wchar_t *szDllName)
- {
- HANDLE hProcess = NULL;
- LPVOID pRemoteBuf = NULL;
- FARPROC pThreadProc = NULL;
- DWORD dwBufSize = wcslen(szDllName)*sizeof(wchar_t)+2;
- if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
- {
- return FALSE;
- }
- pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
- MEM_COMMIT, PAGE_READWRITE);
- WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,
- dwBufSize, NULL);
- pThreadProc = GetProcAddress(GetModuleHandle(L"kernel32.dll"),
- "LoadLibraryW");
- if( !MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pThreadProc, pRemoteBuf) )
- {
- return FALSE;
- }
- VirtualFreeEx(hProcess, pRemoteBuf, dwBufSize, MEM_RELEASE);
- CloseHandle(hProcess);
- return TRUE;
- }
- int DoInject(DWORD aPid, const WCHAR *aFullpath)
- {
- if (wcslen(aFullpath) <= 0)
- {
- return -1;
- }
- //判断dll是否存在
- HANDLE hFile = CreateFile(aFullpath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if(hFile != INVALID_HANDLE_VALUE)
- {
- DWORD dwsize = GetFileSize(hFile, NULL);
- CloseHandle(hFile);
- if (dwsize < 10)
- {
- return -2;
- }
- }
- else
- {
- return -3;
- }
- BOOL bSuc=SetPrivilege(SE_DEBUG_NAME, TRUE);
- bSuc=InjectDll((DWORD)aPid, aFullpath);
- if (bSuc)
- {
- return -4;
- }
- return 0;
- }
- // 真实注入的时候应该这样调用
- DoInject(m_processId, L"E:\\src\\easyhook\\trunk\\Debug\\x86\\HookSvr.dll");
- </pre><br>
- 这样就能保证注入的钩子能正常工作了。
EasyHook远程代码注入相关推荐
- 远程代码注入及DLL注入教程(InlineHook)---植物大战僵尸为例
远程代码注入及DLL注入教程 说明 本人刚开始学习逆向,不知道有没有动力学下深去,这一块也没有详细的实战教学,学多少就上传多少,希望能给想学的朋友一点帮助吧,本教程想通过植物大战僵尸这一经典游戏来 ...
- Apache Log4j 远程代码注入漏洞
漏洞说明 2021年12月9日,Apache Log4j2 Java 日志模块存在远程命令执行漏洞可直接控制目标服务器问题,攻击者攻击难度极低.由于 Apache Log4j2 某些功能存在递归解析功 ...
- java远程代码注入_Java RMI远程反序列化任意类及远程代码执行解析(CVE-2017-3241 )...
原标题:Java RMI远程反序列化任意类及远程代码执行解析(CVE-2017-3241 ) 本打算慢慢写出来的,但前几天发现国外有研究员发了一篇关于这个CVE的文章,他和我找到的地方很相似.然而不知 ...
- [免费专栏] Android安全之利用JDB调试Android应用程序(动态代码注入技术)
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...
- 代码注入之远程线程篇
引子 前些日子由于项目要求,在网上到处找资料,于无意中发现了 CodeProject 上的一篇很老的文章,文章标题为: Three Ways to Inject Your Code into Anot ...
- 【Android 逆向】Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )
文章目录 一.进程注入原理 二.远程调用流程 ( 获取 so 动态库地址 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 ) 一.进程注入原理 调试进程 At ...
- XXE漏洞利用技巧(XML注入):从XML到远程代码执行
目录 什么是XXE 基本利用 Blind OOB XXE 场景1 - 端口扫描 场景2 - 通过DTD窃取文件 场景3 - 远程代码执行 场景4 - 钓鱼 场景4 - HTTP 内网主机探测 场景5 ...
- 利用DOCX文档远程模板注入执行宏代码
利用DOCX文档远程模板注入执行宏代码 简介 本地文件中在没有宏代码的情况下,攻击者可以尝试执行远程文件中宏代码.其中来自APT28的最新样本将此技术展现的淋漓尽致.该样本是docx文件,文件内没有任 ...
- 软件安全之代码注入技术 向目标 PE 文件注入 DLL notepad lpk.dll 远程线程函数 提权函数 OpenProcess VirtualAllocEx
实验 4 代码注入技术 引言 1.实验说明 代码注入是将用户代码注入到其他进程或者可执行文件中,实现拦截目标进程运行过程的关键信息.改变目标进程或可执行文件原本执行流程等目的 2.实验目的 本实验通过 ...
最新文章
- Vue之@click、事件修饰符@click.stop与@click.prevent、按键修饰符@keyup.enter
- 如何发布php网站_php网站如何发布【货币问答】- 联合货币
- QT的QGLFormat类的使用
- ASP.NET Core 3.0 gRPC 身份认证和授权
- linux默认归档目录,Linux系统管理(第4章:目录和文件管理二)
- java调用javascript函数_使用Java程序中的参数调用Javascript函数
- scrum 11.6
- 地域和地方的区别_区域经济学入门级名词内涵的探索(区域、地域、地区、空间和区位的区别与联系)...
- Java中的final、static、this、super 关键字
- python数据分析收获与心得体会_初次数据分析--我的心得体会
- 自动阅读专业版第七次更新---原薅羊毛专业版
- 测试进阶必备,这5款http接口自动化测试工具真的很香
- Java实现 LeetCode 741 摘樱桃(DFS || 递推 || 传纸条)
- java系统化基础-day02-运算符、选择结构、循环结构
- 用matlab绘制三维图和三视图
- VB完全控制IE浏览器,操作ie对象,响应ie事件
- 闲话虚拟仪器开发历史
- chmod 777 修改文件权限
- Eclipse使用教程1
- IDC服务商开启行业自律新篇章