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要用到的库都齐了,而且还可以选择安装到其 ...
随机推荐
- DP 水的问题
假设的自然数N的K随机二进制表示是不相邻的两个相邻的数字.那么我们说这个数字是K好一些. 乞讨L地点K十六进制数K的相当数量的数. 例如K = 4.L = 2什么时候.整个K好一些11.13.20.2 ...
- CSS3+HTML5特效7 - 特殊的 Loading 效果
效果如下 实现原理: 利用CSS3的@keyframes规则创建动画效果: 使用CSS3的animation效果完成滚动切换. 代码说明: 样式表中@-webkit-keyframes及@ke ...
- 剖析Jetty实现原理
之前写一个简单易用Jetty文章.Jetty对于做JAVA Web发展的方面来说并不陌生,他是一个servlet集装箱,只有相对Tomcat这是比较简单的设计,并且也相对简单,使用灵活,我是学习和使用 ...
- Ubuntu下的用户和权限(二)
五.chown.chgrp命令 从名字就能够猜測他们是干嘛的,可是这两个命令须要root权限. chown命令的格式为:chown user:group file 中间的user : group三项 ...
- java-list-remove()用法浅析 解决java list remove() 数据不对的问题
在java中对list进行操作很频繁,特别是进行list启遍历,这些操作我们都会,也很熟悉,但是对java中list进行删除元素,remove list中的元素就不怎么熟悉了吧,可以说很陌生,是实际操 ...
- UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)
在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...
- 【 c语言中无符号和有符号的加法运算】【深入理解】--【sky原创】
原文:[ c语言中无符号和有符号的加法运算][深入理解]--[sky原创] 第一题 #include<stdio.h> int main() { unsigned int a=6; i ...
- Linux---江湖
Linux江湖13:我该如何备份系统 Posted on 2014-12-18 10:39 京山游侠 阅读(497) 评论(3) 编辑 收藏 在前面的一些文章中,我反复提到经常会把系统搞崩溃,所以备份 ...
- C#如何获得系统时间
原文:C#如何获得系统时间 C#获取时间,日期 //C#里内置的DateTime基本上都可以实现这些功能,巧用DateTime会使你处理这些事来变轻松多了 //今天 ...
- GIMP也疯狂之动态图的制作(三)
Note:本篇文章内容为linux下利用gimp和其它工具组合完成截取制作GIF图的一种实现,制作更为灵活,但并不方便,如果不需要那么高的定制性,并追求方便高效.可以使用类似QQ影音之类的软件,自带截 ...