#include "HookSSDT.h"
#include <ntimage.h> #define SEC_IMAGE 0x001000000 ULONG32 __NtOpenProcessIndex = ;
PVOID __ServiceTableBase = NULL;
ULONG32 __OldNtOpenProcessOffset = ;
PVOID __OldNtOpenProcess = NULL;
UCHAR __OldCode[] = {};
BOOLEAN __IsHook = FALSE;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG32 v1 = ;
char FunctionName[] = "NtOpenProcess";
ULONG64 SSDTAddress = ;
DriverObject->DriverUnload = DriverUnload; if (GetSSDTAddress(&SSDTAddress) == FALSE)
{
return Status;
} DbgPrint("Win7x64 SSDT:%p\r\n", SSDTAddress); //寻找23H if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(FunctionName,
&__NtOpenProcessIndex) == FALSE)
{
return STATUS_UNSUCCESSFUL;
} __ServiceTableBase = ((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0;
__OldNtOpenProcessOffset = ((PULONG32)__ServiceTableBase)[__NtOpenProcessIndex];
v1 = __OldNtOpenProcessOffset >> ;
__OldNtOpenProcess = (PVOID)((ULONG64)__ServiceTableBase + v1);
HookSSDT(__ServiceTableBase,__NtOpenProcessIndex,FakeOpenProcess,KeBugCheckEx,,__OldCode,);
return Status;
} BOOLEAN GetSSDTAddress(ULONG64* SSDTAddress)
{
//kd> rdmsr c0000082
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + PAGE_SIZE;
PUCHAR i = NULL;
UCHAR v1 = , v2 = , v3 = ;
INT64 Offset = ; //002320c7
ULONG64 VariableAddress = ;
*SSDTAddress = NULL;
for (i = StartSearchAddress; i < EndSearchAddress; i++)
{
if (MmIsAddressValid(i) && MmIsAddressValid(i + ) && MmIsAddressValid(i + ))
{
v1 = *i;
v2 = *(i + );
v3 = *(i + );
if (v1 == 0x4c && v2 == 0x8d && v3 == 0x15)
{
memcpy(&Offset, i + , );
*SSDTAddress = Offset + (ULONG64)i + ;
break;
}
}
}
//Win32 导出表 搜索 KeServiceDescriptorTable
if (*SSDTAddress == NULL)
{
return FALSE;
} return TRUE;
}
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(CHAR* FunctionName,ULONG32* SSDTFunctionIndex)
{
/*
0:004> u zwopenprocess
ntdll!NtOpenProcess:
00000000`774ddc10 4c8bd1 mov r10,rcx
00000000`774ddc13 b823000000 mov eax,23h
00000000`774ddc18 0f05 syscall
00000000`774ddc1a c3 ret
00000000`774ddc1b 0f1f440000 nop dword ptr [rax+rax]
*/ ULONG i;
BOOLEAN IsOk = FALSE;
WCHAR FileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; //C:\Windows\
SIZE_T MappingViewSize = ;
PVOID MappingBaseAddress = NULL;
PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL;
PIMAGE_NT_HEADERS NtHeader = NULL;
UINT32* AddressOfFunctions = NULL;
UINT32* AddressOfNames = NULL;
UINT16* AddressOfNameOrdinals = NULL;
CHAR* v1 = NULL;
ULONG32 FunctionOrdinal = ;
PVOID FunctionAddress = ;
ULONG32 Offset_SSDTFunctionIndex = ;
//将Ntdll.dll 当前的空间中 *SSDTFunctionIndex = -;
IsOk = MappingPEFileInRing0Space(FileFullPath,&MappingBaseAddress, &MappingViewSize);
if (IsOk==FALSE)
{
return FALSE;
}
else
{
__try{
NtHeader = RtlImageNtHeader(MappingBaseAddress); //extern
if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
{
ImageExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((UINT8*)MappingBaseAddress +
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //AddressOfFunctions 指向函数地址数组
AddressOfFunctions = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfFunctions);
AddressOfNames = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNames);
AddressOfNameOrdinals = (UINT16*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
for(i = ; i < ImageExportDirectory->NumberOfNames; i++)
{
v1 = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]); //获得函数名称
if (_stricmp(FunctionName, v1) == )
{
FunctionOrdinal = AddressOfNameOrdinals[i];
FunctionAddress = (PVOID)((UINT8*)MappingBaseAddress + AddressOfFunctions[FunctionOrdinal]); *SSDTFunctionIndex = *(ULONG32*)((UINT8*)FunctionAddress+Offset_SSDTFunctionIndex);
break;
}
}
}
}__except(EXCEPTION_EXECUTE_HANDLER)
{
;
}
} ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); //解除映射 if (*SSDTFunctionIndex==-)
{
return FALSE;
} return TRUE;
}
BOOLEAN
MappingPEFileInRing0Space(WCHAR* FileFullPath,PVOID* MappingBaseAddress, PSIZE_T MappingViewSize)
{ NTSTATUS Status;
UNICODE_STRING v1;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle = NULL;
HANDLE SectionHandle = NULL; if (!FileFullPath &&MmIsAddressValid(FileFullPath))
{
return FALSE;
} if (!MappingBaseAddress&&MmIsAddressValid(MappingBaseAddress))
{
return FALSE;
} RtlInitUnicodeString(&v1, FileFullPath);
//初始化一个OBJECT_ATTRIBUTES结构体ObjectAttributes,它指定对象句柄的属性,供打开句柄的例程使用。
//驱动程序运行进程上下文中,若要运行在系统进程,需要设置OBJ_KERNEL_HANDLE标志到Attributes参数。
//OBJ_KERNEL_HANDLE标志限制,使用此打开的句柄的进程仅能运行在内核模式。否则句柄可以在驱动运行的进程上下文中访问。 InitializeObjectAttributes(&ObjectAttributes,
&v1,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
); //传递ObjectAttributes结构的指针到实际打开句柄的例程
//获得文件句柄
Status = IoCreateFile(&FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes, //文件绝对路径
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
,
CreateFileTypeNone,
NULL,
IO_NO_PARAMETER_CHECKING
);
if (!NT_SUCCESS(Status))
{
return FALSE;
} ObjectAttributes.ObjectName = NULL;
//创建一个Section Object ,即共享内存
Status = ZwCreateSection(&SectionHandle,
SECTION_QUERY | SECTION_MAP_READ,
&ObjectAttributes,
NULL,
PAGE_WRITECOPY,
SEC_IMAGE, //内存对齐 0x1000
FileHandle
);
/*NTSTATUS ZwCreateSection(
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
);*/
ZwClose(FileHandle);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
//生成一个可以访问的MappingBaseAddress
Status = ZwMapViewOfSection(SectionHandle,
NtCurrentProcess(), //映射到当前进程的内存空间中
MappingBaseAddress,
,
,
,
MappingViewSize,
ViewUnmap,
,
PAGE_WRITECOPY
);
ZwClose(SectionHandle);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
VOID HookSSDT(PVOID ServiceTableBase, ULONG32 SSDTFunctionIndex,PVOID FakeFunctionAddress,
PVOID OldFunctionAddress,ULONG32 OldFunctionParameterCount,UCHAR* OldFunctionCode,ULONG32 PatchCodeLength)
{
//寻找一个内核不常用的函数(KeBugCheckEx) 进行InlineHook使其跳转到Fake_NtOpenProcess函数
ULONG32 v1 = ; WPOFF();
// KeBugCheckEx
// mov rax,10 Jmp Fake 15
// mov rbx,rax
InlineHook(OldFunctionAddress, FakeFunctionAddress, OldFunctionCode, PatchCodeLength);
WPON(); //寻找一个内核不常用的函数(KeBugCheckEx) 计算SSDT中的偏移 进行置换 v1 = CalcFunctionOffsetInSSDT(ServiceTableBase,OldFunctionAddress, OldFunctionParameterCount); WPOFF();
((PULONG32)ServiceTableBase)[SSDTFunctionIndex] = (ULONG32)v1;
WPON(); __IsHook = TRUE;
}
VOID
UnHookSSDT(PVOID ServiceTableBase, ULONG32 SSDTFunctionIndex,ULONG32 OldFunctionOffset,PVOID OldFunctionAddress,
UCHAR* OldFunctionCode,ULONG32 PatchCodeLength)
{ WPOFF();
UnInlineHook(OldFunctionAddress, OldFunctionCode, PatchCodeLength);
WPON(); WPOFF();
((PULONG32)ServiceTableBase)[SSDTFunctionIndex] = (ULONG32)OldFunctionOffset;
WPON();
} VOID InlineHook(ULONG64 OldFunctionAddress, ULONG64 FakeFunctionAddress, UCHAR* OldFunctionCode, ULONG32 PatchCodeLength)
{ ULONG64 v1 = ;
UCHAR PatchCode[] = "\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; //InlineHook Jmp 函数地址
v1 = FakeFunctionAddress;
memcpy(OldFunctionCode, (PVOID)OldFunctionAddress, PatchCodeLength); //保存原先函数的指令
memcpy(PatchCode + , &v1, ); memset((PVOID)OldFunctionAddress, 0x90, PatchCodeLength); //打补丁 NOP = 0x90
memcpy((PVOID)OldFunctionAddress, PatchCode, );
}
VOID UnInlineHook(PVOID OldFunctionAddress, UCHAR* OldFunctionCode, ULONG32 PatchCodeLength)
{
memcpy((PVOID)OldFunctionAddress, OldFunctionCode, PatchCodeLength);
} ULONG32 CalcFunctionOffsetInSSDT(PVOID ServiceTableBase, PVOID FunctionAddress,ULONG32 ParameterCount)
{
//v1 : INT8 Temp = 0
CHAR v1 = ;
CHAR Bits[] = {};
ULONG32 v2 = ,i;
v2 = (ULONG32)((ULONG64)FunctionAddress-(ULONG64)ServiceTableBase);
v2 = v2<<; //0110 0001 a1 ----> 0001 0000
if(ParameterCount>)
{
ParameterCount = ParameterCount-; //NtReadFile 9个参数
}
else
{
ParameterCount = ;
} memcpy(&v1,&v2,);
//处理低四位,填写参数个数 如果一个函数的参数为5 那么dwTemp的低4位就是 0001 如果参数是6 就是0002 因为 6要减4 #define SETBIT(x,y) x|=(1<<y) //将X的第Y位置1
#define CLRBIT(x,y) x&=~(1<<y) //将X的第Y位清0
#define GETBIT(x,y) (x & (1 << y)) //取X的第Y位,返回0或非0 for(i=;i<;i++) //一个16进制 4个二进制 0000
{
Bits[i]=GETBIT(ParameterCount,i);
if(Bits[i])
{
SETBIT(v1,i);
}
else
{
CLRBIT(v1,i);
}
}
/*
ulParamCount i Bits[i] b i b
0101 0 1 0000 0 0001 set
0101 1 0 0001 1 0001 clr
0101 2 1 0001 2 0101 set
0101 3 0 0101 3 0101 clr */
//把数据复制回去
memcpy(&v2,&v1,);
return v2;
} NTSTATUS FakeOpenProcess(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientID)
{ //EnumProcessByForce.exe
//OpenProcess---->Ntdll(ZwOpenProcess eax,23H syscall)----->NtosKrnl.exe(ZwOpenProcss eax,23H SSDT[23H])----->KeCheckBugEx---->Jmp FakeOpenProcess PEPROCESS EProcess = PsGetCurrentProcess(); //EnumProcessByForce进程上下背景文
if (EProcess != NULL&&MmIsAddressValid(EProcess))
{
//通过EProcess 获得进程名称 char *ProcessImageName = PsGetProcessImageFileName(EProcess); //0x2e0
if (strstr(ProcessImageName, "EnumProcess") != )
{
return STATUS_ACCESS_DENIED; //黑名单
}
} ((pfnNtOpenProcess)__OldNtOpenProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientID); //白名单
} VOID WPOFF()
{
_disable();
__writecr0(__readcr0() & (~(0x10000))); }
VOID WPON()
{
__writecr0(__readcr0() ^ 0x10000);
_enable();
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DbgPrint("ByeByeDriver\r\n"); if (__IsHook)
{
UnHookSSDT(__ServiceTableBase, __NtOpenProcessIndex, __OldNtOpenProcessOffset, KeBugCheckEx,
__OldCode, ); __IsHook = FALSE;
} }
#pragma once
#include <ntddk.h> typedef struct _SERVER_SERVICE_DESCRIPTOR_TABLE_
{
PVOID Unknow0;
PVOID Unknow1;
PVOID Unknow2;
PVOID Unknow3;
}SERVER_SERVICE_DESCRIPTOR_TABLE, *PSERVER_SERVICE_DESCRIPTOR_TABLE; typedef
NTSTATUS(*pfnNtOpenProcess)(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientID); extern
PIMAGE_NT_HEADERS
NTAPI
RtlImageNtHeader(PVOID BaseAddress); extern
char* PsGetProcessImageFileName(PEPROCESS EProcess); BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(
CHAR* FunctionName,
ULONG32* SSDTFunctionIndex);
BOOLEAN
MappingPEFileInRing0Space(WCHAR* FileFullPath, PVOID* MappingBaseAddress, PSIZE_T MappingViewSize);
BOOLEAN GetSSDTAddress(ULONG64* SSDTAddress);
VOID HookSSDT(PVOID ServiceTableBase, ULONG32 SSDTFunctionIndex, PVOID FakeFunctionAddress);
ULONG32 CalcFunctionOffsetInSSDT(PVOID ServiceTableBase, PVOID FunctionAddress, ULONG32 ParameterCount); VOID HookSSDT(PVOID ServiceTableBase, ULONG32 SSDTFunctionIndex, PVOID FakeFunctionAddress,
PVOID OldFunctionAddress, ULONG32 OldFunctionParameterCount, UCHAR* OldFunctionCode, ULONG32 PatchCodeLength);
VOID
UnHookSSDT(PVOID ServiceTableBase, ULONG32 SSDTFunctionIndex, ULONG32 OldFunctionOffset, PVOID OldFunctionAddress,
UCHAR* OldFunctionCode, ULONG32 PatchCodeLength); VOID InlineHook(ULONG64 OldFunctionAddress, ULONG64 FakeFunctionAddress, UCHAR* OldFunctionCode, ULONG32 PatchCodeLength);
VOID UnInlineHook(PVOID OldFunctionAddress, UCHAR* OldFunctionCode, ULONG32 PatchCodeLength); NTSTATUS FakeOpenProcess(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientID);
VOID WPOFF();
VOID WPON();
VOID DriverUnload(PDRIVER_OBJECT DriverObject);

ring0 SSDTHook 实现x64/x86的更多相关文章

  1. X32,X64,X86 代表什意义

    X32,X64,X86是什么意思 各代表什么:X86指32位,X64指64位,现在用户最多的是XP,但win7是趋势,发展很快,建议你装个win7 32位的系统,下载的话地方很多,官方安装原版和gho ...

  2. protobuf-3.0.0-beta-2 windows编译 x64/x86

    V3.0.0 beta2以及之后都是CMake 创建VS Solution,project. 因为只能创建x64的项目工程,有时候需要x86的, 只能创建完x64后,自己修改工程配置弄成x86. 创建 ...

  3. Windows10 1607 x64/x86 + Office 2016 Win/Mac + KMS激活/安装密钥汇总

    各位观众,这里汇总了一份最新微软系统和办公软件的资源清单,希望对你们有帮助. Windows10 1607 For x64 ed2k://|file|cn_windows_10_multiple_ed ...

  4. ring0 SSDTHook

    SSDT 的全称是 System Services Descriptor Table,系统服务描述符表.这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来. ...

  5. Windows 10 Creators Update [ISO官方镜像][15063][1703][x64][x86][创意者更新正式版]

    请把下载地址手动复制到迅雷里面去,谢谢! [64 位简体中文专业/家庭版] 文件名:cn_windows_10_multiple_editions_version_1703_updated_march ...

  6. DllImport 自动选择x64或x86 dll

    前言 标题不知道怎么确切地命名,在.net的托管世界里,有时不得不使用c的某个动态库,比如ocr.opencv等,如果幸运,有前人已经包装出.net版本,但有些不非常流行的库,只能自己使用pinvok ...

  7. 『开源重编译』System.Data.SQLite.dll 自适应 x86 x64 AnyCPU 重编译

    背景: > System.Data.SQLite.dll 程序集 不能良好的支持 AngCPU 格式 System.Data.SQLite.dll 在 适应 x86 和 x64 有三个方案: & ...

  8. C# 关于X86/X64/AnyCpu 的关系

    电脑硬件CPU可以分为x86与x64, x86的机器只能安装32位的操作系统,如XP, WIN7_86, x64的机器既可以安装32位的系统,又可以安装64位的系统,只是在x64的机器上安装32位的系 ...

  9. cmake构建时指定编译器架构(x86 or x64)

    vs2015 x64编译器为例,cmake命令如下: cmake -G "Visual Studio 14 Win64" path\to\source\dir 去掉Win64,就是 ...

随机推荐

  1. javascript 获取当前 URL 参数的两种方法

    window.location.host; //返回url 的主机部分,例如:www.xxx.com window.location.hostname; //返回www.xxx.com window. ...

  2. ST表(查询区间最值问题)

    ST表与线段树相比,这是静态的,无法改动,但是他的查询速度比线段树要快,这是牺牲空间换时间的算法. O(nlogn)预处理,O(1)查询.空间O(nlogn). ][]; ]; void rmq_in ...

  3. codeforces 620D Professor GukiZ and Two Arrays

    #include <bits/stdc++.h> using namespace std; + ; const long long inf = 1e18; int n, m; long l ...

  4. hdu2068 RPG的错排

    RPG的错排 时间限制:1000/1000 MS(Java / Others)内存限制:32768/32768 K(Java / Others)总提交内容:16421接受的提交内容:6670 问题描述 ...

  5. Photoshop入门教程(五):滤镜

    学习心得:滤镜通常用于摄影行业,是安装在相机镜头前用于过滤自然光的附加镜头,从而获得一些特殊的效果.同理,Photoshop的滤镜也是为了产生特殊的效果.Photoshop滤镜分为两类:一种是内部滤镜 ...

  6. navicat premiun连接mysql数据库报错,错误代码:1251

    今天在电脑上安装了Mysql 8.0.11,然后想用 Navicat Premium连接数据库,结果报错了: error 1251:client does not support authentica ...

  7. 在vue2.x中安装sass并配置

    在vue中安装sass先检查系统中有没有安装sass,在命令行中输入 sass -v 表示sass在电脑中已有,否者可以参考我这篇博客安装Sass遇到的坑 一.先安装sass cmd打开命令行,到项目 ...

  8. 从零开始使用vue-cli搭建一个vue项目及注意事项

    一.安装node.js 1.根据电脑的自行下载node.js安装包http://nodejs.cn 2.点击安装,按照正常的的一路点击下去 3.验证安装是否成功,按键win+r,输入cmd打开命令行工 ...

  9. JS中==、===和Object.is()的区别

    JS中==.===和Object.is()的区别 首先,先粗略了解一下这三个玩意儿: ==:等同,比较运算符,两边值类型不同的时候,先进行类型转换,再比较: ===:恒等,严格比较运算符,不做类型转换 ...

  10. python_元组 学习

    一.创建元组 代码: name=(‘chinese’,’gansu’,’beijing’) 创建空元组 name=() 元组中只包含一个元素时,需要在玄素后面加逗号(,)消除歧义: name=(‘ch ...