【紫水晶首发】VB小子玩转驱动程序(4):HOOK
本帖最后由 xiaoly99 于 2014-7-10 20:41 编辑VB小子玩转驱动程序(4):HOOK
作者:0.0
0.0 导论
Ring3:
Private Sub Command1_Click()
On Error Resume Next
Dim TID As Long
TID = CLng(Text1.Text)
With DrvController
Call .IoControl(.CTL_CODE_GEN(&H801), VarPtr(TID), 4, 0, 0)'这句代码将TID以&H801的IOCTL代码传入Ring0 以SysEnter进入
End With
Command1.Enabled =False
End Sub
------------------------------------------------------------------------------------------------------------------------------------------
Ring0:
DispatchIoctl----------Switch(IOCTLCode)----------Case(StartProt)
memcpy(&mytid,pIoBuffer,sizeof(mytid)); //将Ring3传来的TID的地址写入mytid变量
PsLookupThreadByThreadId((HANDLE)mytid,&myet)) //得到EThread
myep=IoThreadToProcess(myet); //得到EProcess
*(PULONG)((ULONG)myep+0x248)=0x4; //设置进程已退出
*(PULONG)((ULONG)myet+0x248)=0x10; //设置线程为系统线程
HookMmIsAddressValid(); //Hook函数
HookKeAttachProcess() //Hook函数
这里特别讲一下两个函数
第一个函数的作用是判断一个地址是否有效 而冰刃是也是用MmIsAddressValid来判断地址有效性
小知识1:冰刃还Hook了KeBugCheckEx确保结束DKOM了BreakOnTermination标志的进程不会蓝屏 不过Hook KeBugCheck2会更好些 但是KeBugCheck2是未导出函数 所以要搜索函数或者暴搜内核 这个下篇讲
第二个函数的作用是进入进程 ReadProcessMemory和WriteProcessMemory都是依靠KeAttachProcess
但是没有Hook KeStackAttachProcess这个函数,所以可以通过某些YY方法PspExitProcess
最好是Hook KiAttachProcess+0x5 这样好一些
-----------------------------------------------------------
现在讲如何Hook
先关内存写保护 就是对cr0寄存器的操作
在计算jmp偏移量
偏移量的计算公式是 : 跳转地址 - 当前地址 - 5
然后RtlCopyMemory把偏移Copy到一个数组中
还未Hook前的Byte数组是这样的 0xE9,0,0,0,0
填入后提高IQRL到DPC级别 注意:DPC不是一个级别 而是指和DPC一样的优先级
再获取函数地址 用RtlCopyMemory把Byte数组Copy到函数中
再降低IQRL到Passive级
关内存写保护
两个实例
1.1 准备
获取未导出函数的准备是WinDbg和适用于系统的符号包,可以根据下列表格下载 注:下载的统一为Xp x86版本,其它版本请自行搜索
XPSP0http://msdl.microsoft.com/download/symbols/packages/windowsxp/windowsxp.x86.fre.rtm.symbols.exe
XPSP1http://msdl.microsoft.com/download/symbols/packages/windowsxp/xpsp1sym_x86.exeXPSP2http://msdl.microsoft.com/download/symbols/packages/windowsxp/WindowsXP-KB835935-SP2-slp-Symbols.exeWinDbghttp://msdl.microsoft.com/download/symbols/debuggers/dbg_x86_6.11.1.404.msi
1.2 查找特征码
假设符号包安装在d:\Symbol,那么打开Windbg,在"lkd>"命令行后输入命令:.sympath SRV*d:\Symbol*http://msdl.microsoft.com/download/symbols
!sym noisy
!lmi nt
.reload /f nt
现在可以用u 函数名获得未导出函数地址了,但是在我们的驱动函数中不可以直接调用或Hook未导出函数,我们加载好符号先测试一下,输入命令"u KeBugCheck2"
lkd> u KeBugCheck2 l 5
nt!KeBugCheck2:
804f9226 8bff mov edi,edi
804f9228 55 push ebp
804f9229 8bec mov ebp,esp
804f922b 81ecc8030000 sub esp,3C8h
804f9231 a1c0be5480 mov eax,dword ptr
在本机上,KeBugCheck2的地址为804f9226,但在驱动中怎么获取这个地址呢?可以搜索导出函数KeBugCheckEx
lkd> u kebugcheckexl 10
nt!KeBugCheckEx:
804f9caa 8bff mov edi,edi
804f9cac 55 push ebp
804f9cad 8bec mov ebp,esp
804f9caf 6a00 push 0
804f9cb1 ff7518 push dword ptr
804f9cb4 ff7514 push dword ptr
804f9cb7 ff7510 push dword ptr
804f9cba ff750c push dword ptr
804f9cbd ff7508 push dword ptr
804f9cc0 e861f5ffff call nt!KeBugCheck2 (804f9226)
804f9cc5 5d pop ebp
804f9cc6 c21400 ret 14h
在804f9cc0的位置调用了KeBugCheck2,从中我们可以知道特征码是e8########5d
这里是61f5ffff,为什么不是804f9226呢?因为它是一个偏移值,我们先把它以ULONG的形式读出:fffff561,这里用到一个公式:当前地址+偏移量+5=Call地址
804f9cc0 + fffff561 + 5 = 804f9226 = KeBugCheck2
------------------------------------------------------------------------------------
2.1 驱动搜索#include "LDasm.h"PVOIDGetFunctionAddr(IN PCWSTR FunctionName){UNICODE_STRINGUniCodeFunctionName;RtlInitUnicodeString(&UniCodeFunctionName,FunctionName);returnMmGetSystemRoutineAddress(&UniCodeFunctionName);}
VOID GetKeBugCheck2(){
UCHAR *cPtr, *pOpcode;
ULONG Length;
for (cPtr =(PUCHAR)GetFunctionAddr(L"KeBugCheckEx");cPtr <(PUCHAR)GetFunctionAddr(L"KeInsertQueueApc") + 32;cPtr += Length)
{
Length = SizeOfCode(cPtr, &pOpcode);
if (!Length) break;
if (*pOpcode == 0xE8 && *(PUSHORT)(pOpcode + 5) == 0x5D)
{
KeBugCheck2 =(KEBUGCHECK2)(*(PULONG)(pOpcode+1)+(ULONG)cPtr + 5);//注意 为什么有两个KeBugCheck2呢?因为C是大小写敏感的
break;
}
}}//此段代码选自IceFreak->Kill.h2.2 动态调用未导出函数先声明类型(typedef):typedef VOID (*KEBUGCHECK2)(
IN ULONGBugCheckCode,
IN ULONG_PTRBugCheckParameter1,
IN ULONG_PTRBugCheckParameter2,
IN ULONG_PTRBugCheckParameter3,
IN ULONG_PTRBugCheckParameter4,
IN ULONG_PTRBugCheckParameterNew
);
再声明函数:KEBUGCHECK2 KeBugCheck2 = NULL;
这样就可以调用了,不过在调用之前先Call一次GetKeBugCheck2函数,以便获得KeBugCheck2的地址
2.3 Hook
知道地址后就可以向普通的函数一样Hook了,注意:在Hook了FastCall类型的函数是,要注意堆栈平衡,最好不要直接在其内部调用外部函数和全局变量,代码如下:
pushfd
pushad
call MyFuction
popad
popfd 这里的氛围很好
希望继续 本帖最后由 HoviDelphic 于 2010-1-25 02:08 编辑
第一个函数的作用是判断一个地址是否有效 而冰刃是用Hook KeBugCheckEx来判断地址有效性 如果在Ring0中读或写非法地址就会调用KeBugCheck蓝屏
xiaoly99 发表于 2010-1-24 17:58 http://www.m5home.com/bbs/images/common/back.gif
是么?貌似冰刃hook KeBugCheckEx只是为了防止在杀标志为BreakOnTermination的进/线程时蓝屏。 是么?貌似冰刃hook KeBugCheckEx只是为了防止在杀标志为BreakOnTermination的进/线程时蓝屏。
HoviDelphic 发表于 2010-1-25 02:06 http://www.m5home.com/bbs/images/common/back.gif
已经改正了:) 学习学习,再学习... LZ怎么水晶狂飚啊!!?!?!?!:funk: 我用很通俗的语言解释了ssdt/sssdt hook。 收藏下,慢慢看! 收藏下,慢慢看! 本帖最后由 syfy 于 2010-2-13 17:48 编辑
你的顺序是不是反了,为什么不是先从导出的函数开始寻址呢 你的顺序是不是反了,为什么不是先从导出的函数开始寻址呢
syfy 发表于 2010-2-13 16:06 http://www.m5home.com/bbs/images/common/back.gif
你说谁的顺序反了?
另外syfy=syf吗? 不等不等,我可不是syf大牛,我是新手 哦,原来syf是大牛啊,一同膜拜大牛。“syf大牛”在此网站的账号是“本网站最菜的人”。 新年快乐!
支持一下. 原理和http://www.vbgood.com/viewthread.php?tid=83676&extra=&page=1
这篇相同吗? 我觉得应该先说下普通的APIHOOK,
首先说下用PB写DLL用VB写注入 如何HOOKAPI
起飞就是驱动级HOOK了。
不说了回学校整去! dll注入确实是最有效率和最安全的方法,ssdt hook已经老掉牙了 dll注入确实是最有效率和最安全的方法,ssdt hook已经老掉牙了
syfy 发表于 2010-2-19 18:24 http://www.m5home.com/bbs/images/common/back.gif
ssdt hook在内核层是稳定的方法 还没有老掉牙呢
dll注入的话在Ring0 Hook OBORH就可以让你不能注入了 ssdt hook在内核层是稳定的方法 确实不错,学习了,谢谢了 学习 刚刚来学习了, 好文章{:soso_e102:}学习一下
页:
[1]