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.