- 浏览: 41305 次
- 性别:
- 来自: 广州
关于SSDT Hook的理论知识就不多说了。简单的说一下Delphi开发KMD的一些需要注意的地方...这里使用DDDK---有点自己修改过的痕迹不过区别不大...自己可以看代码1.KeServiceDescriptorTable是一个很特殊的函数...如 ...
关于SSDT Hook的理论知识就不多说了。
简单的说一下Delphi开发KMD的一些需要注意的地方...
这里使用DDDK---有点自己修改过的痕迹不过区别不大...自己可以看代码
1.KeServiceDescriptorTable是一个很特殊的函数...如果直接使用implib来进行创建库的话
你会发现这个函数是被忽略的...因为偏移为0所以这个函数基本上只能起到标志作用没有任何实用价值....一些代码中出现了
代码:
function SystemService(AFunc:Pointer):PLONG;
begin
Result:=PLONG(Cardinal(KeServiceDescriptorTable^.ServiceTableBase)+SizeOf(ULONG)*PULONG(ULONG(AFunc)+1)^);
end;
很容易让人误认为是运行后的返回值(PS:Delphi的函数调用可以不需要写xxx())
上面说过因为这个函数几乎是没用的...所以不可能是执行他后返回地址
还有一点需要注意的...难道这个地址是说函数的地址??
导入表中的确是可以创建这个函数...但是这个函数几乎是没用的...而且系统的SYS Loader也不可能为他填写正确的函数地址...
这里取得地址就是他的本身地址...因为他的虚拟偏移为0
所以你直接使用
代码:
PPointer(@KeServiceDescriptorTable)^;
得到这个地址就可以了
2.fastcall的问题
这个问题很头痛.这个函数和delphi的调用方式完全不一样
很容易让人误认为是相同的Delphi的寄存器调用方式是
eax,edx,ecx,push...,etc
vc的fastcall大部分是edx,ecx,etc....
所以为了解决这个问题需要自己重写某些代码部分...
3.基本上没什么需要注意了自己做好链接库您当然可以使用
mickeylan牛为我们制作的rmcoff...
4.调试部分WinDbg什么的我就不说了...因为无法进行源码调试
个人觉得SysDebuger就不错其实asm也就那么回事。不是吗?呵呵
下面写一个完整的SSDT Hook
代码:
{
NtOpenProcess[SSDT Hook] By Anskya
Email: Anskya[at]Gmail.com
}
unit Driver;
interface
uses
ntddk; // ---->DDDK.pas
function _DriverEntry(DriverObject: PDriverObject; RegistryPath: PUnicodeString): NTSTATUS; stdcall;
implementation
type
TZwOpenProcess = function(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId): NTSTATUS; stdcall;
var
HookActive: Boolean;
ZwOpenProcessNextHook: TZwOpenProcess;
// 从导入表中获取一个函数的地址
function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
begin
Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^;
end;
// KeServiceDescriptorTable+函数名计算SSDT函数偏移
function SystemServiceName(AFunc: Pointer): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := PPointer(@KeServiceDescriptorTable)^;
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * PULONG(ULONG(AFunc) + 1)^));
end;
// KeServiceDescriptorTable+序号名计算SSDT函数偏移
function SystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := PPointer(@KeServiceDescriptorTable)^;
Result := PLONG(PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * iOrd)));
end;
// 钩子过程
function ZwOpenProcessHookProc(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId): NTSTATUS; stdcall;
begin
DbgPrint('ZwOpenProcess HookProc: NewZwOpenProcess(ProcessHandle:0x%.8X,DesiredAccess:0x%.8X,ObjectAttributes:0x%.8X,ClientId:0x%.8X)',
ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
Result := ZwOpenProcessNextHook(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
DbgPrint('ZwOpenProcess HookProc: NewZwOpenProcess(-):0x%.8X', Result);
end;
// 驱动卸载过程
procedure DriverUnload(DriverObject:PDriverObject); stdcall;
begin
if (HookActive) then
begin
asm
cli //disable WP bit
push eax
mov eax, cr0 //move CR0 register into EAX
and eax, not 000010000h //disable WP bit
mov cr0, eax //write register back
pop eax
end;
ZwOpenProcessNextHook := TZwOpenProcess(xInterlockedExchange(SystemServiceName(GetImportFunAddr(@ZwOpenProcess)), LONG(@ZwOpenProcessNextHook)));
asm
push eax //enable WP bit
mov eax, cr0 //move CR0 register into EAX
or eax, 000010000h //enable WP bit
mov cr0, eax //write register back
pop eax
sti
end;
DbgPrint('ZwOpenProcess New Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess Old Address: 0x%.8X', DWORD(@ZwOpenProcessNextHook));
HookActive := False;
end;
DbgPrint('DriverUnload(-)');
end;
// 驱动入口点
function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString): NTSTATUS; stdcall;
begin
DriverObject^.DriverUnload := @DriverUnload;
Result := STATUS_SUCCESS;
DbgPrint('DriverEntry(-):0x%.8X', Result);
HookActive := False;
DbgPrint('ZwOpenProcess Import Address: 0x%.8X', GetImportFunAddr(@ZwOpenProcess));
DbgPrint('KeServiceDescriptorTable() Address 1: 0x%.8X', @KeServiceDescriptorTable);
DbgPrint('KeServiceDescriptorTable() Address 2: 0x%.8X', PPointer(@KeServiceDescriptorTable)^);
DbgPrint('ZwOpenProcess ord Address: 0x%.8X', SystemServiceOrd($7A)^); // XP ord!
DbgPrint('ZwOpenProcess Name Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess HookProc Address: 0x%.8X', @ZwOpenProcessHookProc);
if (Not HookActive) then
begin
// SSDT Hook
asm //disable WP bit
cli
push eax
mov eax, cr0 //move CR0 register into EAX
and eax, not 000010000h //disable WP bit
mov cr0, eax //write register back
pop eax
end;
//lpNew^ := LONG(lpOld);
ZwOpenProcessNextHook := TZwOpenProcess(xInterlockedExchange(SystemServiceName(GetImportFunAddr(@ZwOpenProcess)), LONG(@ZwOpenProcessHookProc)));
asm
push eax //enable WP bit
mov eax, cr0 //move CR0 register into EAX
or eax, 000010000h //enable WP bit
mov cr0, eax //write register back
pop eax
sti
end;
DbgPrint('ZwOpenProcess New Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess Old Address: 0x%.8X', DWORD(@ZwOpenProcessNextHook));
HookActive := True;
end else
begin
DbgPrint('ZwOpenProcess Hooked!!! By Anskya');
end;
end;
end.
关于function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
这个函数稍微说一下...
如果你使用的连接库是x86模式的你就不能这样了。。。
这个是标准格式...
call [xxxx]---->jmp [xxxxxx]---->函数地址
x86模式的lib是直接
call [xxxx]---->函数地址
这里需要注意一下
这个函数你可以本地获取一下Ring3下的函数地址吧...这个我就不多说了...
相信大家import hook玩的都比我熟
现在正在自己整理一个头部...当然也是站在各位前辈的肩膀上进行更新的
心得:有的时候觉得Delphi写驱动也很有意思,相对来说比较简单...入门不错(就是编译方面比较麻烦..但是翻译的同时也学到了许多东西.我喜欢这份工作...以后会有更多的东西呈现给大家看看...由于小弟初次接触底层相关的东西难免有错误希望大家海涵,还有指出。我会虚心接受的。)
没太大必最好不要用Delphi去写这个。头部翻译麻烦,源码级调试,等等问题。。。还有就是您真的有这个必要吗?
写一些简单的不错。。。KMD方面的还行。。。
关于SSDT Hook的理论知识就不多说了。
简单的说一下Delphi开发KMD的一些需要注意的地方...
这里使用DDDK---有点自己修改过的痕迹不过区别不大...自己可以看代码
1.KeServiceDescriptorTable是一个很特殊的函数...如果直接使用implib来进行创建库的话
你会发现这个函数是被忽略的...因为偏移为0所以这个函数基本上只能起到标志作用没有任何实用价值....一些代码中出现了
代码:
function SystemService(AFunc:Pointer):PLONG;
begin
Result:=PLONG(Cardinal(KeServiceDescriptorTable^.ServiceTableBase)+SizeOf(ULONG)*PULONG(ULONG(AFunc)+1)^);
end;
很容易让人误认为是运行后的返回值(PS:Delphi的函数调用可以不需要写xxx())
上面说过因为这个函数几乎是没用的...所以不可能是执行他后返回地址
还有一点需要注意的...难道这个地址是说函数的地址??
导入表中的确是可以创建这个函数...但是这个函数几乎是没用的...而且系统的SYS Loader也不可能为他填写正确的函数地址...
这里取得地址就是他的本身地址...因为他的虚拟偏移为0
所以你直接使用
代码:
PPointer(@KeServiceDescriptorTable)^;
得到这个地址就可以了
2.fastcall的问题
这个问题很头痛.这个函数和delphi的调用方式完全不一样
很容易让人误认为是相同的Delphi的寄存器调用方式是
eax,edx,ecx,push...,etc
vc的fastcall大部分是edx,ecx,etc....
所以为了解决这个问题需要自己重写某些代码部分...
3.基本上没什么需要注意了自己做好链接库您当然可以使用
mickeylan牛为我们制作的rmcoff...
4.调试部分WinDbg什么的我就不说了...因为无法进行源码调试
个人觉得SysDebuger就不错其实asm也就那么回事。不是吗?呵呵
下面写一个完整的SSDT Hook
代码:
{
NtOpenProcess[SSDT Hook] By Anskya
Email: Anskya[at]Gmail.com
}
unit Driver;
interface
uses
ntddk; // ---->DDDK.pas
function _DriverEntry(DriverObject: PDriverObject; RegistryPath: PUnicodeString): NTSTATUS; stdcall;
implementation
type
TZwOpenProcess = function(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId): NTSTATUS; stdcall;
var
HookActive: Boolean;
ZwOpenProcessNextHook: TZwOpenProcess;
// 从导入表中获取一个函数的地址
function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
begin
Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^;
end;
// KeServiceDescriptorTable+函数名计算SSDT函数偏移
function SystemServiceName(AFunc: Pointer): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := PPointer(@KeServiceDescriptorTable)^;
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * PULONG(ULONG(AFunc) + 1)^));
end;
// KeServiceDescriptorTable+序号名计算SSDT函数偏移
function SystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := PPointer(@KeServiceDescriptorTable)^;
Result := PLONG(PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * iOrd)));
end;
// 钩子过程
function ZwOpenProcessHookProc(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId): NTSTATUS; stdcall;
begin
DbgPrint('ZwOpenProcess HookProc: NewZwOpenProcess(ProcessHandle:0x%.8X,DesiredAccess:0x%.8X,ObjectAttributes:0x%.8X,ClientId:0x%.8X)',
ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
Result := ZwOpenProcessNextHook(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
DbgPrint('ZwOpenProcess HookProc: NewZwOpenProcess(-):0x%.8X', Result);
end;
// 驱动卸载过程
procedure DriverUnload(DriverObject:PDriverObject); stdcall;
begin
if (HookActive) then
begin
asm
cli //disable WP bit
push eax
mov eax, cr0 //move CR0 register into EAX
and eax, not 000010000h //disable WP bit
mov cr0, eax //write register back
pop eax
end;
ZwOpenProcessNextHook := TZwOpenProcess(xInterlockedExchange(SystemServiceName(GetImportFunAddr(@ZwOpenProcess)), LONG(@ZwOpenProcessNextHook)));
asm
push eax //enable WP bit
mov eax, cr0 //move CR0 register into EAX
or eax, 000010000h //enable WP bit
mov cr0, eax //write register back
pop eax
sti
end;
DbgPrint('ZwOpenProcess New Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess Old Address: 0x%.8X', DWORD(@ZwOpenProcessNextHook));
HookActive := False;
end;
DbgPrint('DriverUnload(-)');
end;
// 驱动入口点
function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString): NTSTATUS; stdcall;
begin
DriverObject^.DriverUnload := @DriverUnload;
Result := STATUS_SUCCESS;
DbgPrint('DriverEntry(-):0x%.8X', Result);
HookActive := False;
DbgPrint('ZwOpenProcess Import Address: 0x%.8X', GetImportFunAddr(@ZwOpenProcess));
DbgPrint('KeServiceDescriptorTable() Address 1: 0x%.8X', @KeServiceDescriptorTable);
DbgPrint('KeServiceDescriptorTable() Address 2: 0x%.8X', PPointer(@KeServiceDescriptorTable)^);
DbgPrint('ZwOpenProcess ord Address: 0x%.8X', SystemServiceOrd($7A)^); // XP ord!
DbgPrint('ZwOpenProcess Name Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess HookProc Address: 0x%.8X', @ZwOpenProcessHookProc);
if (Not HookActive) then
begin
// SSDT Hook
asm //disable WP bit
cli
push eax
mov eax, cr0 //move CR0 register into EAX
and eax, not 000010000h //disable WP bit
mov cr0, eax //write register back
pop eax
end;
//lpNew^ := LONG(lpOld);
ZwOpenProcessNextHook := TZwOpenProcess(xInterlockedExchange(SystemServiceName(GetImportFunAddr(@ZwOpenProcess)), LONG(@ZwOpenProcessHookProc)));
asm
push eax //enable WP bit
mov eax, cr0 //move CR0 register into EAX
or eax, 000010000h //enable WP bit
mov cr0, eax //write register back
pop eax
sti
end;
DbgPrint('ZwOpenProcess New Address: 0x%.8X', SystemServiceName(GetImportFunAddr(@ZwOpenProcess))^);
DbgPrint('ZwOpenProcess Old Address: 0x%.8X', DWORD(@ZwOpenProcessNextHook));
HookActive := True;
end else
begin
DbgPrint('ZwOpenProcess Hooked!!! By Anskya');
end;
end;
end.
关于function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
这个函数稍微说一下...
如果你使用的连接库是x86模式的你就不能这样了。。。
这个是标准格式...
call [xxxx]---->jmp [xxxxxx]---->函数地址
x86模式的lib是直接
call [xxxx]---->函数地址
这里需要注意一下
这个函数你可以本地获取一下Ring3下的函数地址吧...这个我就不多说了...
相信大家import hook玩的都比我熟
现在正在自己整理一个头部...当然也是站在各位前辈的肩膀上进行更新的
心得:有的时候觉得Delphi写驱动也很有意思,相对来说比较简单...入门不错(就是编译方面比较麻烦..但是翻译的同时也学到了许多东西.我喜欢这份工作...以后会有更多的东西呈现给大家看看...由于小弟初次接触底层相关的东西难免有错误希望大家海涵,还有指出。我会虚心接受的。)
没太大必最好不要用Delphi去写这个。头部翻译麻烦,源码级调试,等等问题。。。还有就是您真的有这个必要吗?
写一些简单的不错。。。KMD方面的还行。。。
发表评论
-
API HOOK的实现原理
2009-05-27 17:10 1056一、序言 对大多数的Windows开发者来说,如何在Win32 ... -
delphi关键字详解
2009-05-22 10:16 1682absolute //它使得你能够 ... -
Object Pascal编程风格通则
2009-05-14 14:44 953概要: 这篇文章展现了一种格式化Delphi代码的标准 ... -
子目录级的文件查找
2009-05-14 10:49 885实现方法: 1. 获取当前目录下的所有下一级子目录。 2. ... -
Delphi面向对象(OOP)
2009-05-12 14:29 1405何为面向对象?(OO) 结构化编程(SP)是一种编程 ... -
线程池(1、2)使用
2009-05-06 10:55 1004// 创建线程池 FThreadPool := TThread ... -
线程池(2)
2009-05-06 10:52 898{ 函 数 名:TThreadsPool.FreeFinish ... -
DELPHI写的循环队列
2009-04-28 11:31 1797unit cirstream; interface u ... -
线程池(1)
2009-04-27 14:28 868unit uThreadPool; { aPool.Ad ...
相关推荐
WINDOWS 过PG后可修改SSDT,实现SSDT hook,采用二次挑战方式实现
使用ssdthook技术实现进程防止关闭功能,包含完整代码,代码注释齐全。
ssdthook
SSDTHook实现进程保护:http://blog.csdn.net/php_fly/article/details/9202379
ssdt hooking for windows kernel
ring3恢复SSDT HOOK(易语言ssdt hook恢复工具)是一款易语言源码恢复辅助工具。他可以基于ring3恢复SSDTHOOK,一款很专业的工具。使用ZwSystemDebugControl,可以在ring3下读写内核空间虚拟内存,但是XP以上系统貌似...
SSDT Table Viewr, Detecting SSDT HOoks .
SSDT HOOK检测,SSDT SHADOW HOOK的检测没有做,跟SSDT检测原理一样,只是多分析一个PE,多比对一套函数,没有计算当前HOOK落到那个moudle也没有INLINE检测,INLINE还是很麻烦,早就有linxer大牛的xuetr了,自己写也...
通过hook内核中ssdt表中的ntopenprocess函数,标号为35,可通过遍历ssdt表查找得知,可实现进程保护。 适用系统:win7 64,需关闭驱动签名保护 编程工具:vs2012+wdk8.0
SSDT表 hook 原理 源码
如何区分ssdt hook和inline hook的区别
SSDT HookSSDT HookSSDT HookSSDT HookSSDT HookSSDT Hook
SSDt HOOK的 源码 大家感兴趣的看看
HookDemo_SSDT SSDT hook 的简单例子
SSDT Hook nt!zwReadVirtualMemory 的完整代码
SSDT HOOK引擎,调用HookService()之前应该先调用InitServicesTalbe()来对SSDT进行一次性的保存,避免后面多次HOOK就要保存多次 !
详细演示了32位系统下的SSDT Hook的安装与恢复
易语言Shadow ssdt HOOK恢复
ssdt内核hook的源代码ssdt内核hook的源代码
XP下SSDT Hook ZwCreateThread的代码,仅适用于XP,由驱动和用户模式下控制程序组成,是从以前写的另一个程序修改过来的,所以代码中部分结构体的成员的定义是多余的,要写SSDT Hook的可以参考一下