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等 敬请关注  }

【旧源码】HookNtOpenProcess Source 

专注于: Net分布式技术,移动服务端架构及系统安全学习及研究  by Andy


 
 

64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )的更多相关文章

  1. Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持

    下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...

  2. 64位下的InlineHook

    目录 x64下手工HOOK的方法 一丶HOOK的几种方法之远跳 1. 远跳 不影响寄存器 + 15字节方法 2.远跳 影响寄存器 + 12字节方法 3.影响寄存器,恢复寄存器 进行跳转. 4. 常用 ...

  3. 2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案)

    可以负责任的说,这篇文档是windows10安装pygraphviz中,在中文技术网站中最新的文档,没有之一.是自己完全结合各种问题,包括调试等,总结出来的. 问题来源:主要是可视化RvNN网络的树结 ...

  4. 64位下pwntools中dynELF函数的使用

    这几天有同学问我在64位下怎么用这个函数,于是针对同一道题写了个利用dynELF的方法 编译好的程序 http://pan.baidu.com/s/1jImF95O 源码在后面 from pwn im ...

  5. win7(64)位下WinDbg64调试VMware10下的win7(32位)

    win7(64)位下WinDbg64调试VMware10下的win7(32位) 一 Windbg32位还是64位的选择 参考文档<Windbg 32位版本和64位版本的选择> http:/ ...

  6. Ubuntu 14.04 AMD 64位 下 Android Studio 的安装

    Ubuntu 14.04 AMD 64位 下 Android Studio 的安装 作者:yoyoyosiyu 邮箱:yoyoyosiyu@163.com 时间:2015年8月25日 Android ...

  7. 偶然碰到的Win7 64位下CHM 的问题解决

    最近下了几个沪江资料,都是chm格式的,但是在win7 64位下,都显示不了里面的音频和视频flash之类的控件,虽然可以通过源文件的方式打开视频文件,但是很麻烦.    网上似乎碰到的人也不是很多, ...

  8. 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 ...

  9. Linux 64位下一键安装scipy等科学计算环境

    Linux 64位下一键安装scipy等科学计算环境 采用scipy.org的各种方法试过了,安装还是失败.找到了一键式安装包Anaconda,基本python要用到的库都齐了,而且还可以选择安装到其 ...

随机推荐

  1. iOS使用UIScrollView实现左右滑动UITableView和UICollectionView

    在UIScrollView嵌套UITableView这篇文章是非常,但该项目的需求,需要嵌套UICollectionView,和UICollectionView和UITableView有非常多的不同, ...

  2. Android_显示器本身被卸载应用程序

    1.经jni实现功能 //LOG宏定义 #define LOG_INFO(tag, msg) __android_log_write(ANDROID_LOG_INFO, tag, msg) #defi ...

  3. Struts2 整合jQuery实现Ajax功能(2)

    1.1.1   Action利用struts2-json-plugin-X.X.X.jar响应Json格式信息: 1.      function removerecordbyid(recordid) ...

  4. UITableView刷新局部

    //局部section刷新 NSIndexSet *nd = [[NSIndexSet alloc] initWithIndex:1]; //刷新第二个section [self.tableView ...

  5. &lt;C++ 实现设计模式&gt; 观察者模式

    观察者模式,又称公布--订阅,mvc模式等. 通俗点讲,比方股票来说,非常多人关注一支股票,派一个人去观察股票的情况,一有变化(观察),就通知全部的预定这个消息的人. 而我们常见的mvc模式,v是指v ...

  6. MVC验证13-2个属性至少输入一项

    原文:MVC验证13-2个属性至少输入一项 有时候,我们希望2个属性中,至少有一个是必填,比如: using Car.Test.Portal.Extension;   namespace Car.Te ...

  7. MySQL 存储过程 经常使用语法

    MySQL 存储过程是从 MySQL 5.0 開始添加的新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装.特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库 ...

  8. 微信应用号开发知识贮备之Webpack实战

    天地会珠海分舵注:随着微信应用号的呼之欲出,相信新一轮的APP变革即将发生.作为行业内人士,我们很应该去拥抱这个趋势.这段时间在忙完工作之余准备储备一下这方面的知识点,以免将来被微信应用号的浪潮所淹没 ...

  9. 使用AndroidStudio快速开发教程

    关于AndroidStudio的使用 参考:http://www.codes51.com/article/detail_98914.html  1.对于开发环境的通性:编写 调试 视图   一般的开发 ...

  10. WimMaker 2.0 (2013.10) WIM制作工具

    WimMaker 2.0 (2013.10) WIM制作工具 可用于制作PE启动内核的Wim文件 说明: 因本软件使用.NET2.0制作,故主要用于制作WIM映像不用于备份还原系统(虽可用,但不专业, ...