想写这个程序主要是因为看了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与用户层通信询问是否放行。

 #include "ntddk.h"   //环境:WDK 7.1 WIN XP SP3 测试通过
#include <ntdef.h>  //注意我分发函数中是故意留空白的,不要直接拿来编译 #define NtSetEventID 219 typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; NTSTATUS ZwSetEvent(__in HANDLE EventHandle,__out_opt PLONG PreviousState); PVOID AddressOfFuncAddress;
HANDLE HandleTemp = (HANDLE)0x288C58F1;
ULONG NtSetEventAddress, TheHookAddress,KiFastCallEntryAddress;
ULONG YesOrNo=;
ULONG AddressOffset = ;
ULONG TempDword,Test;
ULONG ProcessPID = ;
ULONG pid, DispatchAddress, TempBufferCopy;
PULONG DwordAddress = ;
INT8 i;
INT8 *PbyteAddress;
KSPIN_LOCK MySpinLock1;
KSPIN_LOCK MySpinLock2;
KSPIN_LOCK MySpinLock3;
KIRQL TempKirql1;
KIRQL TempKirql2;
ULONG DebugAddress = ,FuncAddress;
//设置SSDT HOOK 用来栈回溯得到KiFastCallEntry地址
Check()
NTSTATUS HookSSDT(PVOID FuncAdress)
{
ULONG OutTemp = ;
NtSetEventAddress = (ULONG)KeServiceDescriptorTable.ServiceTableBase[NtSetEventID];
DebugAddress=(ULONG)&KeServiceDescriptorTable.ServiceTableBase[NtSetEventID];
KeInitializeSpinLock(&MySpinLock1);
KeAcquireSpinLock(&MySpinLock1,&TempKirql1);
_asm {
cli
push eax
mov eax, cr0
and eax, not 10000h
mov cr0, eax
pop eax
}
KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = (ULONG)FuncAdress;
__asm {
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
sti
}
KeReleaseSpinLock(&MySpinLock1,&TempKirql1);
ZwSetEvent(HandleTemp,
&OutTemp);
return STATUS_SUCCESS;
}
//解除SSDT HOOK
void UnhookSSDTHook()
{
KeInitializeSpinLock(&MySpinLock2);
KeAcquireSpinLock(&MySpinLock2,&TempKirql1);
_asm {
cli
push eax
mov eax, cr0
and eax, not 10000h
mov cr0, eax
pop eax
};
KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = NtSetEventAddress; _asm {
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
sti
};
KeReleaseSpinLock(&MySpinLock2,&TempKirql1);
return;
}
ULONG TheDispatchFunc(ULONG arg1, ULONG arg2, ULONG arg3)
{
if (arg3== (ULONG)KeServiceDescriptorTable.ServiceTableBase)
{
//这里可以根据栈中参数进行做判断
}
return arg2; }
//被挂载在KiFastCallEntry中(作为一个中转函数)
__declspec(naked) void InlineFunc()
{ _asm {
pushad
pushfd push edi//服务表基址
push ebx//服务地址
push eax//服务序号
call TheDispatchFunc
mov FuncAddress,eax popfd
popad
//补全被覆盖的函数
mov ebx, FuncAddress
sub esp, ecx
shr ecx, jmp TempBufferCopy }; }
//被挂载在SSDT的函数,需判断伪句柄
//并且要进行Inline HOOK
__declspec(naked) void SSDTFunc()
{
_asm {
push eax
mov eax, [esp + ]
mov TempDword, eax
pop eax
} if (TempDword == HandleTemp)
{
_asm {
push eax
mov eax, [esp + ]
mov KiFastCallEntryAddress, eax
pop eax
};
UnhookSSDTHook();
}
else
{
//_asm {int 3};
_asm {
jmp NtSetEventAddress
};
}
for (i = ; i < ; i++)
{ if (*((PULONG)KiFastCallEntryAddress)==0xe9c1e12b)
{
TheHookAddress = KiFastCallEntryAddress;
YesOrNo = ;
break;
}
KiFastCallEntryAddress--;
}
if (YesOrNo)
{
AddressOffset = (ULONG)InlineFunc - - (ULONG)TheHookAddress;
PbyteAddress = (INT8 *)TheHookAddress;
*PbyteAddress = 0xe9;
DwordAddress = (PULONG)((ULONG)TheHookAddress + );
*DwordAddress = AddressOffset;
TempBufferCopy = (ULONG)PbyteAddress + ;
}
//_asm {int 3};
_asm{retn 0x8 }
}
NTSTATUS UnloadFunc(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath)
{
//清理必要资源
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath)
{
NTSTATUS Status = ;
AddressOfFuncAddress=ExAllocatePool(NonPagedPool, );
MyDriver->DriverUnload = UnloadFunc;
Status = HookSSDT((PVOID)SSDTFunc);
if (!NT_SUCCESS(Status))
{
return ;
}
return STATUS_SUCCESS;
}

通过构造系统服务分发实现拦截&过滤 (仿360游戏保险箱)的更多相关文章

  1. 如何构造一个简单的USB过滤驱动程序

    本文分三部分来介绍如何构造一个简单的USB过滤驱动程序,包括"基本原理"."程序的实现"."使用INF安装".此文的目的在于希望读者了解基本 ...

  2. 一文读懂 Android TouchEvent 事件分发、拦截、处理过程

    什么是事件?事件是用户触摸手机屏幕,引起的一系列TouchEvent,包括ACTION_DOWN.ACTION_MOVE.ACTION_UP.ACTION_CANCEL等,这些action组合后变成点 ...

  3. MVC的Filters(拦截过滤)的Error页面,支持Ajax报错

    报错拦截过滤到error页面 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, A ...

  4. 拦截过滤防御XSS攻击 -- Struts2.3 以及 2.5 的解决方式

    使用Struts2框架开发的后台在防御XSS攻击的时候很多方式都不能用,因为Struts2对请求进行的二次封装有区别.以下针对Struts2的XSS攻击进行拦截过滤防御解决: Struts2.3 本方 ...

  5. C#制作高仿360安全卫士窗体(三)

    距上篇C#制作高仿360安全卫士窗体(二)也将近一个多月了,这个月事情还是像往常一样的多.不多我也乐在其中,毕竟我做的是我喜欢做的东西.今天特地抽空把怎么制作文本框写一下.同时也希望有爱好这些玩意的同 ...

  6. C#制作高仿360安全卫士窗体3

    C#制作高仿360安全卫士窗体(三)   距上篇C#制作高仿360安全卫士窗体(二)也将近一个多月了,这个月事情还是像往常一样的多.不多我也乐在其中,毕竟我做的是我喜欢做的东西.今天特地抽空把怎么制作 ...

  7. Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”

    Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...

  8. C#制作高仿360安全卫士窗体<二>

    继上次C#制作高仿360安全卫士窗体<一>发布之后响应还不错,我的博客放肆雷特也来了不少的新朋友,在这里先谢谢大家的支持!我自己也反复看了一下觉得对不起大家,写的非常乱而且很少文字介绍.在 ...

  9. C#制作高仿360安全卫士窗体<一>

    开始写这一系列博客之前先要向大家说声抱歉,放肆雷特建立很久却很少有更新.当然博客人气也不旺,大部分都是看的人多评论收藏的人少.一直想要改变这种状态,正好赶上了最近工作上做了一个高仿360安全卫士窗体. ...

随机推荐

  1. c动态分配结构体二维数组

    这个问题我纠结了蛮久了,因为前面一直忙(自己也懒了点),所以没有能好好研究这个.希望这篇文章能够帮助你们. #include <stdio.h> #include <stdlib.h ...

  2. my-innodb-heavy-4G.cnf配置文件注解

    [client] ####客户端 port = 3306 ####mysql客户端连接时的默认端口号 socket = /application/mysql-5.5.32/tmp/mysql.sock ...

  3. python【数据类型:列表与元组】

    python列表: 定义一个列表:cities=['北京','上海','广州','深圳'] 注意:列表的下标0表示第一个元素,下标-1表示最后一个元素 列表增加元素 在列表末尾添加一个元素:citie ...

  4. P2207 Photo

    P2207 Photo 题目描述 Framer Jhon 打算给他的N头奶牛照相,( 2 <= N <= 1 000 000 000) . 他们排成一条线,并且依次取1~N作为编号. 每一 ...

  5. java基础-BigInteger类常用方法介绍

    java基础-BigInteger类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.BigInteger类概述 Java中long型为最大整数类型,对于超过long ...

  6. Excel 中 VLOOKUP() 函数小结

    应用场景: 数据仓库上游源系统的数据库表变更,现在需要拆分一部分数据出来,单独放到一张新表中.假设原表为A,新表为B,B表和A表结构大部分一样,只有字段的前缀不同,那么我们如何找出到底有哪些字段不同呢 ...

  7. 科学计算三维可视化---TraitsUI的介绍

    TraitsUI的介绍 Python中存在Tkinter,wxPython,pyQt4等GUI图像界面编写库,这三类库要求程序员掌握众多的GUI API函数 对于科学计算的应用来说,我们希望可以快速的 ...

  8. centos7.2 rabbitmq3.6.2源码部署

    1.安装所有依赖包yum install -y gcc ncurses ncurses-base ncurses-devel ncurses-libs ncurses-static ncurses-t ...

  9. php 中 FastCGI与cgi的关系,何为fastcgi

    FastCGI是语言无关的.可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持 在内存中并因此获得较高的性能.众所周知,CGI解释器的反复加载是CGI性能低下的主要原因, 如果CGI解释器 ...

  10. BFS:八数码问题

    #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> ...