暴力搜索x64 ssdt 以及掛鉤HOOK

 IDA加載ntoskrnl.exe 微軟符號,進入,jump by name,隨便輸入一個,好比zwwritefile,層層跟蹤,進入,能夠發現redis

.text:00000001401B91D4                 lea     r10, KeServiceDescriptorTableshell

.text:00000001401B91C0 ; =============== S U B R O U T I N E =======================================
.text:00000001401B91C0
.text:00000001401B91C0
.text:00000001401B91C0 KiSystemServiceStart proc near          ; DATA XREF: KiServiceInternal+5Ao
.text:00000001401B91C0                                         ; .data:0000000140397340o
.text:00000001401B91C0                 mov     [rbx+90h], rsp
.text:00000001401B91C7                 mov     edi, eax
.text:00000001401B91C9                 shr     edi, 7
.text:00000001401B91CC                 and     edi, 20h
.text:00000001401B91CF                 and     eax, 0FFFh
.text:00000001401B91CF KiSystemServiceStart endp ; sp-analysis failed
.text:00000001401B91CF
.text:00000001401B91D4
.text:00000001401B91D4 ; =============== S U B R O U T I N E =======================================
.text:00000001401B91D4
.text:00000001401B91D4
.text:00000001401B91D4 KiSystemServiceRepeat proc near         ; CODE XREF: KiSystemServiceExit+3CCj
.text:00000001401B91D4                 lea     r10, KeServiceDescriptorTable
.text:00000001401B91DB                 lea     r11, KeServiceDescriptorTableShadow
.text:00000001401B91E2                 test    dword ptr [rbx+78h], 80h
.text:00000001401B91E9                 jz      short loc_1401B91FE
.text:00000001401B91EB                 test    dword ptr [rbx+78h], 200000h
.text:00000001401B91F2                 jz      short loc_1401B91FB
.text:00000001401B91F4                 lea     r11, KeServiceDescriptorTableFilter
.text:00000001401B91FB
.text:00000001401B91FB loc_1401B91FB:                          ; CODE XREF: KiSystemServiceRepeat+1Ej
.text:00000001401B91FB                 mov     r10, r11
.text:00000001401B91FE
.text:00000001401B91FE loc_1401B91FE:                          ; CODE XREF: KiSystemServiceRepeat+15j
.text:00000001401B91FE                 cmp     eax, [r10+rdi+10h]
.text:00000001401B9203                 jnb     loc_1401B96DE
.text:00000001401B9209                 mov     r10, [r10+rdi]
.text:00000001401B920D                 movsxd  r11, dword ptr [r10+rax*4]
.text:00000001401B9211                 mov     rax, r11
.text:00000001401B9214                 sar     r11, 4
.text:00000001401B9218                 add     r10, r11
.text:00000001401B921B                 cmp     edi, 20h
.text:00000001401B921E                 jnz     short loc_1401B9270
.text:00000001401B9220                 mov     r11, [rbx+0F0h]
.text:00000001401B9220 KiSystemServiceRepeat endp ; sp-analysis failed
.text:00000001401B9220
.text:00000001401B9227

使用windbg跟蹤:fffff800`957cdb04發現KeServiceDescriptorTable, dd一看,正是fffff800`95a38740,因此偏移地址在網絡

fffff800`957cd9c0~fffff800`957cdb04 之間,暴力搜索 4c8d1535ac2600session

0: kd> rdmsr C0000082
msr[c0000082] = fffff800`957cd9c0
0: kd> ln fffff800`957cd9c0
Browse module
Set bu breakpoint

(fffff800`957cd9c0)   nt!KiSystemCall64   |  (fffff800`957cdaf0)   nt!KiSystemServiceStart
Exact matches:
    nt!KiSystemCall64 (<no parameter info>)
windbg> .hh 
0: kd> u fffff800`957cd9c0
nt!KiSystemCall64:
fffff800`957cd9c0 0f01f8          swapgs
fffff800`957cd9c3 654889242510000000 mov   qword ptr gs:[10h],rsp
fffff800`957cd9cc 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]
fffff800`957cd9d5 6a2b            push    2Bh
fffff800`957cd9d7 65ff342510000000 push    qword ptr gs:[10h]
fffff800`957cd9df 4153            push    r11
fffff800`957cd9e1 6a33            push    33h
fffff800`957cd9e3 51              push    rcx
0: kd> uf nt!KiSystemCall64
Flow analysis was incomplete, some code may be missing
nt!KiSystemCall64:
fffff800`957cd9c0 0f01f8          swapgs
fffff800`957cd9c3 654889242510000000 mov   qword ptr gs:[10h],rsp
fffff800`957cd9cc 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]
fffff800`957cd9d5 6a2b            push    2Bh
fffff800`957cd9d7 65ff342510000000 push    qword ptr gs:[10h]
fffff800`957cd9df 4153            push    r11
fffff800`957cd9e1 6a33            push    33h
fffff800`957cd9e3 51              push    rcx
fffff800`957cd9e4 498bca          mov     rcx,r10
fffff800`957cd9e7 4883ec08        sub     rsp,8
fffff800`957cd9eb 55              push    rbp
fffff800`957cd9ec 4881ec58010000  sub     rsp,158h
fffff800`957cd9f3 488dac2480000000 lea     rbp,[rsp+80h]
fffff800`957cd9fb 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx
fffff800`957cda02 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi
fffff800`957cda09 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi
fffff800`957cda10 c645ab02        mov     byte ptr [rbp-55h],2
fffff800`957cda14 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
fffff800`957cda1d 0f0d8b90000000  prefetchw [rbx+90h]
fffff800`957cda24 0fae5dac        stmxcsr dword ptr [rbp-54h]
fffff800`957cda28 650fae142580010000 ldmxcsr dword ptr gs:[180h]
fffff800`957cda31 807b0300        cmp     byte ptr [rbx+3],0
fffff800`957cda35 66c785800000000000 mov   word ptr [rbp+80h],0
fffff800`957cda3e 0f849a000000    je      nt!KiSystemCall64+0x11e (fffff800`957cdade)  Branch

nt!KiSystemCall64+0x84:
fffff800`957cda44 488945b0        mov     qword ptr [rbp-50h],rax
fffff800`957cda48 48894db8        mov     qword ptr [rbp-48h],rcx
fffff800`957cda4c 488955c0        mov     qword ptr [rbp-40h],rdx
fffff800`957cda50 f6430303        test    byte ptr [rbx+3],3
fffff800`957cda54 4c8945c8        mov     qword ptr [rbp-38h],r8
fffff800`957cda58 4c894dd0        mov     qword ptr [rbp-30h],r9
fffff800`957cda5c 7405            je      nt!KiSystemCall64+0xa3 (fffff800`957cda63)  Branch

nt!KiSystemCall64+0x9e:
fffff800`957cda5e e86d60ffff      call    nt!KiSaveDebugRegisterState (fffff800`957c3ad0)

nt!KiSystemCall64+0xa3:
fffff800`957cda63 f6430304        test    byte ptr [rbx+3],4
fffff800`957cda67 740e            je      nt!KiSystemCall64+0xb7 (fffff800`957cda77)  Branch

nt!KiSystemCall64+0xa9:
fffff800`957cda69 fb              sti
fffff800`957cda6a 488bcc          mov     rcx,rsp
fffff800`957cda6d e84e285600      call    nt!PsPicoSystemCallDispatch (fffff800`95d302c0)
fffff800`957cda72 e9f4010000      jmp     nt!KiSystemServiceExit (fffff800`957cdc6b)  Branch

nt!KiSystemCall64+0xb7:
fffff800`957cda77 f6430380        test    byte ptr [rbx+3],80h
fffff800`957cda7b 7442            je      nt!KiSystemCall64+0xff (fffff800`957cdabf)  Branch

nt!KiSystemCall64+0xbd:
fffff800`957cda7d b9020100c0      mov     ecx,0C0000102h
fffff800`957cda82 0f32            rdmsr
fffff800`957cda84 48c1e220        shl     rdx,20h
fffff800`957cda88 480bc2          or      rax,rdx
fffff800`957cda8b 483983f0000000  cmp     qword ptr [rbx+0F0h],rax
fffff800`957cda92 742b            je      nt!KiSystemCall64+0xff (fffff800`957cdabf)  Branch

nt!KiSystemCall64+0xd4:
fffff800`957cda94 48398300020000  cmp     qword ptr [rbx+200h],rax
fffff800`957cda9b 7422            je      nt!KiSystemCall64+0xff (fffff800`957cdabf)  Branch

nt!KiSystemCall64+0xdd:
fffff800`957cda9d 488b93f0010000  mov     rdx,qword ptr [rbx+1F0h]
fffff800`957cdaa4 0fba6b7408      bts     dword ptr [rbx+74h],8
fffff800`957cdaa9 66ff8be6010000  dec     word ptr [rbx+1E6h]
fffff800`957cdab0 48898280000000  mov     qword ptr [rdx+80h],rax
fffff800`957cdab7 fb              sti
fffff800`957cdab8 e8c30d0000      call    nt!KiUmsCallEntry (fffff800`957ce880)
fffff800`957cdabd eb0b            jmp     nt!KiSystemCall64+0x10a (fffff800`957cdaca)  Branch

nt!KiSystemCall64+0xff:
fffff800`957cdabf f6430340        test    byte ptr [rbx+3],40h
fffff800`957cdac3 7405            je      nt!KiSystemCall64+0x10a (fffff800`957cdaca)  Branch

nt!KiSystemCall64+0x105:
fffff800`957cdac5 0fba6b7410      bts     dword ptr [rbx+74h],10h

nt!KiSystemCall64+0x10a:
fffff800`957cdaca 488b45b0        mov     rax,qword ptr [rbp-50h]
fffff800`957cdace 488b4db8        mov     rcx,qword ptr [rbp-48h]
fffff800`957cdad2 488b55c0        mov     rdx,qword ptr [rbp-40h]
fffff800`957cdad6 4c8b45c8        mov     r8,qword ptr [rbp-38h]
fffff800`957cdada 4c8b4dd0        mov     r9,qword ptr [rbp-30h]

nt!KiSystemCall64+0x11e:
fffff800`957cdade fb              sti
fffff800`957cdadf 48898b88000000  mov     qword ptr [rbx+88h],rcx
fffff800`957cdae6 898380000000    mov     dword ptr [rbx+80h],eax
fffff800`957cdaec 0f1f4000        nop     dword ptr [rax]
fffff800`957cdaf0 4889a390000000  mov     qword ptr [rbx+90h],rsp
fffff800`957cdaf7 8bf8            mov     edi,eax
fffff800`957cdaf9 c1ef07          shr     edi,7
fffff800`957cdafc 83e720          and     edi,20h
fffff800`957cdaff 25ff0f0000      and     eax,0FFFh

nt!KiSystemServiceRepeat:
fffff800`957cdb04 4c8d1535ac2600  lea     r10,[nt!KeServiceDescriptorTable (fffff800`95a38740)]
fffff800`957cdb0b 4c8d1deeab2600  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`95a38700)]
fffff800`957cdb12 f7437840000000  test    dword ptr [rbx+78h],40h
fffff800`957cdb19 4d0f45d3        cmovne  r10,r11
fffff800`957cdb1d 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
fffff800`957cdb22 0f83ef020000    jae     nt!KiSystemServiceExit+0x1ac (fffff800`957cde17)  Branch

nt!KiSystemServiceRepeat+0x24:
fffff800`957cdb28 4e8b1417        mov     r10,qword ptr [rdi+r10]
fffff800`957cdb2c 4d631c82        movsxd  r11,dword ptr [r10+rax*4]
fffff800`957cdb30 498bc3          mov     rax,r11
fffff800`957cdb33 49c1fb04        sar     r11,4
fffff800`957cdb37 4d03d3          add     r10,r11
fffff800`957cdb3a 83ff20          cmp     edi,20h
fffff800`957cdb3d 7551            jne     nt!KiSystemServiceGdiTebAccess+0x4a (fffff800`957cdb90)  Branch

...

代碼:ide

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)
		if ((*(PULONG)pStartSearchAddress & 0x00FFFFFF) == 0x158d4c)
		{
			//pFindCodeAddress = (PULONG)(pStartSearchAddress - 12);
			pFindCodeAddress = (PULONG)(pStartSearchAddress + 3);
			//return (ULONG_PTR)pFindCodeAddress + (((*(PULONG)pFindCodeAddress) >> 24) + 7) + (ULONG_PTR)(((*(PULONG)(pFindCodeAddress + 1)) & 0x0FFFF) << 8);
			return ((ULONG_PTR)pFindCodeAddress-3 + 7) + ((LONG)(*(PULONG)pFindCodeAddress));
		}
	}
	return 0;
}

或(來自網絡):函數

typedef struct _SYSTEM_SERVICE_TABLE{
    PVOID          ServiceTableBase;
    PVOID          ServiceCounterTableBase;
    ULONGLONG      NumberOfServices;
    PVOID          ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
 
ULONGLONG MyGetKeServiceDescriptorTable()
{
	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 + 1))
		{
			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;
}
 
ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
	LONG dwtmp = 0;
	PULONG ServiceTableBase = NULL;
	ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
	dwtmp = ServiceTableBase[id];
	dwtmp = dwtmp >> 4;
	return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}

查找ntoskrnl.exe基址(SSDT實際上就像PE文件的導出表,只是x64把隱藏了,可是這個表仍然在PE文件的內部):fetch

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]; //ntoskrnl.exe模塊
			imgBaseAddr = pSystemModule->Base; //內核基址
			return imgBaseAddr;
		}
	}
	return 0;
}

在內核地址附近尋找空缺(用來作跳板,填充:mov rax, xxx ; jmp rax)this

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

所有代碼:加密

////////////////////////////////////////////////////////////////////////////
//
//	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 : %llx\n", 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 : 0x%08x\n", dwExportRVA);
		Dbg("Export table size : 0x%08x\n", dwExportSize);
		Dbg("EAT : 0x%08X\n", (PIMAGE_EXPORT_DIRECTORY)((unsigned char*)Ntdll_ImageBase+dwExportRVA));
		pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((unsigned char*)Ntdll_ImageBase+dwExportRVA);
		Dbg("number of exported functions : 0x%08x\n", 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 : %s\n", name);
					Dbg("addr : 0x%08x\n", ((unsigned char*)Ntdll_ImageBase + addrFunc[addrOrdinal[i]]));
					Dbg("syscall : %x\n", *(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 : %x\n", 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: %d\n", 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
		//modified by simpower91 因爲SSDT加密後偏移地址不能爲負數,所以searchAddr必需要在SSDT以後
		//然而SSDT卻在.rdata區段,SSDT所指向的入口有的在PAGE區段,理論上放在.rdata以後的可X區段均可以,PAGE屬於可交換分頁,位於PAGELK以後。
		//if(pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)
		if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)&&(strcmp(pSectionHeader->Name,"PAGELK")==0))
		{
			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]; //ntoskrnl.exe模塊
			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)
		if ((*(PULONG)pStartSearchAddress & 0x00FFFFFF) == 0x158d4c)
		{
			//pFindCodeAddress = (PULONG)(pStartSearchAddress - 12);
			pFindCodeAddress = (PULONG)(pStartSearchAddress + 3);
			//return (ULONG_PTR)pFindCodeAddress + (((*(PULONG)pFindCodeAddress) >> 24) + 7) + (ULONG_PTR)(((*(PULONG)(pFindCodeAddress + 1)) & 0x0FFFF) << 8);
			return ((ULONG_PTR)pFindCodeAddress-3 + 7) + ((LONG)(*(PULONG)pFindCodeAddress));
		}
	}
	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 : %llx\n", KeServiceDescriptorTable);
	KiServiceTable = KeServiceDescriptorTable->ServiceTableBase;
	Dbg("KiServiceTable : %llx\n", KiServiceTable);
	kernelBase = GetKernelBase();
	Dbg("Kernel base addr : %llx\n", kernelBase);
	pStartSearchAddress = GetEndOfTextSection(kernelBase);
	Dbg("pStartSearchAddress : %llx\n", 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, "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);
	//the up is ok
	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);
	return;
	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);
	return; //問題函數
	Install_Hook(GetSyscallNumber(pImageExportDirectory, "ZwSetInformationFile", offsetSyscall), (PVOID)Hooked_NtSetInformationFile, (PVOID*)&Orig_NtSetInformationFile, 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[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0"; //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 : %llx\n", *origFunc);
		Dbg("Hooked_Func : %llx\n", hookedFunc);
		// mov rax, @NewFunc; jmp rax
		*(PULONGLONG)(jmp_to_newFunction+2) = (ULONGLONG)hookedFunc;

		trampoline = SearchCodeCave(searchAddr);
		Dbg("trampoline : %llx\n", 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 );
}

最後要說一下即便是調試模式也要過Patch Guard,由於當你斷開調試器PG就會檢測CRITICAL_STRUCTURE_CORRUPTION藍屏。spa

其描述是這樣的(windbg dump):

CRITICAL_STRUCTURE_CORRUPTION (109)
This bugcheck is generated when the kernel detects that critical kernel code or
data have been corrupted. There are generally three causes for a corruption:
1) A driver has inadvertently or deliberately modified critical kernel code
 or data. See http://www.microsoft.com/whdc/driver/kernel/64bitPatching.mspx
2) A developer attempted to set a normal kernel breakpoint using a kernel
 debugger that was not attached when the system was booted. Normal breakpoints,
 "bp", can only be set if the debugger is attached at boot time. Hardware
 breakpoints, "ba", can be set at any time.
3) A hardware corruption occurred, e.g. failing RAM holding kernel code or data.
Arguments:
Arg1: a3a01f590c498504, Reserved
Arg2: b3b72bdf5eca4827, Reserved
Arg3: fffff800da38e020, Failure type dependent information
Arg4: 0000000000000000, Type of corrupted region, can be
	0   : A generic data region
	1   : Modification of a function or .pdata
	2   : A processor IDT
	3   : A processor GDT
	4   : Type 1 process list corruption
	5   : Type 2 process list corruption
	6   : Debug routine modification
	7   : Critical MSR modification
	8   : Object type
	9   : A processor IVT
	a   : Modification of a system service function
	b   : A generic session data region
	c   : Modification of a session function or .pdata
	d   : Modification of an import table
	e   : Modification of a session import table
	f   : Ps Win32 callout modification
	10  : Debug switch routine modification
	11  : IRP allocator modification
	12  : Driver call dispatcher modification
	13  : IRP completion dispatcher modification
	14  : IRP deallocator modification
	15  : A processor control register
	16  : Critical floating point control register modification
	17  : Local APIC modification
	18  : Kernel notification callout modification
	19  : Loaded module list modification
	1a  : Type 3 process list corruption
	1b  : Type 4 process list corruption
	1c  : Driver object corruption
	1d  : Executive callback object modification
	1e  : Modification of module padding
	1f  : Modification of a protected process
	20  : A generic data region
	21  : A page hash mismatch
	22  : A session page hash mismatch
	23  : Load config directory modification
	24  : Inverted function table modification
	25  : Session configuration modification
	26  : An extended processor control register
	27  : Type 1 pool corruption
	28  : Type 2 pool corruption
	29  : Type 3 pool corruption
	2a  : Type 4 pool corruption
	101 : General pool corruption
	102 : Modification of win32k.sys

...

過PG的方法(關鍵點是 /start AUTOENABLE,注意啓動後不能讓調試器連進來並關閉調試器,不然就又會啓動pg):

There is another thing to mention. You can of course disable PatchGuard in a DOCUMENTED, STABLE and EASY manner, by running the following commands in a root-shell and restarting the PC afterwards:

Hide   Copy Code

Bcdedit /debug ON
Bcdedit /dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200 /start AUTOENABLE /noumex
網絡方式:
bcdedit /dbgsettings net hostip:w.x.y.z port:n key:Key

「noumex」 will disable user mode exceptions for kernel debuggers which in fact would Visual Studio prevent from working. 「AUTOENABLE」 will force PatchGuard to be disabled, because even if you don’t attach a kernel debugger, you could do it at any time, and that is enough.

相關文章
相關標籤/搜索