阻止反外挂GPK/sys加载思路
思路建议:
sys 驱动加载之前,要 CreateService ,试试拦截这个api?或者更底层?
不重启的话,Hook ZwLoadDriver,ZwSetSysteminformation基本就差不多了
createservice,zwloaddriver,zwsetsysteminformation
开发工具: C-C++
另类阻止驱动加载(转)
关于驱动的加载大概有几种方法
1 在WINDOWS下动态加载
2 在WINDOWS启动的时候加载
3 感染系统文件
对于 在WINDOWS启动的时候加载 和 感染系统文件 我们暂时不讨论,玩么只讨论动态加载
一般的加载流程,是这样的:打开服务管理器->创建服务->启动服务->(系统加载驱动)
这个过程系统最终会调用NtLoadDriver来加载驱动(也可以用Ntdll.dll里面的NtSetSystemInformation来加载)
而NtLoadDriver 会向系统插入一个作业,然后等待另外一个系统线程来加载驱动,并等待驱动的加载完成(NtSetSystemInformation也是一样的),然后返回
这样我们就可以HOOK NtLoadDriver和NtSetSystemInformation来阻止驱动加载,但是这个方法已经用烂了,这里我HOOK NtCreateSection来阻止驱动加载
为什么HOOK NtCreateSection呢???
因为在另外一个线程取得消息加载驱动的时候会调用NtCreateSection来映射驱动到内核内存空间
(流程:大概是这样 IoCreateFile(打开驱动文件,将它的第二个参数设置为FILE_EXECUTE | SYNCHRONIZE) -> NtCreateSection(为驱动在内核内存空间创建一个节) ->NtMapViewOfSection(映射驱动到内核内存空间) -> 寻找驱动的DriverEntry,并调用 -> ZwClose(关闭文件句柄) ->然后通知NtLoadDriver(或者NtSetSystemInformation)驱动加载完成->NtLoadDriver(或者NtSetSystemInformation)返回用户层,并通知用户驱动加载完成)
在驱动加载流程中,我们可以看到我们有很多机会劫持驱动的加载
我们可以HOOK NtCreateSection 或者 NtMapViewOfSection 来阻止驱动加载
这里我采用HOOK NtCreateSection的办法阻止驱动加载
以下为代码
#include <ntifs.h>
//声明用到的头文件和结构 宏等
#include "NtCreateSection.h"
#if DBG
#define DriversUnload(Address, p) \
Address->DriverUnload=p;
#else
#define DriversUnload(Address, p) \
Address->DriverUnload=NULL;
#endif
typedef int BOOL;
typedef unsigned int UINT;
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef void *LPVOID;
typedef unsigned char BYTE;
typedef DWORD *PDWORD;
typedef BYTE *PBYTE;
typedef WORD *PWORD;
#define PAGE_NOACCESS 0x01
#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
#define MEM_DECOMMIT 0x4000
#define MEM_RELEASE 0x8000
#define MEM_FREE 0x10000
#define MEM_PRIVATE 0x20000
#define MEM_MAPPED 0x40000
#define MEM_RESET 0x80000
#define MEM_TOP_DOWN 0x100000
#define MEM_4MB_PAGES 0x80000000
#define SEC_FILE 0x800000
#define SEC_IMAGE 0x1000000
#define SEC_VLM 0x2000000
#define SEC_RESERVE 0x4000000
#define SEC_COMMIT 0x8000000
#define SEC_NOCACHE 0x10000000
#define MEM_IMAGE SEC_IMAGE
PVOID WriteAddress=NULL;
PMDL pMdl=NULL;
//声明所需要的函数
NTSYSAPI
NTSTATUS
NTAPI
ZwYieldExecution(
VOID
);
PVOID NTAPI GetJmpAddress(PVOID Fun,BOOL *Call_Code);
NTSTATUS
NTAPI
CallBack_NtCreateSection (
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
);
NTSTATUS
NTAPI
OldNtCreateSection (
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
);
void makejmp(LPVOID Fun1,LPVOID Fun2,LPVOID jmp);
#pragma alloc_text(PAGE,makejmp)
#pragma alloc_text(PAGE,OldNtCreateSection)
#pragma alloc_text(PAGE,CallBack_NtCreateSection)
#pragma alloc_text(PAGE,GetJmpAddress)
//所有声明结束
//驱动入口
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
//创建设备,这个就不讲解了,大家明白就好,我重点讲解HOOK过程
Status = IoCreateDevice(
DriverObject,
0,
NULL,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDeviceObject
);
if ( NT_SUCCESS(Status) ) {
KIRQL oldIrql;
PVOID HookAddress = NULL;
BOOL Hook=0;
PVOID JmpData=ExAllocatePool(NonPagedPool,5);//申请内存,用来保存内容为Jmp CallBack_NtCreateSection的代码
DriversUnload(DriverObject,Unload);//设置DriverObject->DriverUnload = Unload;这个宏只有在调试版本的时候才会设置
//DriverObject->DriverUnload = Unload;如果不是调试版本,就会设置DriverObject->DriverUnload = NULL;
if(JmpData==NULL)
{
DbgPrint("HOOK NtCreateSection失败! 内存申请失败\n");
return Status;
}
memset(JmpData,0x90,5);//初始化JmpData内容为NOP
//将NtCreateSection的头7个字节复制到OldNtCreateSection中来
pMdl=IoCreateWriteMdlForAddress(OldNtCreateSection,&WriteAddress,7);
if(pMdl==NULL)
{
DbgPrint("HOOK NtCreateSection失败! OldNtCreateSection 写入失败\n");
ExFreePool(JmpData);
JmpData=NULL;
WriteAddress=NULL;
pMdl=NULL;
return Status;
}
memcpy(WriteAddress,NtCreateSection,7);
IoFreeMdlForAddress(WriteAddress,pMdl);
WriteAddress=NULL;
//将NtCreateSection的头5字节变成可写
pMdl=IoCreateWriteMdlForAddress(NtCreateSection,&WriteAddress,7);
if(pMdl==NULL)
{
DbgPrint("HOOK NtCreateSection失败! NtCreateSection 写入失败\n");
ExFreePool(JmpData);
JmpData=NULL;
WriteAddress=NULL;
pMdl=NULL;
return Status;
}
//检查是否已经被别人HOOK,如果已经被别人HOOK则我们退出HOOK,这里是可以改进的,但是我没有时间写,只能退出HOOK
HookAddress=GetJmpAddress(NtCreateSection,&Hook);
if(HookAddress!=NULL)
{
DbgPrint("HOOK NtCreateSection失败! 发现NtCreateSection已经被别人HOOK 所以本HOOK退出\n");
ExFreePool(JmpData);
JmpData=NULL;
IoFreeMdlForAddress(WriteAddress,pMdl);
WriteAddress=NULL;
pMdl=NULL;
return Status;
}
//HOOK NtCreateSection
if(NT_SUCCESS(ZwYieldExecution()))//先向系统申请CPU时间
{
_asm cli//关闭中断
oldIrql = KeRaiseIrqlToDpcLevel();//提升到DPC级别
memset(WriteAddress,0x90,7);//修改NtCreateSection的前7个字节为NOP指令
makejmp(NtCreateSection,CallBack_NtCreateSection,JmpData);//取得 Jmp CallBack_NtCreateSection的代码,代码保存在JmpData中
memcpy(WriteAddress,JmpData,5);//修改NtCreateSection前5个字节为 Jmp CallBack_NtCreateSection
KeLowerIrql(oldIrql);//还原到原来的IRQL级别
_asm sti//开中断
}else
{
DbgPrint("申请CPU时间失败,HOOK退出\n");
}
ExFreePool(JmpData);
JmpData=NULL;
}
return Status;
}
//我们的NtCreateSection过滤函数
NTSTATUS
NTAPI
CallBack_NtCreateSection (
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
)
{
NTSTATUS Status = 0;
Status = OldNtCreateSection(
SectionHandle,
DesiredAccess,
ObjectAttributes ,
MaximumSize ,
SectionPageProtection,
AllocationAttributes,
FileHandle);
if ( NT_SUCCESS(Status) )
{
//进行行为判断,如果是要加载驱动,我们就直接返回错误,并关闭句柄,如果不是就返回原来的结果
if(((DWORD)PsGetCurrentProcessId()==(DWORD)4)|((DWORD)PsGetCurrentProcessId()==(DWORD)8)|((DWORD)PsGetCurrentProcessId()==(DWORD)0))
{
if((FlagOn(DesiredAccess,SECTION_MAP_EXECUTE))||(FlagOn(DesiredAccess,PAGE_EXECUTE_READ)))
if((PAGE_EXECUTE==SectionPageProtection)|(AllocationAttributes==SEC_IMAGE))
{
ZwClose(*SectionHandle);
*SectionHandle=NULL;
return STATUS_ACCESS_DENIED;
}
}
}
return Status;
}
//用来跳转到原函数的一个裸函数
__declspec(naked)NTSTATUS
NTAPI
OldNtCreateSection (
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
)
{
_asm
{
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
mov eax,NtCreateSection //将原函数地址送入eax
add eax,7 //eax加7,用来跳过我们的HOOK
push eax //将eax压入
ret //跳回原函数
}
}
//用来生成跳转代码的函数
void makejmp(LPVOID Fun1,LPVOID Fun2,LPVOID jmp)
{
BYTE *data=(BYTE *)jmp;
long dFun1=(long)Fun1;
long dFun2=(long)Fun2;
DWORD H;
data[0]=0xe9;
_asm
{
mov eax,dFun1
mov edx,dFun2
sub edx,eax
sub edx,5
mov H,edx
}
memcpy(&data[1],(void *)&H,4);
}
VOID Unload(
IN PDRIVER_OBJECT DriverObject
)
{
KIRQL oldIrql;
while(!NT_SUCCESS(ZwYieldExecution()))//取得CPU时间,如果取得失败,就一直获取,直到成功
{
}
if(pMdl!=NULL)//检查我们是否已经进行过HOOK,//如果我们进行过HOOK 就还原
{
oldIrql = KeRaiseIrqlToDpcLevel();
memcpy(WriteAddress,OldNtCreateSection,7);
KeLowerIrql(oldIrql);
IoFreeMdlForAddress(WriteAddress,pMdl);
}
IoDeleteDevice(DriverObject->DeviceObject);//删除设备
pMdl=NULL;
WriteAddress=NULL;
}
PVOID NTAPI GetJmpAddress(PVOID Fun,BOOL *Call_Code)
{
PVOID Return=NULL;
BYTE *data=(BYTE *)Fun;
DWORD Old=0;
if(data[0]==0xe9)
{
*Call_Code=0;
}else if (data[0]==0xe8)
{
*Call_Code=1;
}else
{
*Call_Code=2;
return NULL;
}
memcpy((void *)&Old,&data[1],4);
_asm
{
mov eax,Old
mov edx,Fun
add eax,edx
add eax,5
mov Return,eax
}
return Return;
}
这个驱动只支持单核心CPU 多核心CPU请自行修改(将所有CPU都提升到DPC级别 以后再进行HOOK)驱动加载流程是看了WIN2K的代码来讲的,WIN2K的代码很长,所以就简单的讲了一下
阻止反外挂GPK/sys加载思路相关推荐
- 反沙箱CobaltStrike木马加载器分析
总结 1.计算Sleep类函数延时时间与实际流逝时间是否匹配可判断环境是否为正常.对沙箱来说,跳过Sleep节约时间成本是有必要的不可省去,但可适当处理GetTickCount类函数,使其与延时时间匹 ...
- vfatfs.sys加载
在DriverEntry中,创建了一个device,并调用IoRegisterFileSystem,将它注册到文件系统类型中. 每个分区类型驱动加载时候,都会调用IoRegisterFileSyste ...
- ios App启动加载广告页面思路
需求 很多app(如淘宝.美团等)在启动图加载完毕后,还会显示几秒的广告,一般都有个跳过按钮可以跳过这个广告,有的app在点击广告页之后还会进入一个广告页面,点击返回进入首页.虽然说这个广告页面对用户 ...
- 关于App启动加载广告页面思路
需求 很多app(如淘宝.美团等)在启动图加载完毕后,还会显示几秒的广告,一般都有个跳过按钮可以跳过这个广告,有的app在点击广告页之后还会进入一个广告页面,点击返回进入首页.虽然说这个广告页面对用户 ...
- 懒加载原理以及实现思路
懒加载的优点 提高前端性能,按需加载图片减轻服务器负担,提高页面加载速度. 懒加载的原理 图片的加载是依赖于src路径,我们可以设置一个暂存器,把图片路劲放到暂存器中,当我们需要这个图片加载显示时,再 ...
- Android动态加载黑科技 动态创建Activity模式
基本信息 Author:kaedea GitHub:android-dynamical-loading 代理Activity模式的限制 还记得我们在代理Activity模式里谈到启动插件APK里的Ac ...
- 晨枫U盘维护工具的ISOLINUX模式可加载磁盘映像的探索及USB-ROM引导后安装系统的相关问题
哎呀,标题似乎写的好乱,以后心情静下来在整理吧.乱七八糟的.~~~ --大头爸爸2010-12-9注 怎么说呢,为了突出这篇文章目的,废话少说,直接将今天一天的调试情况记录一下. 我的目的就是在&qu ...
- webpack 异步加载配置文件_Webpack 是怎样运行的?
在平时开发中我们经常会用到Webpack这个时下最流行的前端打包工具.它打包开发代码,输出能在各种浏览器运行的代码,提升了开发至发布过程的效率. 我们知道一份Webpack配置文件主要包含入口(ent ...
- Android Fragment懒加载
懒加载思路 在Fragment布局创建的时候调用懒加载方法,创建之后将isViewPrepared设置为true. /**标记Fragment视图是否已经初始化完毕*/private boolean ...
最新文章
- linux C 多线程编程
- 上当记,收国外快递时,注意相关责任定义
- Nginx + Spring Boot 实现负载均衡
- xp里删除不想要的删不掉的帐户
- Linux经典实用的使用技巧33则和常用60个命令
- 读者来信(1)——项目经理,不要迷信制度!
- 关于监听UITextField的问题
- 更新MySQL复制 自动监控脚本
- ubuntu环境下lnmp环境搭建(3)之Php
- php 中文字符串截取函数--比较好的
- 前端之路:平凡中的小事,有点鸡汤的感觉哟!
- angular cli中的--flat参数
- Linux Cgroups详解(一)
- 《MBA一日读2.0 读书笔记》
- 电脑插入耳机未识别的问题
- 关于PV、EV、AC、CV、SV、CPI、SPI、BAC、ETC、EAC的解析及计算
- 分位数回归模型学习笔记
- Web项目【用户管理系统】完整版
- 输入分数,判断成绩等级(使用if和switch两种方法)
- 阿里云国际站:java应用提速(速度与激情)
热门文章
- 家政公司为什么需要小程序来获客
- 1、orbslam2 安装与运行
- wps excel中如何实现替换换行(换行符如何打出来放到替换文本框中去)
- asp如何将图片文件上传到mysql数据库中_ASP图片上传[图片直接存储在数据库里面]...
- python学习笔记:读取xyz文件
- 苹果数据记录之详细让人不寒而栗
- 联想服务器固态硬盘吗,联想加快度超级硬盘升级服务,他们的固态硬盘比一般的好吗?...
- sql server 2008 刷新缓存
- 我的世界服务器 显示合成指令,我的世界的各种指令大家知道多少给我多少吧,我正在做服务器,求命令方块或对话框的指令...
- 编译时异常与运行时异常的区别