IDA加载ntoskrnl.exe 微软符号,进入,jump by name,随便输入一个,比如zwwritefile,层层跟踪,进入,可以发现
.text:00000001401B91D4 lea r10, KeServiceDescriptorTable
.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
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
...
代码:
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文件的内部):
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)
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蓝屏。
其描述是这样的(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.