Delphi实现SSDT Hook

关于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玩的都比我熟