我们可以通过枚举ntdll.dll的导出函数来间接枚举SSDT所有表项所对应的函数,因为所有的内核服务函数对应于ntdll.dll的同名函数都是这样开头的:
汇编代码
- mov eax, <ServiceIndex>
对应的机器码为:
机器码
- B8 <ServiceIndex>
以下代码摘自cuckoo驱动hooking.c ,offsetSyscall在x86下为1byte (B8/mov eax),而在x64为4byte,请在代码中寻找。
代码语言:javascript复制////////////////////////////////////////////////////////////////////////////
//
// zer0m0n
//
// Copyright 2016 Adrien Chevalier, Nicolas Correia, Cyril Moreau
//
// This file is part of zer0m0n.
//
// Zer0m0n is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Zer0m0n is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Zer0m0n. If not, see <http://www.gnu.org/licenses/>.
//
//
// File : hooking.c
// Abstract : Hooking function for zer0m0n
// Revision : v1.1
// Author : Adrien Chevalier, Nicolas Correia, Cyril Moreau
// Email : contact.zer0m0n@gmail.com
// Date : 2016-07-05
//
/////////////////////////////////////////////////////////////////////////////
#include "struct.h"
#include "hooking.h"
#include "main.h"
#include "hook_reg.h"
#include "hook_process.h"
#include "hook_file.h"
#include "hook_misc.h"
#include "struct.h"
PVOID MapNtdllIntoMemory()
{
NTSTATUS status;
HANDLE hSection;
OBJECT_ATTRIBUTES objAttr;
UNICODE_STRING pathFile;
USHORT NumberOfSections;
SECTION_IMAGE_INFORMATION sii = {0};
PVOID pSection = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_NT_HEADERS64 pNtHeader64 = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = NULL;
DWORD dwExportRVA, dwExportSize;
RtlInitUnicodeString(&pathFile, L"\KnownDlls\ntdll.dll");
InitializeObjectAttributes(&objAttr, &pathFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
if(NT_SUCCESS(status = ZwOpenSection(&hSection, SECTION_MAP_READ, &objAttr)))
{
ZwQuerySection(hSection, 1, &sii, sizeof(sii), 0);
Dbg("ntdll entry point : %llxn", sii.EntryPoint);
Ntdll_ImageBase = sii.EntryPoint;
pDosHeader = (PIMAGE_DOS_HEADER)Ntdll_ImageBase;
#ifdef _M_X64
pNtHeader64 = (PIMAGE_NT_HEADERS64)((unsigned char*)Ntdll_ImageBase pDosHeader->e_lfanew);
pSectionHeader = (PIMAGE_SECTION_HEADER)((unsigned char*)pNtHeader64 sizeof(IMAGE_NT_HEADERS64));
dwExportRVA = pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
dwExportSize = pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
#endif
pNtHeader = (PIMAGE_NT_HEADERS)((unsigned char*)Ntdll_ImageBase pDosHeader->e_lfanew);
pSectionHeader = (PIMAGE_SECTION_HEADER)((unsigned char*)pNtHeader sizeof(IMAGE_NT_HEADERS));
dwExportRVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
dwExportSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
Dbg("Export table address : 0xxn", dwExportRVA);
Dbg("Export table size : 0xxn", dwExportSize);
Dbg("EAT : 0xXn", (PIMAGE_EXPORT_DIRECTORY)((unsigned char*)Ntdll_ImageBase dwExportRVA));
pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((unsigned char*)Ntdll_ImageBase dwExportRVA);
Dbg("number of exported functions : 0xxn", pImageExportDirectory->NumberOfFunctions);
}
ZwClose(hSection);
return pImageExportDirectory;
}
ULONG GetSyscallNumber(__in PIMAGE_EXPORT_DIRECTORY pImageExportDirectory,
__in PUCHAR funcName,
__in ULONG offsetSyscall)
{
PULONG addrName = NULL, addrFunc = NULL;
PWORD addrOrdinal = NULL;
ULONG i = 0;
PCHAR name = NULL;
SIZE_T n;
if(pImageExportDirectory && funcName)
{
addrName = (PULONG)((unsigned char*)Ntdll_ImageBase pImageExportDirectory->AddressOfNames);
addrFunc = (PULONG)((unsigned char*)Ntdll_ImageBase pImageExportDirectory->AddressOfFunctions);
addrOrdinal = (PWORD)((unsigned char*)Ntdll_ImageBase pImageExportDirectory->AddressOfNameOrdinals);
for(i=0; i < pImageExportDirectory->NumberOfNames; i)
{
name = ((unsigned char*)Ntdll_ImageBase addrName[i]);
__try
{
ProbeForRead(name, 0, 1);
RtlStringCchLengthA(funcName, NTSTRSAFE_MAX_CCH, &n);
if(RtlEqualMemory(funcName, name, n))
{
Dbg("[ ] FOUND : %sn", name);
Dbg("addr : 0xxn", ((unsigned char*)Ntdll_ImageBase addrFunc[addrOrdinal[i]]));
Dbg("syscall : %xn", *(PULONG)((PUCHAR)((unsigned char*)Ntdll_ImageBase addrFunc[addrOrdinal[i]] offsetSyscall)));
return *(PULONG)((PUCHAR)((unsigned char*)Ntdll_ImageBase addrFunc[addrOrdinal[i]] offsetSyscall));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
Dbg("Exception : %xn", GetExceptionCode());
}
}
}
return 0;
}
ULONG GetSSDTEntry(__in PULONG KiServiceTable,
__in PVOID FuncAddress)
{
return ((ULONG)((ULONGLONG)FuncAddress-(ULONGLONG)KiServiceTable)) << 4;
}
PVOID SearchCodeCave(__in PUCHAR pStartSearchAddress)
{
while(pStartSearchAddress )
{
if(MmIsAddressValid(pStartSearchAddress))
{
if(*(PULONG)pStartSearchAddress == 0x00000000 && *(PULONG)(pStartSearchAddress 4) == 0x00000000 && *(PULONG)(pStartSearchAddress 8) == 0x00000000)
return pStartSearchAddress;
}
}
return 0;
}
ULONGLONG GetNTAddressFromSSDT(__in PULONG KiServiceTable,
__in ULONG ServiceId )
{
return (LONGLONG)( KiServiceTable[ServiceId] >> 4 )
(ULONGLONG)KiServiceTable;
}
PVOID GetEndOfTextSection(__in PVOID moduleBase)
{
USHORT NumberOfSections;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS64 pNtHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
ULONG i;
PVOID begin_text, end_text;
end_text = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)moduleBase;
pNtHeader = (PIMAGE_NT_HEADERS64)((unsigned char*)moduleBase pDosHeader->e_lfanew);
NumberOfSections = pNtHeader->FileHeader.NumberOfSections;
Dbg("Number of Sections: %dn", NumberOfSections);
pSectionHeader = (PIMAGE_SECTION_HEADER)((unsigned char*)pNtHeader sizeof(IMAGE_NT_HEADERS64));
Dbg("section header : %llx n", pSectionHeader);
// parse each section in order to get to the executable section
for(i=0; i<NumberOfSections; i )
{
// this is the .text section
if(pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)
{
begin_text = (PVOID)(pSectionHeader->VirtualAddress (ULONG_PTR)moduleBase);
end_text = (PVOID)((ULONG_PTR)begin_text pSectionHeader->Misc.VirtualSize);
Dbg("%s section is located at : %llx n", pSectionHeader->Name, begin_text);
Dbg("end of %s section at : %llx n", pSectionHeader->Name, end_text);
break;
}
pSectionHeader ;
}
return end_text;
}
PVOID GetKernelBase()
{
UNICODE_STRING funcAddr;
ULONG ulNeededSize = 0, ModuleCount;
PVOID pBuffer;
PSYSTEM_MODULE_INFORMATION pSystemModuleInformation = NULL;
PSYSTEM_MODULE pSystemModule = NULL;
PVOID imgBaseAddr;
ZwQuerySystemInformation(SystemModuleInformation, &ulNeededSize, 0, &ulNeededSize);
if(ulNeededSize)
{
pBuffer = PoolAlloc(ulNeededSize);
if(NT_SUCCESS(ZwQuerySystemInformation(SystemModuleInformation, pBuffer, ulNeededSize, &ulNeededSize)))
{
pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;
pSystemModule = &pSystemModuleInformation->Modules[0];
imgBaseAddr = pSystemModule->Base;
return imgBaseAddr;
}
}
return 0;
}
ULONGLONG GetKeServiceDescriptorTable64()
{
PUCHAR pStartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR pEndSearchAddress = (PUCHAR)( ((ULONG_PTR)pStartSearchAddress PAGE_SIZE) & (~0x0FFF) );
PULONG pFindCodeAddress = NULL;
ULONG_PTR pKeServiceDescriptorTable;
while ( pStartSearchAddress < pEndSearchAddress )
{
if ( (*(PULONG)pStartSearchAddress & 0xFFFFFF00) == 0x83f70000 )
{
pFindCodeAddress = (PULONG)(pStartSearchAddress - 12);
return (ULONG_PTR)pFindCodeAddress (((*(PULONG)pFindCodeAddress)>>24) 7) (ULONG_PTR)(((*(PULONG)(pFindCodeAddress 1))&0x0FFFF)<<8);
}
}
return 0;
}
VOID HookSSDT()
{
PDWORD func = NULL;
PULONG KiServiceTable = NULL;
PVOID kernelBase = NULL;
PVOID pStartSearchAddress = NULL;
DWORD offsetSyscall = 1;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
#ifdef _M_X64
KeServiceDescriptorTable = (pServiceDescriptorTableEntry)GetKeServiceDescriptorTable64();
Dbg("KeServiceDescriptorTable : %llxn", KeServiceDescriptorTable);
KiServiceTable = KeServiceDescriptorTable->ServiceTableBase;
Dbg("KiServiceTable : %llxn", KiServiceTable);
kernelBase = GetKernelBase();
Dbg("Kernel base addr : %llxn", kernelBase);
pStartSearchAddress = GetEndOfTextSection(kernelBase);
Dbg("pStartSearchAddress : %llxn", pStartSearchAddress);
offsetSyscall = 4;
#endif
pImageExportDirectory = MapNtdllIntoMemory();
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwWriteFile", offsetSyscall), (PVOID)Hooked_NtWriteFile, (PVOID*)&Orig_NtWriteFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateFile", offsetSyscall), (PVOID)Hooked_NtCreateFile, (PVOID*)&Orig_NtCreateFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwReadFile", offsetSyscall), (PVOID)Hooked_NtReadFile, (PVOID*)&Orig_NtReadFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDeleteFile", offsetSyscall), (PVOID)Hooked_NtDeleteFile, (PVOID*)&Orig_NtDeleteFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwOpenFile", offsetSyscall), (PVOID)Hooked_NtOpenFile, (PVOID*)&Orig_NtOpenFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwSetInformationFile", offsetSyscall), (PVOID)Hooked_NtSetInformationFile, (PVOID*)&Orig_NtSetInformationFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwClose", offsetSyscall), (PVOID)Hooked_NtClose, (PVOID*)&Orig_NtClose, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDeviceIoControlFile", offsetSyscall), (PVOID)Hooked_NtDeviceIoControlFile, (PVOID*)&Orig_NtDeviceIoControlFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwQueryAttributesFile", offsetSyscall), (PVOID)Hooked_NtQueryAttributesFile, (PVOID*)&Orig_NtQueryAttributesFile, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwQueryValueKey", offsetSyscall), (PVOID)Hooked_NtQueryValueKey, (PVOID*)&Orig_NtQueryValueKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwOpenKey", offsetSyscall), (PVOID)Hooked_NtOpenKey, (PVOID*)&Orig_NtOpenKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwOpenKeyEx", offsetSyscall), (PVOID)Hooked_NtOpenKeyEx, (PVOID*)&Orig_NtOpenKeyEx, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateKey", offsetSyscall), (PVOID)Hooked_NtCreateKey, (PVOID*)&Orig_NtCreateKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDeleteKey", offsetSyscall), (PVOID)Hooked_NtDeleteKey, (PVOID*)&Orig_NtDeleteKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDeleteValueKey", offsetSyscall), (PVOID)Hooked_NtDeleteValueKey, (PVOID*)&Orig_NtDeleteValueKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwSetValueKey", offsetSyscall), (PVOID)Hooked_NtSetValueKey, (PVOID*)&Orig_NtSetValueKey, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwTerminateProcess", offsetSyscall), (PVOID)Hooked_NtTerminateProcess, (PVOID*)&Orig_NtTerminateProcess, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateProcess", offsetSyscall), (PVOID)Hooked_NtCreateProcess, (PVOID*)&Orig_NtCreateProcess, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateProcessEx", offsetSyscall), (PVOID)Hooked_NtCreateProcessEx, (PVOID*)&Orig_NtCreateProcessEx, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateUserProcess", offsetSyscall), (PVOID)Hooked_NtCreateUserProcess, (PVOID*)&Orig_NtCreateUserProcess, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwWriteVirtualMemory", offsetSyscall), (PVOID)Hooked_NtWriteVirtualMemory, (PVOID*)&Orig_NtWriteVirtualMemory, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwReadVirtualMemory", offsetSyscall), (PVOID)Hooked_NtReadVirtualMemory, (PVOID*)&Orig_NtReadVirtualMemory, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwMapViewOfSection", offsetSyscall), (PVOID)Hooked_NtMapViewOfSection, (PVOID*)&Orig_NtMapViewOfSection, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwOpenProcess", offsetSyscall), (PVOID)Hooked_NtOpenProcess, (PVOID*)&Orig_NtOpenProcess, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwResumeThread", offsetSyscall), (PVOID)Hooked_NtResumeThread, (PVOID*)&Orig_NtResumeThread, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwSetContextThread", offsetSyscall), (PVOID)Hooked_NtSetContextThread, (PVOID*)&Orig_NtSetContextThread, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateThread", offsetSyscall), (PVOID)Hooked_NtCreateThread, (PVOID*)&Orig_NtCreateThread, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateThreadEx", offsetSyscall), (PVOID)Hooked_NtCreateThreadEx, (PVOID*)&Orig_NtCreateThreadEx, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateSection", offsetSyscall), (PVOID)Hooked_NtCreateSection, (PVOID*)&Orig_NtCreateSection, pStartSearchAddress, KiServiceTable);//
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwSystemDebugControl", offsetSyscall), (PVOID)Hooked_NtSystemDebugControl, (PVOID*)&Orig_NtSystemDebugControl, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwQueueApcThread", offsetSyscall), (PVOID)Hooked_NtQueueApcThread, (PVOID*)&Orig_NtQueueApcThread, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwOpenThread", offsetSyscall), (PVOID)Hooked_NtOpenThread, (PVOID*)&Orig_NtOpenThread, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwQuerySystemInformation", offsetSyscall), (PVOID)Hooked_NtQuerySystemInformation, (PVOID*)&Orig_NtQuerySystemInformation, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDebugActiveProcess", offsetSyscall), (PVOID)Hooked_NtDebugActiveProcess, (PVOID*)&Orig_NtDebugActiveProcess, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwCreateMutant", offsetSyscall), (PVOID)Hooked_NtCreateMutant, (PVOID*)&Orig_NtCreateMutant, pStartSearchAddress, KiServiceTable);
Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwDelayExecution", offsetSyscall), (PVOID)Hooked_NtDelayExecution, (PVOID*)&Orig_NtDelayExecution, pStartSearchAddress, KiServiceTable);
}
VOID Install_Hook(__in ULONG syscall,
__in PVOID hookedFunc,
__inout PVOID *origFunc,
__in PVOID searchAddr,
__in PULONG KiServiceTable)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UCHAR jmp_to_newFunction[] = "x48xB8xFFxFFxFFxFFxFFxFFxFFxFFxFFxE0"; //mov rax, xxx ; jmp rax
KIRQL Irql;
ULONG SsdtEntry;
PVOID trampoline = NULL;
PMDL mdl = NULL;
PVOID memAddr = NULL;
KIRQL irql;
if(syscall > 0)
{
irql = UnsetWP();
#ifdef _M_IX86
*origFunc = (PVOID)SYSTEMSERVICE(syscall);
(PVOID)SYSTEMSERVICE(syscall) = hookedFunc;
#elif defined _M_X64
Dbg("OS : 64 bits !n");
*origFunc = (PVOID)GetNTAddressFromSSDT(KiServiceTable, syscall);
Dbg("Orig_Func : %llxn", *origFunc);
Dbg("Hooked_Func : %llxn", hookedFunc);
// mov rax, @NewFunc; jmp rax
*(PULONGLONG)(jmp_to_newFunction 2) = (ULONGLONG)hookedFunc;
trampoline = SearchCodeCave(searchAddr);
Dbg("trampoline : %llxn", trampoline);
mdl = IoAllocateMdl(trampoline, 12, FALSE, FALSE, NULL);
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
memAddr = MmMapLockedPagesSpecifyCache(mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
RtlMoveMemory(memAddr, jmp_to_newFunction, 12);
SsdtEntry = GetSSDTEntry(KiServiceTable, trampoline);
SsdtEntry &= 0xFFFFFFF0;
SsdtEntry = KiServiceTable[syscall] & 0x0F;
KiServiceTable[syscall] = SsdtEntry;
#endif
SetWP(irql);
}
}
KIRQL UnsetWP( )
{
KIRQL Irql = KeRaiseIrqlToDpcLevel();
UINT_PTR cr0 = __readcr0();
cr0 &= ~0x10000;
__writecr0( cr0 );
_disable();
return Irql;
}
VOID SetWP(KIRQL Irql)
{
UINT_PTR cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0( cr0 );
KeLowerIrql( Irql );
}