zoukankan      html  css  js  c++  java
  • 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 的保护并且成功结束掉计算器


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

  • 相关阅读:
    循环顺序队列
    iscsi与multipath
    MySQL 数据库设计 笔记与总结(4)维护优化
    [Swift]LeetCode6. Z字形变换 | ZigZag Conversion
    [Swift]八大排序算法(八):基数排序
    [Swift]八大排序算法(七):归并排序
    [Swift]八大排序算法(六):希尔排序
    [Swift]八大排序算法(五):插入排序
    [Swift]八大排序算法(四):堆排序
    [Swift]八大排序算法(三):选择排序 和 简单选择排序
  • 原文地址:https://www.cnblogs.com/csnd/p/12062004.html
Copyright © 2011-2022 走看看