前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >暴力搜索x64 ssdt 以及挂钩HOOK

暴力搜索x64 ssdt 以及挂钩HOOK

作者头像
战神伽罗
发布2019-07-24 16:05:27
2.2K0
发布2019-07-24 16:05:27
举报

IDA加载ntoskrnl.exe 微软符号,进入,jump by name,随便输入一个,比如zwwritefile,层层跟踪,进入,可以发现

.text:00000001401B91D4 lea r10, KeServiceDescriptorTable

代码语言:javascript
复制
.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 之间,暴力搜索 4c8d1535ac2600

代码语言:javascript
复制
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

...

代码:

代码语言:javascript
复制
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;
}

或(来自网络):

代码语言:javascript
复制
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文件的内部):

代码语言:javascript
复制
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)

代码语言:javascript
复制
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;
}

全部代码:

代码语言: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 : %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蓝屏。

其描述是这样的(windbg dump):

代码语言:javascript
复制
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

代码语言:javascript
复制
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.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档