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
");
}

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 
");
			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
");

	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] = '';
			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
", NtosBase);
	printf("NTOSKRNL name: %s
", 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
", 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
", 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"; //每个函数名之间隔着
	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	当前地址	  原始地址	    函数名
");
	//这里不能显示到最后一个函数
	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!	%llx  %llx  %s
", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
			else
				printf("0x%-0.3X	%llx  %llx  %s
", 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!	%llx  %llx  %s
", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
			else
				printf("0x%-0.3X	%llx  %llx  %s
", 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("
Press [ENTER] to continue...
");
			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	%llx  %llx  %s
", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);


	//显示测试的hook函数



	ssdt_fun_cnt++;
	//显示ssdt表上的函数数
	printf("
Total of SSDT function: %ld
", 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
");
		return 0;
	}
	else {
		printf("LoadDriver=true
");
	}

	getchar();

	GetNtosBase();
	GetNtosImageBase();
	GetKiServiceTable();
	PrintAllSSDTFunction();

	getchar();

	UnhookSSDT();

	getchar();
	getchar();
	//卸载驱动
	UnInstallDriver();
	printf("UninstallDriver=true
");
	return 0;
}


执行结果1hook掉关闭进程的函数,然后加载上面的驱动。


执行结果2 Hook SSDT保护计算器不被结束


执行结果3 执行UnHook 取消掉上面SSDT HOOK 的保护并且成功结束掉计算器


    最后再声明一遍,所有的代码几乎都来源于学习资料,胡文亮前辈。还有很多细节为了测试方便我就随意的改了。很多地方发现内存泄漏以及无用代码。如果是用于实际项目,一定要弄清楚原理之后好好改改代码再用。

原文地址:https://www.cnblogs.com/csnd/p/12062005.html