• 通过构造系统服务分发实现拦截&过滤 (仿360游戏保险箱)


    想写这个程序主要是因为看了KSSD的一篇帖子,http://bbs.pediy.com/showthread.php?t=108378

    讲 的是360保险箱保护游戏账号的原理,实际上就是对各种请求的拦截。这个帖子是大约6年前的了,我简单的看了一下现在的360保险箱应该不再采用这种方法了。

    这里主要的思路就是HOOK住系统服务的分发,这已经不是什么新鲜的手法了。比方说,很多外挂作者都使用了内核重载来突破游戏保护的重重HOOK,内核重载也是劫持KiFastCallEntry来实现劫持服务分发的。这篇文章只是写来做一个练习。

    基本流程是

    1.应用层:

    负责安装驱动模块并与驱动通信,由用户选择是否要放行指定操作

    2.内核层:

    (1)设置SSDT HOOK并调用HOOK 函数,进行栈回溯获取KiFastCallEntry()基址
    (2)利用KiFastCallEntry()基址暴力搜索找到HOOK点位置并设置Inline Hook
    (3)判断服务请求是否合法,合法则放行,不合法则传递消息给用户层,由用户决定是否放行

    其实以上三步就是360保险箱的做法,程序里的有些内容因为不知道该怎么写,所以直接由那篇帖子的汇编分析逆写出来了。

    其实网上有很多HOOK KiFastCallEntry的代码,但是我没有找到有劫持ebx来劫持服务分发的例子,所以我写的就是

    sub esp, ecx

    shr ecx, 2

    mov ebx,FuncAddress

    结果一直蓝屏,调了整整两天也没找到哪里的问题

    后来在群里问到要把顺序改成这样

    mov ebx,FuncAddress

    sub esp, ecx

    shr ecx, 2

    结果真的不会触发BSOD了,不知道原理是什么,因为我觉得两种应该没有本质的区别(无论是寄存器还是堆栈我都没有改掉),可是第一种就是不行。

    本来应该生成一个设备对象与应用层通信的,结果被蓝屏弄的实在搞不下去,就以后再说吧,核心的程序就是这些了。

    想法就是根据SSDT索引得知是什么函数,然后再用在内核栈中索引出SSDT函数的参数(因为在call ebx时参数肯定已经入栈了),最后根据情况用IRP与用户层通信询问是否放行。

      1 #include "ntddk.h"   //环境:WDK 7.1 WIN XP SP3 测试通过
      2 #include <ntdef.h>  //注意我分发函数中是故意留空白的,不要直接拿来编译
      3 
      4 #define NtSetEventID 219
      5 
      6 typedef struct ServiceDescriptorEntry {
      7     unsigned int *ServiceTableBase;
      8     unsigned int *ServiceCounterTableBase;
      9     unsigned int NumberOfServices;
     10     unsigned char *ParamTableBase;
     11 } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
     12 
     13 __declspec(dllimport)  ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
     14 
     15 NTSTATUS ZwSetEvent(__in HANDLE  EventHandle,__out_opt PLONG  PreviousState);
     16 
     17 PVOID AddressOfFuncAddress;
     18 HANDLE HandleTemp = (HANDLE)0x288C58F1;
     19 ULONG NtSetEventAddress, TheHookAddress,KiFastCallEntryAddress;
     20 ULONG YesOrNo=0;
     21 ULONG AddressOffset = 0;
     22 ULONG TempDword,Test;
     23 ULONG ProcessPID = 0;
     24 ULONG pid, DispatchAddress, TempBufferCopy;
     25 PULONG DwordAddress = 0;
     26 INT8 i;
     27 INT8 *PbyteAddress;
     28 KSPIN_LOCK MySpinLock1;
     29 KSPIN_LOCK MySpinLock2;
     30 KSPIN_LOCK MySpinLock3;
     31 KIRQL TempKirql1;
     32 KIRQL TempKirql2;
     33 ULONG DebugAddress = 0,FuncAddress;
     34 //设置SSDT HOOK 用来栈回溯得到KiFastCallEntry地址
     35 Check()
     36 NTSTATUS HookSSDT(PVOID FuncAdress)
     37 {
     38     ULONG OutTemp = 0;
     39     NtSetEventAddress = (ULONG)KeServiceDescriptorTable.ServiceTableBase[NtSetEventID];
     40     DebugAddress=(ULONG)&KeServiceDescriptorTable.ServiceTableBase[NtSetEventID];
     41     KeInitializeSpinLock(&MySpinLock1);
     42     KeAcquireSpinLock(&MySpinLock1,&TempKirql1);
     43     _asm {    
     44             cli
     45             push eax
     46             mov  eax, cr0
     47             and  eax, not 10000h
     48             mov  cr0, eax
     49             pop eax
     50     }
     51     KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = (ULONG)FuncAdress;
     52     __asm {
     53             push eax
     54             mov  eax, cr0
     55             or eax, 10000h
     56             mov  cr0, eax
     57             pop eax
     58             sti
     59     }
     60     KeReleaseSpinLock(&MySpinLock1,&TempKirql1);
     61     ZwSetEvent(HandleTemp,
     62         &OutTemp);
     63     return STATUS_SUCCESS;
     64 }
     65 //解除SSDT HOOK
     66 void UnhookSSDTHook()
     67 {
     68     KeInitializeSpinLock(&MySpinLock2);
     69     KeAcquireSpinLock(&MySpinLock2,&TempKirql1);
     70     _asm {
     71             cli
     72             push eax
     73             mov  eax, cr0
     74             and  eax, not 10000h
     75             mov  cr0, eax
     76             pop eax
     77     };
     78     KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = NtSetEventAddress;
     79 
     80     _asm {
     81             push eax
     82             mov  eax, cr0
     83             or eax, 10000h
     84             mov  cr0, eax
     85             pop eax
     86             sti
     87     };
     88     KeReleaseSpinLock(&MySpinLock2,&TempKirql1);
     89     return;
     90 }
     91 ULONG TheDispatchFunc(ULONG arg1, ULONG arg2, ULONG arg3)
     92 {    
     93     if (arg3== (ULONG)KeServiceDescriptorTable.ServiceTableBase)
     94     {
     95         //这里可以根据栈中参数进行做判断
     96     }
     97     return arg2;
     98 
     99 }
    100 //被挂载在KiFastCallEntry中(作为一个中转函数)
    101 __declspec(naked) void InlineFunc()
    102 {
    103     
    104     
    105     _asm {
    106             pushad
    107             pushfd
    108 
    109             push edi//服务表基址
    110             push ebx//服务地址
    111             push eax//服务序号
    112             call TheDispatchFunc
    113             mov FuncAddress,eax
    114             
    115             popfd
    116             popad
    117             //补全被覆盖的函数
    118             mov ebx, FuncAddress
    119             sub esp, ecx
    120             shr ecx, 2
    121             
    122 
    123             jmp TempBufferCopy
    124             
    125     };
    126 
    127 }
    128 //被挂载在SSDT的函数,需判断伪句柄
    129 //并且要进行Inline HOOK
    130 __declspec(naked) void SSDTFunc()
    131 {
    132     _asm {
    133             push eax
    134             mov eax, [esp + 8]
    135             mov TempDword, eax
    136             pop eax
    137     }
    138 
    139     if (TempDword == HandleTemp)
    140     {
    141         _asm {
    142             push eax
    143             mov eax, [esp + 4]
    144             mov KiFastCallEntryAddress, eax
    145             pop eax
    146             };
    147         UnhookSSDTHook();
    148     }
    149     else
    150     {    
    151         //_asm {int 3};
    152         _asm {
    153             jmp NtSetEventAddress
    154         };
    155     }
    156     for (i = 0; i < 200; i++)
    157     {
    158         
    159         if (*((PULONG)KiFastCallEntryAddress)==0xe9c1e12b)
    160         {
    161             TheHookAddress = KiFastCallEntryAddress;
    162             YesOrNo = 1;
    163             break;
    164         }
    165         KiFastCallEntryAddress--;
    166     }
    167     if (YesOrNo)
    168     {    
    169         AddressOffset = (ULONG)InlineFunc - 5 - (ULONG)TheHookAddress;
    170         PbyteAddress = (INT8 *)TheHookAddress;
    171         *PbyteAddress = 0xe9;
    172         DwordAddress = (PULONG)((ULONG)TheHookAddress + 1);
    173         *DwordAddress = AddressOffset;
    174         TempBufferCopy = (ULONG)PbyteAddress + 5;
    175     }
    176     //_asm {int 3};
    177     _asm{retn 0x8 }
    178 }
    179 NTSTATUS UnloadFunc(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath)
    180 {
    181     //清理必要资源
    182     return STATUS_SUCCESS;
    183 }
    184 NTSTATUS DriverEntry(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath)
    185 {
    186     NTSTATUS Status = 0;
    187     AddressOfFuncAddress=ExAllocatePool(NonPagedPool, 4);
    188     MyDriver->DriverUnload = UnloadFunc;
    189     Status = HookSSDT((PVOID)SSDTFunc);
    190     if (!NT_SUCCESS(Status))
    191     {
    192         return 1;
    193     }
    194     return STATUS_SUCCESS;
    195 }
  • 相关阅读:
    Ubuntu安装deb软件包错误(依赖关系问题)解决
    scrapy抓取的中文结果乱码解决办法
    删除Git记录里的大文件
    Ubuntu18.04 修改DNS
    linux实现ssh免密码登录
    Vim进阶指南
    查找相同图片并重命名
    Markdown进阶指南
    一眼看穿flatMap和map的区别
    Java8简明指南
  • 原文地址:https://www.cnblogs.com/Ox9A82/p/5237069.html
Copyright © 2020-2023  润新知