zoukankan      html  css  js  c++  java
  • 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玩的都比我熟

  • 相关阅读:
    RHEL7使用ssm命令管理LVM
    LVM命令摘要
    Linux用户磁盘配额
    Linux磁盘分区实战案例
    通过yum升级CentOS/RHEL最小化安装
    RHEL7下PXE+FTP+Kickstart无人值守安装操作系统
    配置VSFTP服务器
    RHEL7下PXE+NFS+Kickstart无人值守安装操作系统
    RHEL7下PXE+Apache+Kickstart无人值守安装操作系统
    html5实现图片自适应手机屏幕页面的css
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/2178877.html
Copyright © 2011-2022 走看看