博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
“热补丁”Hook,多线程下InlineHook解决方法
阅读量:6176 次
发布时间:2019-06-21

本文共 5490 字,大约阅读时间需要 18 分钟。

  “热补丁”(hot patch)是微软提出的一种安全Hook的机制,也是为了方便开发者对某些API函数进行下钩子。这种方法不同于普通的Inline hook更改首部的五个字节,而是更改首部的七个字节。为什么是七个字节呢?下边我们来讲一下这个的原理。

  我们可以看到CreateProcessW函数的首字节为 mov edi,edi(88 FF),这句汇编意思就是将edi的值放入edi,实际上并没有什么用,我们还看到在这个API上边有大段无用的字节。这就给了我们一种新的Hook思路,即将前两个字节改为短跳转指令(EB E9),使其跳到函数上边五字节处,然后再将这五个字节改为长跳转指令(E9 xxxxxxxx)。这样,即使Hook失败,也不影响函数的继续执行。

  接下来我们用代码来实现这一功能:

// HotPatch.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include 
typedef BOOL(WINAPI *pfnCreateprocessW)( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege);BOOL HOOKByHotpatch(LPWSTR wzDllName, LPCSTR szFuncName, PROC pfnNewFunc);BOOL UnhookByHotpatch(LPWSTR wzDllName, LPCSTR szFuncName);BOOL WINAPI NewCreateProcessW( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);int main(){ SetPrivilege(SE_DEBUG_NAME, TRUE); //hook HOOKByHotpatch(L"kernel32.dll", "CreateProcessW", (PROC)NewCreateProcessW); Sleep(1000); STARTUPINFO si = { 0 }; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; PROCESS_INFORMATION pi; //创建进程 TCHAR cmdLine[MAXBYTE] = L"notepad.exe"; BOOL bOk = CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi); Sleep(1000); UnhookByHotpatch(L"kernel32.dll", "CreateProcessW"); return 0;}//设置权限BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege){ TOKEN_PRIVILEGES TokenPrivileges;//权限令牌 HANDLE TokenHandle = NULL; //权限令牌句柄 LUID Luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle)) { printf("OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if (!LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &Luid)) // receives LUID of privilege { printf("LookupPrivilegeValue error: %u\n", GetLastError()); return FALSE; } TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Luid = Luid; if (bEnablePrivilege) TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else TokenPrivileges.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. //调整权限 if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { printf("AdjustTokenPrivileges error: %u\n", GetLastError()); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { printf("The token does not have the specified privilege. \n"); return FALSE; } return TRUE;}//Hootpatch,将函数首字节改为 short jmp(EB F9)BOOL HOOKByHotpatch(LPWSTR wzDllName, LPCSTR szFuncName, PROC pfnNewFunc){ FARPROC pOrgFuncAddr = NULL; DWORD dwOldProtect, dwAddress; BYTE pBuf[5] = { 0xE9, 0, }; BYTE pBuf2[2] = { 0xEB, 0xF9 }; PBYTE pByte; pOrgFuncAddr = (FARPROC)GetProcAddress(GetModuleHandle(wzDllName), szFuncName); pByte = (PBYTE)pOrgFuncAddr; //判断是否被勾 if (pByte[0] == 0xEB) return FALSE; //将前五字节代码改为可读可写 VirtualProtect((LPVOID)((DWORD)pOrgFuncAddr - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 1. NOP (0x90) //将前五字节改为E8 xxxxxxxx dwAddress = (DWORD)pfnNewFunc - (DWORD)pOrgFuncAddr; memcpy(&pBuf[1], &dwAddress, 4); memcpy((LPVOID)((DWORD)pOrgFuncAddr - 5), pBuf, 5); // 2. MOV EDI, EDI (0x8BFF) //将函数前两个字节改为EB F9 memcpy(pOrgFuncAddr, pBuf2, 2); VirtualProtect((LPVOID)((DWORD)pOrgFuncAddr - 5), 7, dwOldProtect, &dwOldProtect); return TRUE;}BOOL UnhookByHotpatch(LPWSTR wzDllName, LPCSTR szFuncName){ FARPROC pHookFunc = NULL; DWORD dwOldProtect; PBYTE pByte; BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 }; BYTE pBuf2[2] = { 0x8B, 0xFF }; pHookFunc = (FARPROC)GetProcAddress(GetModuleHandle(wzDllName), szFuncName); pByte = (PBYTE)pHookFunc; if (pByte[0] != 0xEB) return FALSE; VirtualProtect((LPVOID)pHookFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 1. NOP (0x90) memcpy((LPVOID)((DWORD)pHookFunc - 5), pBuf, 5); // 2. MOV EDI, EDI (0x8BFF) memcpy(pHookFunc, pBuf2, 2); VirtualProtect((LPVOID)pHookFunc, 5, dwOldProtect, &dwOldProtect); return TRUE;}BOOL WINAPI NewCreateProcessW( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation){ MessageBox(NULL, L"Hook", L"", 0); return TRUE;}

  需要注意的是使用这一方法钩取的适用条件(NOP*5指令+MOV ESI,ESI),使用的时候一定要反汇编看一下目标函数是否满足条件。

转载于:https://www.cnblogs.com/Toring/p/6664481.html

你可能感兴趣的文章
Java中高级开发工程师是什么技术水平(附28套Java进阶+高级视频教程)
查看>>
sudo命令
查看>>
第十九章 文本处理流编辑器:awk编程
查看>>
Xtrabackup+Rsync 备份数据库并同步到远端备份机
查看>>
activiti实战读书笔记——第九章 多实例
查看>>
php返回相对时间(如:20分钟前,3天前)的方法
查看>>
WilliamChart各种图表效果实现大全《IT蓝豹》
查看>>
shell脚本——linux主机监控
查看>>
eclipse配置jsp页面模板
查看>>
基于高德地图写的不同功能的地图应用
查看>>
DHCP服务器配置
查看>>
快速瓶颈识别
查看>>
运维工作总结201403
查看>>
我是菜鸟我加油……mysql主从同步
查看>>
[体系结构]设计模式(五)
查看>>
分布式文件系统
查看>>
其实很简单 微星为你详解Z77主板BIOS设置
查看>>
在Ubuntu Kylin下安装JDK1.8
查看>>
Hadoop 学习一
查看>>
Linux中生成/etc/shadow的加密密码
查看>>