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的更多相关文章

  1. Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)

    SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...

  2. Win64 驱动内核编程-18.SSDT

    SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...

  3. Win64 驱动内核编程-19.HOOK-SSDT

    HOOK SSDT 在 WIN64 上 HOOK SSDT 和 UNHOOK SSDT 在原理上跟 WIN32 没什么不同,甚至说 HOOK 和 UNHOOK 在本质上也没有不同,都是在指定的地址上填 ...

  4. Win64 驱动内核编程-3.内核里使用内存

    内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...

  5. Win64 驱动内核编程-8.内核里的其他常用

    内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...

  6. Win64 驱动内核编程-7.内核里操作进程

    在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...

  7. Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)

    驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...

  8. Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook

    Ring0 InLineHook 和UnHook 如果是要在R0里hook,作者的建议是InLine HOOK,毕竟SSDT HOOK 和 SHADOW SSDT HOOK比较麻烦,不好修改.目前R3 ...

  9. Win64 驱动内核编程-11.回调监控进线程句柄操作

    无HOOK监控进线程句柄操作 在 NT5 平台下,要监控进线程句柄的操作. 通常要挂钩三个API:NtOpenProcess.NtOpenThread.NtDuplicateObject.但是在 VI ...

随机推荐

  1. 在scanf函数中占位符使用错误而产生的一些错误

    出现的问题 在做编程题的的时候,遇到了一个很奇怪的错误,出问题的代码如下: 1 #include <cstdio> 2 using namespace std; 3 4 int main( ...

  2. 测试平台系列(1) 搭建Flask服务

    搭建Flask服务 项目地址 点我进入项目地址 代码都会在这里有所展示,喜欢的话可以帮点个star,谢谢大家了!如果你喜欢该教程,也可以分享给其他人. 关于选型 想了很久,本来打算用「Gin」做为后端 ...

  3. 任务队列 与 Celery概述

    一.任务队列(Task Queues) 1.1 什么是任务队列? 任务队列用于管理后台工作,通常这些后台工作必须在 HTTP请求-响应循环 之外执行. 1.2 为什么需要任务队列? 对于那些不是由客户 ...

  4. redis过期key监听事件

    目录 redis安装 docker拉取 启动 redis 配置 命令监听 问题 程序监听 具体监听类 效果 总结 redis常用语缓存操作,但是redis功能不仅仅于此.今天我们来看看redis的ke ...

  5. 关于 PDB 文件你需要知道什么?

    引言 大多数人知道 PDB 文件是用来帮助我们 debug 的,但也仅此而已. 本文主要介绍当你遇到 PDB 文件时(windows 开发中),你必须要知道的内容. 重要的事情说三遍 PDB 文件和源 ...

  6. 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...

  7. 2017-2018 ACM-ICPC Northern Eurasia(A.Archery Tournament)

    题目链接:https://vjudge.net/problem/Gym-101630A 题意: n个事件,t=1 代表增加一个圆心为(x,y),半径为 abs(y)的靶子,t=2,代表射击的坐标为(x ...

  8. kmp&字典树 模板

    kmp: const int maxn=1e5+5; char s[maxn],p[maxn]; int nex[maxn]; int KmpSearch(char* s, char* p) { in ...

  9. 总结下js排序算法和乱序算法

    其实本人最怕的就是算法,大学算法课就感觉老师在讲天书,而且对于前端来说,算法在实际的应用中实在是很有限.毕竟算法要依靠大量的数据为基础才能发挥出算法的效率,就浏览器那性能,......是吧,退一万步说 ...

  10. python多版本与虚拟环境

    这篇纯python技术文章,我自己平时也会用到,在此记录一下. 为什么会用到多个Python版本? 用macOS和Ubutntu的同学都知道系统默认安装的Python2.7.x,然后,我们平时pyth ...