Win64 驱动内核编程-20.UnHook SSDT
UNHOOK SSDT
要恢复 SSDT,首先要获得 SSDT 各个函数的原始地址,而 SSDT 各个函数的原始地址,自然是存储在内核文件里的。于是,有了以下思路:
1.获得内核里 KiServiceTable 的地址(变量名称:KiServiceTable)
2.获得内核文件在内核里的加载地址(变量名称:NtosBase)
3.获得内核文件在 PE32+结构体里的映像基址(变量名称:NtosImageBase)
4.在自身进程里加载内核文件并取得映射地址(变量名称:NtosInProcess)
5.计算出 KiServiceTable 和 NtosBase 之间的“距离”(变量名称:RVA)
6.获得指定 INDEX 函数的地址(计算公式:*(PULONGLONG)(NtosInProcess + RVA
+ 8 * index) - NtosImageBase + NtosBase)
第六步的计算原理:
上面公式需要好好理解下,我卡在一个地方卡了好久,就是
NtosBase + RVA = KiServiceTable
NtosInProcess + RVA = 是一个地址,这个地址存的是存数组地址的。还是相对于文件的基址的。我一直觉得因为都是load到了内存:
NtosBase + RVA = NtosInProcess + RVA
因为之前我认为只有在文件里才会存在FOA地址什么的,一担load了之后就自动修改了。根据相关桥自动修改了。结果看这个样子并不是我想的那样,load之后依然是相对于文件基址的地址而不是和NtosBase + RVA = KiServiceTable一样。这个后期整清楚了我在补充吧。但是已经验证了,资料上的公式是正确的。
接下来是细化每一个地方(下面的代码是我从资料里整理过来的,如果是要实际使用,记得重新整理并且改改,比如内存泄漏问题,比如很多东西都有函数代替不用咱们模拟,代码会精简许多)。
驱动部分代码:
MyDriver.h
#include <ntddk.h>
#define dprintf if (DBG) DbgPrint
#define DEVICE_NAME L"\\Device\\MyDriver"
#define LINK_NAME L"\\DosDevices\\MyDriver"
#define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\MyDriver"
#define IOCTL_ClrSSDTHOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) //Clear ssdt hook
#define IOCTL_GetKiSrvTab CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) //Get KiServiceTable
#define IOCTL_GetFuncAddr CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) //Get function address
#define IOCTL_GetTest CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) //test
MyDriver.cpp
#include <ntddk.h>
#include <windef.h>
#include "MyDriver.h"
#pragma intrinsic(__readmsr)
typedef struct _SYSTEM_SERVICE_TABLE{
PVOID ServiceTableBase;
PVOID ServiceCounterTableBase;
ULONGLONG NumberOfServices;
PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef struct _UNHOOK_SSDT64{
ULONGLONG Address;
ULONGLONG id;
}UNHOOK_SSDT64,*PUNHOOK_SSDT64;
typedef UINT64 (__fastcall *SCFN)(UINT64,UINT64);
SCFN scfn;
ULONGLONG ssdt_base_aadress, ssdt_func_address, KiServiceTable;
ULONG32 ssdt_func_index;
UNHOOK_SSDT64 uhssdt64={0};
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
ULONGLONG GetKeServiceDescriptorTable64()
{
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
UCHAR b1 = 0, b2 = 0, b3 = 0;
ULONG templong = 0;
ULONGLONG addr = 0;
for (i = StartSearchAddress; i<EndSearchAddress; i++)
{
if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
{
b1 = *i;
b2 = *(i + 1);
b3 = *(i + 2);
if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
{
memcpy(&templong, i + 3, 4);
addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
return addr;
}
}
}
return 0;
}
KIRQL WPOFFx64()
{
KIRQL irql=KeRaiseIrqlToDpcLevel();
UINT64 cr0=__readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
return irql;
}
void WPONx64(KIRQL irql)
{
UINT64 cr0=__readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
KeLowerIrql(irql);
}
ULONG GetOffsetAddress(ULONGLONG FuncAddr)
{
ULONG dwtmp=0;
PULONG ServiceTableBase=NULL;
if(KeServiceDescriptorTable==NULL)
KeServiceDescriptorTable=(PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
dwtmp=(ULONG)(FuncAddr-(ULONGLONG)ServiceTableBase);
return dwtmp<<4;
}
VOID UnHookSSDT(ULONG id, ULONGLONG FuncAddr)
{
KIRQL irql;
ULONG dwtmp;
PULONG ServiceTableBase=NULL;
dwtmp=GetOffsetAddress(FuncAddr);
ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
irql=WPOFFx64();
ServiceTableBase[id]=dwtmp;
WPONx64(irql);
}
ULONGLONG GetSSDTFunctionAddress64(ULONGLONG NtApiIndex)
{
LONG dwTemp = 0;
ULONGLONG qwTemp = 0, stb = 0, ret = 0;
PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
stb = (ULONGLONG)(ssdt->ServiceTableBase);
qwTemp = stb + 4 * NtApiIndex;
dwTemp = *(PLONG)qwTemp;
dwTemp = dwTemp >> 4;
ret = stb + (LONG64)dwTemp;
return ret;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
UNICODE_STRING strLink;
RtlInitUnicodeString(&strLink, LINK_NAME);
IoDeleteSymbolicLink(&strLink);
IoDeleteDevice(pDriverObj->DeviceObject);
DbgPrint("[my driver]:DriverUnload\n");
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode;
PVOID pIoBuffer;
ULONG uInSize;
ULONG uOutSize;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(uIoControlCode)
{
case IOCTL_ClrSSDTHOOK:
{
memcpy(&uhssdt64, pIoBuffer, sizeof(UNHOOK_SSDT64));
UnHookSSDT((ULONG)uhssdt64.id, uhssdt64.Address);
status = STATUS_SUCCESS;
break;
}
case IOCTL_GetKiSrvTab:
{
if(ssdt_base_aadress==0)
ssdt_base_aadress=GetKeServiceDescriptorTable64();
KiServiceTable=*(PULONGLONG)ssdt_base_aadress;
memcpy(pIoBuffer, &KiServiceTable, 8);
status = STATUS_SUCCESS;
break;
}
case IOCTL_GetFuncAddr:
{
memcpy(&ssdt_func_index, pIoBuffer, 4);
ssdt_func_address=GetSSDTFunctionAddress64((ULONGLONG)ssdt_func_index);
memcpy(pIoBuffer, &ssdt_func_address, 8);
status = STATUS_SUCCESS;
break;
}
case IOCTL_GetTest:
{
DbgPrint("[my driver]:IoControl is OK \n");
break;
}
}
if(status == STATUS_SUCCESS)
pIrp->IoStatus.Information = uOutSize;
else
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
DbgPrint("[my driver]:DriverEntry\n");
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ustrLinkName;
UNICODE_STRING ustrDevName;
PDEVICE_OBJECT pDevObj;
pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
pDriverObj->DriverUnload = DriverUnload;
RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
if(!NT_SUCCESS(status)) return status;
if(IoIsWdmVersionAvailable(1, 0x10))
RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME);
else
RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
if(!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
return status;
}
return STATUS_SUCCESS;
}
安装部分代码:
ScmDrvCtrl.h
#pragma comment(lib,"advapi32.lib")
class cDrvCtrl
{
public:
cDrvCtrl()
{
m_pSysPath = NULL;
m_pServiceName = NULL;
m_pDisplayName = NULL;
m_hSCManager = NULL;
m_hService = NULL;
m_hDriver = INVALID_HANDLE_VALUE;
}
~cDrvCtrl()
{
if (m_hService) {
CloseServiceHandle(m_hService);
}
if (m_hSCManager) {
CloseServiceHandle(m_hSCManager);
}
if (m_hDriver) {
CloseHandle(m_hDriver);
}
}
public:
DWORD m_dwLastError;
PCHAR m_pSysPath;
PCHAR m_pServiceName;
PCHAR m_pDisplayName;
HANDLE m_hDriver;
SC_HANDLE m_hSCManager;
SC_HANDLE m_hService;
public:
BOOL Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName);
BOOL Start();
BOOL Stop();
BOOL Remove();
BOOL Open(PCHAR pLinkName);
BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes);
BOOL IoControl(HANDLE hDrvHandle, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize);
private:
BOOL GetSvcHandle(PCHAR pServiceName);
DWORD CTL_CODE_GEN(DWORD lngFunction);
protected:
//null
};
BOOL cDrvCtrl::GetSvcHandle(PCHAR pServiceName)
{
m_pServiceName = pServiceName;
m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (NULL == m_hSCManager)
{
m_dwLastError = GetLastError();
return FALSE;
}
m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
if (NULL == m_hService)
{
CloseServiceHandle(m_hSCManager);
return FALSE;
}
else
{
return TRUE;
}
}
BOOL cDrvCtrl::Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName)
{
m_pSysPath = pSysPath;
m_pServiceName = pServiceName;
m_pDisplayName = pDisplayName;
m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (NULL == m_hSCManager)
{
m_dwLastError = GetLastError();
return FALSE;
}
m_hService = CreateServiceA(m_hSCManager,m_pServiceName,m_pDisplayName,
SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
m_pSysPath,NULL,NULL,NULL,NULL,NULL);
if (NULL == m_hService)
{
m_dwLastError = GetLastError();
if (ERROR_SERVICE_EXISTS == m_dwLastError)
{
m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
if (NULL == m_hService)
{
CloseServiceHandle(m_hSCManager);
return FALSE;
}
}
else
{
CloseServiceHandle(m_hSCManager);
return FALSE;
}
}
return TRUE;
}
BOOL cDrvCtrl::Start()
{
if (!StartServiceA(m_hService,NULL,NULL))
{
m_dwLastError = GetLastError();
return FALSE;
}
return TRUE;
}
BOOL cDrvCtrl::Stop()
{
SERVICE_STATUS ss;
GetSvcHandle(m_pServiceName);
if (!ControlService(m_hService,SERVICE_CONTROL_STOP,&ss))
{
m_dwLastError = GetLastError();
return FALSE;
}
return TRUE;
}
BOOL cDrvCtrl::Remove()
{
GetSvcHandle(m_pServiceName);
if (!DeleteService(m_hService))
{
m_dwLastError = GetLastError();
return FALSE;
}
return TRUE;
}
BOOL cDrvCtrl::Open(PCHAR pLinkName)//example: \\\\.\\xxoo
{
if (m_hDriver != INVALID_HANDLE_VALUE)
return TRUE;
m_hDriver = CreateFileA(pLinkName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(m_hDriver != INVALID_HANDLE_VALUE)
return TRUE;
else
return FALSE;
}
BOOL cDrvCtrl::IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes)
{
DWORD dw;
BOOL b=DeviceIoControl(m_hDriver,CTL_CODE_GEN(dwIoCode),InBuff,InBuffLen,OutBuff,OutBuffLen,&dw,NULL);
if(RealRetBytes)
*RealRetBytes=dw;
return b;
}
BOOL cDrvCtrl::IoControl(HANDLE hDrvHandle, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize)
{
DWORD lDrvRetSize;
return DeviceIoControl(hDrvHandle, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &lDrvRetSize, 0);
}
DWORD cDrvCtrl::CTL_CODE_GEN(DWORD lngFunction)
{
return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;
}
main.cpp
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <Windows.h>
#include "ScmDrvCtrl.h"
#pragma warning(disable:4996)
#pragma comment(lib,"user32.lib")
using namespace std;
void GetAppPath(char *szCurFile)
{
GetModuleFileNameA(0, szCurFile, MAX_PATH);
for (SIZE_T i = strlen(szCurFile) - 1; i >= 0; i--)
{
if (szCurFile[i] == '\\')
{
szCurFile[i + 1] = '\0';
break;
}
}
}
//start********************Dirver*************************
cDrvCtrl dcDirver;
BOOL InstallDriver(char * pSysFileName, char * pServiceName, char * pDisplayName) {
char szSysFile[MAX_PATH] = { 0 };
GetAppPath(szSysFile);
strcat(szSysFile, pSysFileName);
BOOL bInstallSuc = FALSE;
if (dcDirver.Install(szSysFile, pServiceName, pDisplayName)) {
if (dcDirver.Start()) {
char pLink[1024] = "\\\\.\\";
strcat(pLink , pDisplayName);
dcDirver.Open(pLink);
DWORD x = 0, y = 0, z = 0;
dcDirver.IoControl(0x803, &x, sizeof(x), &y, sizeof(y), &z);
bInstallSuc = TRUE;
}
}
return bInstallSuc;
}
VOID UnInstallDriver() {
CloseHandle(dcDirver.m_hDriver);
dcDirver.Stop();
dcDirver.Remove();
}
//end********************Dirver*************************
//start********************NtosBase*************************
//获得内核文件在内核里的加载地址(变量名称:NtosBase)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#endif
#define SystemModuleInformation 11
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY{
ULONG Unknow1;
ULONG Unknow2;
ULONG Unknow3;
ULONG Unknow4;
PVOID64 Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT ModuleNameOffset;
char ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct _SYSTEM_MODULE_INFORMATION{
ULONG Count;//内核中以加载的模块的个数
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef long(__stdcall *ZWQUERYSYSTEMINFORMATION)(
IN ULONG SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
IN PULONG ReturnLength OPTIONAL);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation;
ULONGLONG NtosBase = 0;
CHAR NtosName[260] = { 0 };
char *cs(char *str1, char *str2) //connect string
{
long newstrlen = strlen(str1) + strlen(str2) + 1;
char *newstr = (char*)malloc(newstrlen);
memcpy(newstr, str1, strlen(str1));
memcpy(newstr + strlen(str1), str2, strlen(str2) + 1);
return newstr;
}
ULONGLONG GetNtosBaseAndPath(char *ModuleName){
ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQuerySystemInformation");
ULONG NeedSize, i, ModuleCount;
ULONGLONG qwBase = 0;
PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;
ULONG uBufferSize = 0x5000;
PVOID pBuffer = malloc(uBufferSize);
if (ZwQuerySystemInformation(SystemModuleInformation, pBuffer, uBufferSize, &NeedSize) == STATUS_INFO_LENGTH_MISMATCH) {
free(pBuffer);
pBuffer = malloc(NeedSize+10);
ZwQuerySystemInformation(SystemModuleInformation, pBuffer, uBufferSize, &NeedSize);
}
pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;
//获得模块的总数量
ModuleCount = pSystemModuleInformation->Count;
if (ModuleName != NULL) {
strcpy(ModuleName, pSystemModuleInformation->Module[0].ImageName + pSystemModuleInformation->Module[0].ModuleNameOffset);
}
qwBase = (ULONGLONG)pSystemModuleInformation->Module[0].Base;
free(pBuffer);
return qwBase;
}
VOID GetNtosBase(){
char FileName[260] = { 0 }, *FullName;
NtosBase = GetNtosBaseAndPath(FileName);
FullName = cs("C:\\Windows\\system32\\", FileName);
strcpy(NtosName, FullName);
printf("NTOSKRNL base: %llx\n", NtosBase);
printf("NTOSKRNL name: %s\n", NtosName);
}
//end********************NtosBase*************************
//start********************NtosImageBase*************************
ULONGLONG NtosImageBase = 0;
DWORD FileLen(char *filename){
WIN32_FIND_DATAA fileInfo = { 0 };
DWORD fileSize = 0;
HANDLE hFind;
hFind = FindFirstFileA(filename, &fileInfo);
if (hFind != INVALID_HANDLE_VALUE){
fileSize = fileInfo.nFileSizeLow;
FindClose(hFind);
}
return fileSize;
}
CHAR *LoadDllContext(char *filename){
DWORD dwReadWrite, LenOfFile = FileLen(filename);
HANDLE hFile = CreateFileA(filename, GENERIC_READ , FILE_SHARE_READ , 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE){
PCHAR buffer = (PCHAR)malloc(LenOfFile);
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
ReadFile(hFile, buffer, LenOfFile, &dwReadWrite, 0);
CloseHandle(hFile);
return buffer;
}
return NULL;
}
VOID GetNtosImageBase(){
PIMAGE_NT_HEADERS64 pinths64;
PIMAGE_DOS_HEADER pdih;
char *NtosFileData = NULL;
NtosFileData = LoadDllContext(NtosName);
pdih = (PIMAGE_DOS_HEADER)NtosFileData;
pinths64 = (PIMAGE_NT_HEADERS64)(NtosFileData + pdih->e_lfanew);
NtosImageBase = pinths64->OptionalHeader.ImageBase;
printf("ImageBase: %llx\n", NtosImageBase);
free(NtosFileData);
}
//end********************NtosImageBase*************************
//start********************KiServiceTable*************************
ULONGLONG KiServiceTable;
DWORD CTL_CODE_GEN(DWORD lngFunction)
{
return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;
}
VOID GetKiServiceTable()
{
dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x801), NULL, 0, &KiServiceTable, 8);
printf("KiServiceTable: %llx\n", KiServiceTable);
}
//end********************KiServiceTable*************************
//start********************AllSSDTFunction*************************
DWORD GetSSDTFunctionIndex(char *FunctionName)
{
return *(DWORD*)((PUCHAR)GetProcAddress(LoadLibraryW(L"ntdll.dll"), FunctionName) + 4); //极限精简
/*
PUCHAR fptr=(PUCHAR)GetProcAddress(LoadLibraryW(L"ntdll.dll"),FunctionName);
DWORD index=*(DWORD*)(fptr+4);
return index;
*/
/*
所有的函数都像下面一样:
00000000`775a0110 4c8bd1 mov r10,rcx
00000000`775a0113 b8??000000 mov eax,??h
00000000`775a0118 0f05 syscall
00000000`775a011a c3 ret
*/
}
ULONGLONG NtosInProcess = 0;
ULONGLONG GetFunctionOriginalAddress(DWORD index)
{
if (NtosInProcess == 0)
NtosInProcess = (ULONGLONG)LoadLibraryExA(NtosName, 0, DONT_RESOLVE_DLL_REFERENCES); //"C:\\Windows\\system32\\ntkrnlmp.exe"
ULONGLONG RVA = KiServiceTable - NtosBase;
ULONGLONG temp = *(PULONGLONG)(NtosInProcess + RVA + 8 * (ULONGLONG)index);
ULONGLONG RVA_index = temp - NtosImageBase; //IMAGE_OPTIONAL_HEADER64.ImageBase=0x140000000(这个值基本是固定的)
return RVA_index + NtosBase;
}
VOID PrintAllSSDTFunction()
{
DWORD i = 0, fl = 0, fs_pos = 0, fe_pos = 0, PauseCnt = 0, ssdt_fun_cnt = 0;
ULONG64 ssdt_func_addr = 0, ssdt_func_ori_addr = 0;
CopyFileW(L"c:\\windows\\system32\\ntdll.dll", L"c:\\ntdll.txt", 0);
fl = FileLen("c:\\ntdll.txt");
char func_start[] = "ZwAcceptConnectPort", func_end[] = "ZwYieldExecution"; //每个函数名之间隔着\0
char *funs = (char *)malloc(strlen(func_start)); memcpy(funs, func_start, strlen(func_start));
char *fune = (char *)malloc(strlen(func_end)); memcpy(fune, func_end, strlen(func_end));
char *ntdlltxt = LoadDllContext("c:\\ntdll.txt");
for (i = 0; i<fl; i++)
{
if (memcmp(ntdlltxt + i, funs, strlen(func_start)) == 0)
fs_pos = i;
if (memcmp(ntdlltxt + i, fune, strlen(func_end)) == 0)
{
fe_pos = i;
break;
}
}
ntdlltxt = ntdlltxt + fs_pos;
//打印头
printf("ID\t当前地址\t 原始地址\t 函数名\n");
//这里不能显示到最后一个函数
while (strcmp(ntdlltxt, func_end) != 0)
{
DWORD fn_index = GetSSDTFunctionIndex(ntdlltxt);
if (fn_index<1000)
{
ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
ntdlltxt[0] = 'N'; ntdlltxt[1] = 't'; //寻找的是Zw***,但是应该显示Nt***
if (ssdt_func_ori_addr != ssdt_func_addr)
printf("0x%-0.3X!\t%llx %llx %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
else
printf("0x%-0.3X\t%llx %llx %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
}
else
{
fn_index = 0x57; //不同的系统,不同的编号,由于目前只有WIN7 X64,所以这里直接硬编码了
ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
ntdlltxt[0] = 'N'; ntdlltxt[1] = 't';
if (ssdt_func_ori_addr != ssdt_func_addr)
printf("0x%-0.3X!\t%llx %llx %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
else
printf("0x%-0.3X\t%llx %llx %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
/*
0:000> u ZwQuerySystemTime
ntdll!ZwQuerySystemTime:
00000000`77b20450 e91b62fdff jmp ntdll!RtlQuerySystemTime (00000000`77af6670)
00000000`77b20455 6666660f1f840000000000 nop word ptr [rax+rax]
*/
/*
nt!ZwQuerySystemTime:
fffff800`01673fa0 488bc4 mov rax,rsp
fffff800`01673fa3 fa cli
fffff800`01673fa4 4883ec10 sub rsp,10h
fffff800`01673fa8 50 push rax
fffff800`01673fa9 9c pushfq
fffff800`01673faa 6a10 push 10h
fffff800`01673fac 488d053d270000 lea rax,[nt!KiServiceLinkage (fffff800`016766f0)]
fffff800`01673fb3 50 push rax
fffff800`01673fb4 b857000000 mov eax,57h
fffff800`01673fb9 e9825e0000 jmp nt!KiServiceInternal (fffff800`01679e40)
fffff800`01673fbe 6690 xchg ax,ax
*/
}
ntdlltxt = ntdlltxt + strlen(ntdlltxt) + 1;
PauseCnt++;
ssdt_fun_cnt++;
if (PauseCnt == 101)
{
printf("\nPress [ENTER] to continue...\n");
getchar();
PauseCnt = 0;
}
}
//显示完最后一个函数
DWORD fn_index = GetSSDTFunctionIndex(ntdlltxt);
ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
ntdlltxt[0] = 'N'; ntdlltxt[1] = 't';
printf("0x%-0.3X\t%llx %llx %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
//显示测试的hook函数
ssdt_fun_cnt++;
//显示ssdt表上的函数数
printf("\nTotal of SSDT function: %ld\n", ssdt_fun_cnt);
DeleteFileA("c:\\ntdll.txt");
}
//end********************AllSSDTFunction*************************
//start********************UnHook*************************
typedef struct _UNHOOK_SSDT64 {
ULONGLONG Address;
ULONGLONG id;
}UNHOOK_SSDT64, *PUNHOOK_SSDT64;
VOID UnhookSSDT()
{
ULONG id;
ULONG64 ssdt_func_ori_addr = 0;
UNHOOK_SSDT64 data = { 0 };
printf("Input SSDT function index which you want to unhook (like 0x29): ");
scanf("0x%x", &id);
ssdt_func_ori_addr = GetFunctionOriginalAddress(id);
data.Address = ssdt_func_ori_addr;
data.id = (ULONGLONG)id;
dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x800), &data, sizeof(UNHOOK_SSDT64), 0, 0);
}
//end********************UnHook*************************
int main()
{
//安装驱动
if (!InstallDriver("Dri.sys", "MyDriver", "MyDriver")) {
printf("LoadDriver=false\n");
return 0;
}
else {
printf("LoadDriver=true\n");
}
getchar();
GetNtosBase();
GetNtosImageBase();
GetKiServiceTable();
PrintAllSSDTFunction();
getchar();
UnhookSSDT();
getchar();
getchar();
//卸载驱动
UnInstallDriver();
printf("UninstallDriver=true\n");
return 0;
}
执行结果1:hook掉关闭进程的函数,然后加载上面的驱动。
执行结果2 Hook SSDT保护计算器不被结束
执行结果3 执行UnHook 取消掉上面SSDT HOOK 的保护并且成功结束掉计算器
最后再声明一遍,所有的代码几乎都来源于学习资料,胡文亮前辈。还有很多细节为了测试方便我就随意的改了。很多地方发现内存泄漏以及无用代码。如果是用于实际项目,一定要弄清楚原理之后好好改改代码再用。
Win64 驱动内核编程-20.UnHook SSDT的更多相关文章
- Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)
SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...
- Win64 驱动内核编程-18.SSDT
SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...
- Win64 驱动内核编程-19.HOOK-SSDT
HOOK SSDT 在 WIN64 上 HOOK SSDT 和 UNHOOK SSDT 在原理上跟 WIN32 没什么不同,甚至说 HOOK 和 UNHOOK 在本质上也没有不同,都是在指定的地址上填 ...
- Win64 驱动内核编程-3.内核里使用内存
内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...
- Win64 驱动内核编程-8.内核里的其他常用
内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)
驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...
- Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook
Ring0 InLineHook 和UnHook 如果是要在R0里hook,作者的建议是InLine HOOK,毕竟SSDT HOOK 和 SHADOW SSDT HOOK比较麻烦,不好修改.目前R3 ...
- Win64 驱动内核编程-11.回调监控进线程句柄操作
无HOOK监控进线程句柄操作 在 NT5 平台下,要监控进线程句柄的操作. 通常要挂钩三个API:NtOpenProcess.NtOpenThread.NtDuplicateObject.但是在 VI ...
随机推荐
- nginx使用-2(模块和日志)
默认官方模块 1.1.Gzip压缩 压缩文件,使文件变小,传输更快了.目前市场上大部分浏览器是支持GZIP的.IE6以下支持不好,会出现乱码情况. 官方文档:http://nginx.org/en/d ...
- Vue ElementUI表格table中使用select下拉框组件时获取改变之前的值
目前项目中有一个场景,就是表格中显示下拉框,并且下拉框的值可以更改,更改后提交后台更新.因为这个操作比较重要,所以切换时会有一个提示框,提示用户是否修改,是则走提交逻辑,否则直接返回,什么也不做. 之 ...
- 主成分分析 | Principal Components Analysis | PCA
理论 仅仅使用基本的线性代数知识,就可以推导出一种简单的机器学习算法,主成分分析(Principal Components Analysis, PCA). 假设有 $m$ 个点的集合:$\left\{ ...
- JVM之对象回收
finalize /** *此代码演示了两点: *1.对象可以在被GC时自我拯救. *2.这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次 */ public ...
- net start MongoDB 服务没有响应控制功能。 请键入 NET HELPMSG 2186 以获得更多的帮助。
我在 Windows 电脑上修改了 mongo.cfg 文件后 执行 net start mongodb 的时候,命令行出现了这个报错. 这个报错,有几种情况可以进行排查 1. 你的 mongod 命 ...
- .net core 和 WPF 开发升讯威在线客服系统【私有化部署免费版】发布
希望 .net 和 WPF 技术时至今日,还能有一些存在感. 这个项目源于2015年前后,当时开发的初版,我使用了 ASP.NET MVC 做为后端,数据库使用原生 ADO.NET 进行操作.WPF ...
- Shell 正则表达式详解
Shell 正则表达式 什么是正则表达式? 正则表达式在每种语言中都会有,功能就是匹配符合你预期要求的字符串. 为什么要学正则表达式? 在企业工作中,我们每天做的linux运维工作中,时刻都会面对大量 ...
- Distributed | Raft
1. 复制状态机 一致性算法是在复制状态机的背景下产生的.在这种方法下,一组服务器的状态机计算相同状态的相同副本,即使某些服务器宕机,也可以继续运行. 复制状态机通常使用复制日志实现,每个服务器存储一 ...
- 【图像处理】OpenCV+Python图像处理入门教程(六)图像平滑处理
相信很多小伙伴都听过"滤波器"这个词,在通信领域,滤波器能够去除噪声信号等频率成分,然而在我们OpenCV中,"滤波"并不是对频率进行筛选去除,而是实现了图像的 ...
- 有关指针和C语言中的常量
常量类型(五种): 字面常量(2,3,6....) ; enum 定义的枚举常量; 字符常量('a','b'....) ; ...