64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )
64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )
【PS: 如果在64位系统下,出现调用测试demo,返回false的情况下,请修改Hook Dll的代码】
glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc, 0 , 0);
//改成跟X86下一样的
glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,glhInstance, 0);
2013.09.11代码修改, 可以针对指定的进程进行保护( 编译DLL和测试DEMO的时候,请注意目标平台,X86还是X64)
=> 工程给出的是X86下的,X64请自行编译一份Hook dll然后改下名字在测试demo中调用 ,C#中队X86和X64的判断可以通过
Environment.Is64BitOperatingSystem
2013.09.11 HookNtOpenProcessLib Souces
在我的上一篇文章中【Hook技术】实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展 介绍了X86下基于IAT Hook技术,通过Hook OpenProcess来实现从任务管理器中保护进程,看到一些评论,有朋友问该代码是否适用于64位系统? 答案是肯定的,需要修改两个地方:
a. 编译时候,设置平台为X64
b.修改SetWindowsHookEx第三个参数为0 (ps:该设置不是绝对的,如果你发现X64下该方法不成效,请尝试使用X86下的方法),关于这点,是因为64为下和32为下调用SetWindowsHookEx略有不同,官方关于该函数的有一段解析为:
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
如果你希望在X64下通过HOOK技术实现进程的保护,不推荐Hook OpenProcess,可以考虑通过Hook Ntdll的函数(NtOpenProcess)实现,这也是楼主写此文的目的的,介绍通过MHook实现对NtOpenProcess的hook实现进程的保护.
1. Hook技术基础知识(Inline Hook)
在开始本文的实例前想先通过对Hook技术做些简单的介绍,帮助大家更好的理解所谓的Hook技术,所谓的hook技术其实就是修改函数行为的一种技术,通过对函数行为的修改可以实现例如:文件的监控/保护 , 进程的监控/隐藏等,例如大多数的安全软件都是基于这种技术实现的,还有些病毒木马技术也会涉及到hook技术。一般的hook函数的流程:
{ 目标API } ----- 【 Hook API 】 ------- 修改函数入口前几个字节,添加跳转指令 类似JMP DWORD Ptr Address
\
{ jump 我们的代码处 }
|- a. 执行我们代码
|- b. 修复Hook
|- c. 调用目标API
通过修改目标函数的前几个字节,然后跳转到我们的代码执行,等执行完我们定制的代码后,在调用真实的目标API返回结果给调用程序.
大多数的系统API,前几个字节都是对堆栈的操作,而hook技术就是利用了这几个字节实现jmp的,伪代码描述:
目标函数:
mov edi, edi // HOOK Jmp DWORD PTR MyFunctionAddress jump后 MyFunctionAddress内部逻辑处理
push ebp // 堆栈操作 < ==========> xor ecx ,exc <=========> 修复原函数堆栈操作 { mov edi,edi push ebp,...}
mov ebp, esp // 跳到原函数执行JMP 【ADDRESS】
xor ecx, ecx ==> 标记地址为【ADDRESS】
这是一种比较常用的HOOK思路,还有修改函数中部或者尾部的,思路相同,patch的位置不同
还有中Hook的思路是通过“跳板”函数实现,定制函数和目标函数之间的关系
{ Hook Api }
\
{ Jump 定制函数 }
\
{ jump Trampoline(跳板函数) }
\ ______ { Call 目标函数 } ------ { 结果返回给调用程序 }
成功Hook函数后,跳转我们定制的函数中执行,当我们定制的代码执行完后,并不是在函数内部调用原目标函数,而是调用一个叫Trampoline的函数,Trampoline的任务就是平衡堆栈,然后执行原目标函数, 最后将结果返回给调用程序
例如:

mov edi, edi addr1 jmp customFunction ; //执行完地址的逻辑后,跳到调用Trampoline函数
push ebp < ==== JUMP ====> addr2 xor ecx,ecx
mov ebp, esp
addr2 xor ecx, ecx
Trampoline函数:
mov edi, edi
push ebp { 平衡堆栈 }
mov ebp, esp
jmp addr2 ===> 然后跳到原函数某地址执行

这种方法相对于第一种方式来说,安全了很多至少在多线程的环境下 ,一般trampoline跳转函数都是被标记为naked的,很多情况都是通过汇编实现,由自己编码控制堆栈。
2. 实战,X64下Hook NtOpenProcess
本demo中使用的hook引擎是MHook,Mhook是开源的,采用的是第二种hook方式,相比于MinHook/easyHook来说,使用简单,只导出两个函数:

//安装Hook
//ppSystemFunction,原函数地址
//pHookFunction ,定制的函数地址
BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction); //卸载HOOK
//ppHookedFuntion.原函数地址
BOOL Mhook_Unhook(PVOID *ppHookedFunction);

a. 下载Mhook,新建一个win32 DLL工程,名称:HookNtOpenProcessLib
b. 声明NtOpenProcess函数和我们定制的Hook_NtOpenProcess
//=========================================================
// struct CLIENT_ID
typedef struct _CLIENT_ID {
DWORD_PTR UniqueProcess;
DWORD_PTR UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
//===========================================================
// NtOpenProcess
typedef ULONG (WINAPI *pfnNtOpenProcess)(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK AccessMask ,
__in PVOID ObjectAttributes,
__in PCLIENT_ID ClientId);
pfnNtOpenProcess _NtOpenProcess = (pfnNtOpenProcess)GetProcAddress( GetModuleHandle(L"ntdll"),"NtOpenProcess");
定制的Hook_NtOpenProcess,设置进程句柄为NULL,保护所有进程,针对某个进程保护,请通过ProcesssHandler获取PID然后做比较

//===========================================================
//定制我们自己的NtOpenProcess
ULONG WINAPI Hook_pfnNtOpenProcess(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK AccessMask ,
__in PVOID ObjectAttributes,
__in PCLIENT_ID ClientId){
//ULONG result = _NtOpenProcess( ProcessHandle,AccessMask,ObjectAttributes,ClientId);
//DWORD pid = GetProcessIdByHandle( ProcessHandle);
//通过进程句柄获取PID,然后验证
//if(gProtectProcessID == pid ){
// return STATUS_ACCESS_DENIED;
//} //return result;
//===================================
//简单处理,直接设置ProcessHandle,保护所有
ProcessHandle = NULL;
return _NtOpenProcess( ProcessHandle, AccessMask,ObjectAttributes,ClientId);
}

c. 安装消息钩子,跟一篇博文一样,通过SetWindowsHookEx,只是在调用该函数时候需要注意区别下32位系统和64位系统情况,例如:

extern "C" __declspec(dllexport) BOOL InstallHook(DWORD pid)
{
BOOL bResult=FALSE;
//这里需要注意X86和X64下处理是不一样的
#ifdef _M_IX86
glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,glhInstance, 0);
#elif defined _M_X64
glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,0, 0); //第三参数为0,而不是当前模块的实例句柄
#endif if(glhHook!=NULL)
{
gProtectProcessID = pid;
bResult=TRUE;
} return bResult;
}

d.C#调用HOOKNtOpenProcessLib.dll
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Text = "=> HookNtOpenProcess <= ";
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e) {
Label lb = new Label{ Width = 200 , Height = 50 , ForeColor = System.Drawing.SystemColors.GrayText };
lb.Text = "By Andy, FZ " + Environment.NewLine + "专注于: Net分布式技术,移动服务端架构及系统安全学习及研究";
_btnHook = new Button { Text = "sTarthOok" };
_btnHook.Click += (sende, ex) => {
bool result = false;
if (_btnHook.Text.Equals("sTarthOok")) {
result = NativeAPI.InstallHook(System.Diagnostics.Process.GetCurrentProcess().Id);
_btnHook.Text = "sTophOok";
}
else if (_btnHook.Text.Equals("sTophOok")) {
NativeAPI.UninstallHook();
_btnHook.Text = "sTarthOok";
}
//MessageBox.Show(result.ToString());
};
this.Controls.Add( _btnHook );
_btnHook.SetBounds( 0 , 5 , 350,40 );
this.Controls.Add( lb);
lb.SetBounds( 0 , 50 , 350,40 );
}
class NativeAPI{
[DllImport("HookNtOpenProcessLib.dll",CallingConvention=CallingConvention.Cdecl)]
public extern static bool InstallHook( int pid );
[DllImport("HookNtOpenProcessLib.dll",CallingConvention=CallingConvention.Cdecl)]
public extern static bool UninstallHook();
}
private Button _btnHook = null;
}
e.程序运行效果读,第一张通过ARK工具查看inline hook了NtOpenProcess,NtOpenProcess进入内核后是通过调用ZwOpenProcess的,所以我们看到ZwOpenProcess也被Inline hook了,第2张通过任务管理器结束进程
关于程序中一些注意问题:
1. 编译HookNtOpenProcessLib.dll时候,如果要运行在64位系统下,通过“配置管理器”设置下平台X64(也就是你要编译两份DLL,一份是平台为win32的,一个是X64下的)
2. 附件中C#程序,如果希望运行在32位和64位系统上,请通过“配置管理器”设置平台为“AnyCPU”
3. 将编译好的dll(32位和64位)的放在测试demo下,测试demo在调用InstallHook时候,内部SetWindowsHookEx会根据当前平台调用对应的HookNtOpenProcessLib.dll
如果在使用中还存在任何问题,可以给我留言或者通过我的邮箱wygandy1987@gamil.com
{ 后面有时间,将发表一些关于Mhook实现的文章和关于内核Hook的文章,游戏hook等 敬请关注 }
专注于: Net分布式技术,移动服务端架构及系统安全学习及研究 by Andy
64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )的更多相关文章
- Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持
下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...
- 64位下的InlineHook
目录 x64下手工HOOK的方法 一丶HOOK的几种方法之远跳 1. 远跳 不影响寄存器 + 15字节方法 2.远跳 影响寄存器 + 12字节方法 3.影响寄存器,恢复寄存器 进行跳转. 4. 常用 ...
- 2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案)
可以负责任的说,这篇文档是windows10安装pygraphviz中,在中文技术网站中最新的文档,没有之一.是自己完全结合各种问题,包括调试等,总结出来的. 问题来源:主要是可视化RvNN网络的树结 ...
- 64位下pwntools中dynELF函数的使用
这几天有同学问我在64位下怎么用这个函数,于是针对同一道题写了个利用dynELF的方法 编译好的程序 http://pan.baidu.com/s/1jImF95O 源码在后面 from pwn im ...
- win7(64)位下WinDbg64调试VMware10下的win7(32位)
win7(64)位下WinDbg64调试VMware10下的win7(32位) 一 Windbg32位还是64位的选择 参考文档<Windbg 32位版本和64位版本的选择> http:/ ...
- Ubuntu 14.04 AMD 64位 下 Android Studio 的安装
Ubuntu 14.04 AMD 64位 下 Android Studio 的安装 作者:yoyoyosiyu 邮箱:yoyoyosiyu@163.com 时间:2015年8月25日 Android ...
- 偶然碰到的Win7 64位下CHM 的问题解决
最近下了几个沪江资料,都是chm格式的,但是在win7 64位下,都显示不了里面的音频和视频flash之类的控件,虽然可以通过源文件的方式打开视频文件,但是很麻烦. 网上似乎碰到的人也不是很多, ...
- win7 64位下如何安装配置mysql-5.7.4-m14-winx64
win7 64位下如何安装配置mysql-5.7.4-m14-winx641. mysql-5.7.4-m14-winx64.zip下载 官方网站下载地址:http://dev.mysql.com/g ...
- Linux 64位下一键安装scipy等科学计算环境
Linux 64位下一键安装scipy等科学计算环境 采用scipy.org的各种方法试过了,安装还是失败.找到了一键式安装包Anaconda,基本python要用到的库都齐了,而且还可以选择安装到其 ...
随机推荐
- crawler_编码转换_unicode(年)
import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @declare: unicode 帮助类<br> ...
- 【百度地图API】多家地图API内存消耗对比测验(带源码)
原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...
- [Android]Parcelable encountered IOException writing serializable object (name = xxx)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- CII-原子
<atom.h> #ifndef ATOM_INCLUDED #define ATOM_INCLUDED extern int Atom_length(const char *str); ...
- 一步一步写算法(之prim算法 中)
原文:一步一步写算法(之prim算法 中) [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] C)编写最小生成树,涉及创建.挑选和添加过程 MI ...
- 如何让Gridview在没有数据的时候显示表头(asp.net)
原文:如何让Gridview在没有数据的时候显示表头(asp.net) 1.前言 当对GridView控件进行数据绑定时,如果绑定的记录为空,网页上就不显示GridView,造成页面部分空白,页面布局 ...
- intellij idea 13&14 插件推荐及快速上手建议 (已更新!)
原文:intellij idea 13&14 插件推荐及快速上手建议 (已更新!) 早些年 在外企的时候,公司用的是intellij idea ,当时也是从eclipse.MyEclipse转 ...
- webkit内核下的mouseup后mousemove自动触发问题及解决方法
如题,就以chrome为代表举例说明遇到mousemove的问题. 为body分别绑定onmousedown.onmousemove.onmouseup,并为触发时打印至控制台.代码如下(同学不要忘记 ...
- The operator == is undefined for the argument type(s) int, null
package cn.edu.shu.web.test; public class TestInteger { public static void main(String[] args) { /** ...
- ReSharper C++计划上市
ReSharper是著名的VS代码生成工具,去年夏天,JetBrains公司就发布了ReSharper将推出支持C++的版本. ReSharper C++ EAP(Early Access Progr ...