通过构造系统服务分发实现拦截&过滤 (仿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与用户层通信询问是否放行。
#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游戏保险箱)的更多相关文章
- 如何构造一个简单的USB过滤驱动程序
本文分三部分来介绍如何构造一个简单的USB过滤驱动程序,包括"基本原理"."程序的实现"."使用INF安装".此文的目的在于希望读者了解基本 ...
- 一文读懂 Android TouchEvent 事件分发、拦截、处理过程
什么是事件?事件是用户触摸手机屏幕,引起的一系列TouchEvent,包括ACTION_DOWN.ACTION_MOVE.ACTION_UP.ACTION_CANCEL等,这些action组合后变成点 ...
- MVC的Filters(拦截过滤)的Error页面,支持Ajax报错
报错拦截过滤到error页面 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, A ...
- 拦截过滤防御XSS攻击 -- Struts2.3 以及 2.5 的解决方式
使用Struts2框架开发的后台在防御XSS攻击的时候很多方式都不能用,因为Struts2对请求进行的二次封装有区别.以下针对Struts2的XSS攻击进行拦截过滤防御解决: Struts2.3 本方 ...
- C#制作高仿360安全卫士窗体(三)
距上篇C#制作高仿360安全卫士窗体(二)也将近一个多月了,这个月事情还是像往常一样的多.不多我也乐在其中,毕竟我做的是我喜欢做的东西.今天特地抽空把怎么制作文本框写一下.同时也希望有爱好这些玩意的同 ...
- C#制作高仿360安全卫士窗体3
C#制作高仿360安全卫士窗体(三) 距上篇C#制作高仿360安全卫士窗体(二)也将近一个多月了,这个月事情还是像往常一样的多.不多我也乐在其中,毕竟我做的是我喜欢做的东西.今天特地抽空把怎么制作 ...
- Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”
Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...
- C#制作高仿360安全卫士窗体<二>
继上次C#制作高仿360安全卫士窗体<一>发布之后响应还不错,我的博客放肆雷特也来了不少的新朋友,在这里先谢谢大家的支持!我自己也反复看了一下觉得对不起大家,写的非常乱而且很少文字介绍.在 ...
- C#制作高仿360安全卫士窗体<一>
开始写这一系列博客之前先要向大家说声抱歉,放肆雷特建立很久却很少有更新.当然博客人气也不旺,大部分都是看的人多评论收藏的人少.一直想要改变这种状态,正好赶上了最近工作上做了一个高仿360安全卫士窗体. ...
随机推荐
- svn断开链接后,重新share提交代码报错
前言:svn怎样断开链接并清除干净请查看此地址-->android studio中断开SVN连接,并彻底清理项目中的.svn文件 1.每次把项目重新关联到新的svn地址上,我都抓狂一样的烦躁,因 ...
- AES-NI指令集
对于intel的AES-NI新指令集,需要i5处理器及以上的相关硬件支持.在编译时,可能会出现 /usr/lib/gcc/x86_64-linux-gnu/4.8/include/wmmintrin. ...
- 发送邮件 tp5.1 5.0都可以,实测有效
https://www.cnblogs.com/zhensg123/p/8954175.html 博客文章少了个Expection.php 文件; common.php <?php // 应用公 ...
- Python【pymysql】模块
import pymysql# 1.连上数据库 账号.密码 ip 端口号 数据库#2.建立游标#3.执行sql#4 .获取结果# 5.关闭游标#6.连接关闭coon = pymysql.connect ...
- ROI align解释
转自:blog.leanote.com/post/afanti.deng@gmail.com/b5f4f526490b ROI Align 是在Mask-RCNN这篇论文里提出的一种区域特征聚集方式, ...
- 64位Ubuntu 安装scrapy遇到的问题
这两天准备开始学习Python爬虫,安装scrapy框架后出现 Traceback (most recent call last): File "/usr/local/bin/scrapy& ...
- bzoj千题计划167:bzoj3527: [Zjoi2014]力
http://www.lydsy.com/JudgeOnline/problem.php?id=3527 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. 以n=4为例: ...
- ZeroMQ API(八) 异常&属性
1.错误处理 1.1 zmq_errno() 1.1.1 名称 zmq_errno - 为调用线程检索errno的值 1.1.2 概要 int zmq_errno(void); 1.1.3 描述 zm ...
- hive架构原理简析-mapreduce部分
整个处理流程包括主要包括,语法解析(抽象语法树,AST,采用antlr),语义分析(sematic Analyzer生成查询块),逻辑计划生成(OP tree),逻辑计划优化,物理计划生成(Task ...
- javamail模拟邮箱功能--邮件回复-中级实战篇【邮件回复方法】(javamail API电子邮件实例)
引言: JavaMai下载地址l jar包:http://java.sun.com/products/javamail/downloads/index.html 此篇是紧随上篇文章而封装出来的,阅读本 ...