ring0 SSDTHook 实现x64/x86
#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的更多相关文章
- X32,X64,X86 代表什意义
X32,X64,X86是什么意思 各代表什么:X86指32位,X64指64位,现在用户最多的是XP,但win7是趋势,发展很快,建议你装个win7 32位的系统,下载的话地方很多,官方安装原版和gho ...
- protobuf-3.0.0-beta-2 windows编译 x64/x86
V3.0.0 beta2以及之后都是CMake 创建VS Solution,project. 因为只能创建x64的项目工程,有时候需要x86的, 只能创建完x64后,自己修改工程配置弄成x86. 创建 ...
- Windows10 1607 x64/x86 + Office 2016 Win/Mac + KMS激活/安装密钥汇总
各位观众,这里汇总了一份最新微软系统和办公软件的资源清单,希望对你们有帮助. Windows10 1607 For x64 ed2k://|file|cn_windows_10_multiple_ed ...
- ring0 SSDTHook
SSDT 的全称是 System Services Descriptor Table,系统服务描述符表.这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来. ...
- Windows 10 Creators Update [ISO官方镜像][15063][1703][x64][x86][创意者更新正式版]
请把下载地址手动复制到迅雷里面去,谢谢! [64 位简体中文专业/家庭版] 文件名:cn_windows_10_multiple_editions_version_1703_updated_march ...
- DllImport 自动选择x64或x86 dll
前言 标题不知道怎么确切地命名,在.net的托管世界里,有时不得不使用c的某个动态库,比如ocr.opencv等,如果幸运,有前人已经包装出.net版本,但有些不非常流行的库,只能自己使用pinvok ...
- 『开源重编译』System.Data.SQLite.dll 自适应 x86 x64 AnyCPU 重编译
背景: > System.Data.SQLite.dll 程序集 不能良好的支持 AngCPU 格式 System.Data.SQLite.dll 在 适应 x86 和 x64 有三个方案: & ...
- C# 关于X86/X64/AnyCpu 的关系
电脑硬件CPU可以分为x86与x64, x86的机器只能安装32位的操作系统,如XP, WIN7_86, x64的机器既可以安装32位的系统,又可以安装64位的系统,只是在x64的机器上安装32位的系 ...
- cmake构建时指定编译器架构(x86 or x64)
vs2015 x64编译器为例,cmake命令如下: cmake -G "Visual Studio 14 Win64" path\to\source\dir 去掉Win64,就是 ...
随机推荐
- datatables通过ajax调用渲染数据,怎么根据数据给td添加class
html: <table id="table8" cellpadding="0" cellspacing="0" border=&qu ...
- Python练习六十:网页分析,找出里面的正文与链接
网页分析,找出里面的正文与链接 代码如下: from urllib import request from bs4 import BeautifulSoup request = request.url ...
- win7旗舰版+caffe+vs2013+matlab2014b(无GPU版)
参考网站: http://www.cnblogs.com/njust-ycc/p/5776286.html 无法找到gpu/mxGPUArray.h: No such file or director ...
- android window(二)从getSystemService到WindowManagerGlobal
在Activity调用getSystemService(WINDOW_SERVICE) 调用的是父类ContextThemeWrapper package android.view; public c ...
- 安装Python + Selenium
1.Python下载与安装 先去Python官网下载安装包:http://www.python.org/ 下载后按步骤安装(最好不要安装到系统盘) 安装好后将安装路径(Python和Scripts) ...
- CAD安装失败怎样卸载CAD 2010?错误提示某些产品无法安装
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- PlayMaker 操作界面超级详细介绍
原文:https://www.indienova.com/u/christiantam/blogread/1214
- Textchangedlistener的用法
searchet.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequ ...
- CSS选择器笔记,element element和element > element 的区别
看官方解释 element element 例子: div p 官方解释:div内部所有的p元素 就是说 只要p在div内部.如果 p在span内部,span在div内部,p也算在div内部 < ...
- 转:MVC中的文件上传
上传文件与与上传数据区别 上传数据主要指json等简单字符串,上传文件指的是上传word.excel图片等.在上传数据的时候enctype默认为第一个application/x-www-form-ur ...