通过构造系统服务分发实现拦截&过滤 (仿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安全卫士窗体. ...
随机推荐
- static的应用
静态变量.静态代码块.静态方法.非静态方法的区别: 执行顺序:静态变量和静态代码块是按照先后顺序执行的,即在类加载的时候就执行的,属于自动执行的.使用场景:就是一些全局常量,在开始的时候就需要加载的. ...
- 一个最简单的使用Entity Framework 查询SQL 数据库的例子
1.ADO.NET 3.5 Entity Framework是随着.net framework 3.5一起发布的,确认开发环境版本是大于等于3.5版本 2.确认已经安装了ADO.NET 3.5 Ent ...
- JSON学习笔记(总结自w3school)
1. JSON是一种文本. 2. JSON即JavaScript Object Notation(JavaScript对象表示法). JSON用来存储和交换文本信息. JSON比xml更小, 更快, ...
- ubuntu内核及系统升级
升级之前,需要先确认ubuntu当前系统版本,使用操作: root@Dy-JXQ-ubuntu-101:~# lsb_release -a No LSB modules are available. ...
- java基础-迭代器(Iterator)与增强for循环
java基础-迭代器(Iterator)与增强for循环 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Iterator迭代器概述 Java中提供了很多个集合,它们在存储元素时 ...
- Golang入门教程(一)GOPATH与工作空间(Windows)
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.2.md Windows 环境: 下面我就 ...
- SQL Server DB Link相关
若想通过DBlink 清空表或执行存储过程,可以通过这种方式 Insert into table select * from table时,Pull 方式比Push方式快很多
- 【Java】SSM框架整合 附源码
前言 前面已经介绍Spring和Mybatis整合,而本篇介绍在IDEA下Spring.Spring MVC.Mybatis(SSM)三个框架的整合,在阅读本篇之前,建议大家先去了解一下Spring. ...
- 在Linode VPS上搭建最新版Transmission
在Linode VPS上搭建最新版Transmission 2015-09-16 by Hansen 原文链接:http://www.hansendong.me/archives/124.html 以 ...
- 修复TortoiseGit文件夹和文件图标不显示问题的多种解决办法以及重启之后TortoiseGit图标注册表又不见了的解决办法
一 首先进行第一种尝试 打开 regedit.exe ,准备修改注册表 找到 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ ...