diff --git a/BranchTracerSys/kernel-hooks/Hooks.cpp b/BranchTracerSys/kernel-hooks/Hooks.cpp new file mode 100644 index 0000000..c58a305 --- /dev/null +++ b/BranchTracerSys/kernel-hooks/Hooks.cpp @@ -0,0 +1,274 @@ +#include "Hooks.h" + +#define PRINT_PREFIX "[Hooks] " +#include "LDasm.h" +#include +#include + +/* +00000 | 68 88776655 | push 55667788 | +00005 | C74424 04 44332211 | mov dword ptr ss:[rsp+4],11223344 | +0000D | C3 | ret | +*/ +#define PUSHRET14_CODE {0x68,0x88,0x77,0x66,0x55,0xC7,0x44,0x24,0x04,0x44,0x33,0x22,0x11,0xC3} +#define PUSHRET14_JMPADDR_LOW 9 +#define PUSHRET14_JMPADDR_HIGH 1 + +/* +0000 | 48:B8 8877665544332211 | mov rax,1122334455667788 | +000A | FFE0 | jmp rax | + */ +#define JMPRAX12_CODE {0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xE0} +#define JMPRAX12_CODE_JMPADDR 0x2 + + /* + 00007FF692980000 | 41:57 | push r15 | + 00007FF692980002 | 41:56 | push r14 | r14:"minkernel\\ntdll\\ldrinit.c" + 00007FF692980004 | 41:55 | push r13 | + 00007FF692980006 | 41:54 | push r12 | + 00007FF692980008 | 41:53 | push r11 | + 00007FF69298000A | 41:52 | push r10 | + 00007FF69298000C | 41:51 | push r9 | + 00007FF69298000E | 41:50 | push r8 | + 00007FF692980010 | 57 | push rdi | rdi:PEB.InheritedAddressSpace + 00007FF692980011 | 56 | push rsi | rsi:"LdrpInitializeProcess" + 00007FF692980012 | 55 | push rbp | + 00007FF692980013 | 48:8D7424 58 | lea rsi,qword ptr ss:[rsp+58] | + 00007FF692980018 | 56 | push rsi | dummy for rsp + 00007FF692980019 | 53 | push rbx | + 00007FF69298001A | 52 | push rdx | + 00007FF69298001B | 51 | push rcx | rcx:sub_7FFACE90B1AC+88 + 00007FF69298001C | 50 | push rax | + 00007FF69298001D | 48:8D0C24 | lea rcx,qword ptr ss:[rsp] | rcx:sub_7FFACE90B1AC+88 + 00007FF692980021 | 48:B8 EFCDAB8967452301 | mov rax,123456789ABCDEF | + 00007FF69298002B | 48:83EC 08 | sub rsp,8 | + 00007FF69298002F | FFD0 | call rax | + 00007FF692980031 | 48:83C4 08 | add rsp,8 | + 00007FF692980035 | 58 | pop rax | + 00007FF692980036 | 59 | pop rcx | rcx:sub_7FFACE90B1AC+88 + 00007FF692980037 | 5A | pop rdx | + 00007FF692980038 | 5B | pop rbx | + 00007FF692980039 | 48:83C4 08 | add rsp,8 | + 00007FF69298003D | 5D | pop rbp | + 00007FF69298003E | 5E | pop rsi | rsi:"LdrpInitializeProcess" + 00007FF69298003F | 5F | pop rdi | rdi:PEB.InheritedAddressSpace + 00007FF692980040 | 41:58 | pop r8 | + 00007FF692980042 | 41:59 | pop r9 | + 00007FF692980044 | 41:5A | pop r10 | + 00007FF692980046 | 41:5B | pop r11 | + 00007FF692980048 | 41:5C | pop r12 | + 00007FF69298004A | 41:5D | pop r13 | + 00007FF69298004C | 41:5E | pop r14 | r14:"minkernel\\ntdll\\ldrinit.c" + 00007FF69298004E | 41:5F | pop r15 | + */ +#define TEMPLATE_CODE {0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x41, 0x53, 0x41, 0x52, 0x41, 0x51, 0x41, 0x50, 0x57, 0x56, 0x55, 0x48, 0x8D, 0x74, 0x24, 0x58, 0x56, 0x53, 0x52, 0x51, 0x50, 0x48, 0x8D, 0x0C, 0x24, 0x48, 0xB8, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0x48, 0x83, 0xEC, 0x08, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x08, 0x58, 0x59, 0x5A, 0x5B, 0x48, 0x83, 0xC4, 0x08, 0x5D, 0x5E, 0x5F, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41, 0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F} +#define TEMPLATE_CODE_HANDLE 0x23 + + +KIRQL WPOFFx64() +{ + KIRQL irql = KeRaiseIrqlToDpcLevel(); + UINT64 cr0 = __readcr0(); + cr0 &= 0xfffffffffffeffff; + __writecr0(cr0); + _disable(); + return irql; +} + +void WPONx64(KIRQL irql) +{ + UINT64 cr0 = __readcr0(); + cr0 |= 0x10000; + _enable(); + __writecr0(cr0); + KeLowerIrql(irql); +} + + +NTSTATUS InsertIntercept64(__in PVOID SourceCode, __in P_HANDLE HandleRoutine, __in PINTERCEPT_CREATE lpCreateInfo, __out PINTERCEPT_INFO lpInterceptInfo) +{ + KdPrint((PRINT_PREFIX "SourceCode:%p\n", SourceCode)); + KdPrint((PRINT_PREFIX "HandleRoutine:%p\n", HandleRoutine)); + + + // 检查目标源代码地址是否可用. + if (!MmIsAddressValid(SourceCode)) + { + KdPrint((PRINT_PREFIX "SourceCode 是无效地址!\n")); + return STATUS_UNSUCCESSFUL; + } + + // hook最小需要的大小. + ULONG patchNeedSize = 0; + switch (lpCreateInfo->patchType) + { + case PUSH_RET_14: + patchNeedSize = 14; + break; + case MRAX_JMP_12: + patchNeedSize = 12; + break; + default: + return STATUS_UNSUCCESSFUL; + } + + // 计算Hook所需的大小. + ULONG hookSize = 0; + while (hookSize < patchNeedSize) + { + ldasm_data ld; + PUCHAR p = (PUCHAR)SourceCode + hookSize; + ULONG length = ldasm(p, &ld, 1); + hookSize += length; + } + + UCHAR code_template[] = TEMPLATE_CODE; + UCHAR code_pushret14[] = PUSHRET14_CODE; + + // 计算各种内存块大小 + ULONG templateCodeSize = sizeof(code_template); + ULONG preCodeSize = lpCreateInfo->preCodeSize; + ULONG orignalCodeSize = hookSize; // 被覆盖的原始代码大小 + ULONG returnCodeSize = sizeof(code_pushret14); // 用于跳转回原处的代码大小 + ULONG interceptCodeSize = templateCodeSize + preCodeSize + orignalCodeSize + returnCodeSize; // 拦截代码 + + // 申请内存 + PVOID interceptCode = ExAllocatePoolWithTag(NonPagedPool, interceptCodeSize, 'KOOH'); + if (interceptCode == NULL) + { + KdPrint((PRINT_PREFIX "AllocatePool Failed!\n")); + return STATUS_UNSUCCESSFUL; + } + RtlFillMemory(interceptCode, interceptCodeSize, 0x90); + + // 计算指针 + PUCHAR templateCode = (PUCHAR)interceptCode; + PUCHAR preCode = (PUCHAR)interceptCode + templateCodeSize; + PUCHAR orginalCode = (PUCHAR)interceptCode + templateCodeSize + preCodeSize; + PUCHAR returnCode = (PUCHAR)interceptCode + templateCodeSize + preCodeSize + orignalCodeSize; + + // 部署interceptCode代码 + memcpy(templateCode, code_template, templateCodeSize); + memcpy(preCode, lpCreateInfo->preCode, preCodeSize); + memcpy(orginalCode, SourceCode, orignalCodeSize); + memcpy(returnCode, code_pushret14, returnCodeSize); + + // 修复Hnadle地址 + memcpy(templateCode + TEMPLATE_CODE_HANDLE, &HandleRoutine, sizeof(ULONG64)); + + // 修复returnCode地址 + LARGE_INTEGER lagerInteger; + lagerInteger.QuadPart = (ULONG64)SourceCode + hookSize; + memcpy(returnCode + PUSHRET14_JMPADDR_LOW, &lagerInteger.HighPart, sizeof(ULONG)); + memcpy(returnCode + PUSHRET14_JMPADDR_HIGH, &lagerInteger.LowPart, sizeof(ULONG)); + + PVOID code_hookcode = NULL; + // 准备hookCode 并修复硬编码地址 + switch (lpCreateInfo->patchType) + { + case PUSH_RET_14: + { + UCHAR codeBuffer[] = PUSHRET14_CODE; + lagerInteger.QuadPart = (ULONG64)interceptCode; + memcpy(codeBuffer + PUSHRET14_JMPADDR_LOW, &lagerInteger.HighPart, sizeof(ULONG)); + memcpy(codeBuffer + PUSHRET14_JMPADDR_HIGH, &lagerInteger.LowPart, sizeof(ULONG)); + code_hookcode = codeBuffer; + break; + } + case MRAX_JMP_12: + { + UCHAR codeBuffer[] = JMPRAX12_CODE; + memcpy(codeBuffer + JMPRAX12_CODE_JMPADDR, &interceptCode, sizeof(ULONG64)); + code_hookcode = codeBuffer; + break; + } + default: + return STATUS_UNSUCCESSFUL; + } + + + + + // 部署hookCode + PUSHORT DestHeader = (PUSHORT)SourceCode; + PUSHORT CodeHeader = (PUSHORT)code_hookcode; + PUCHAR DestTail = (PUCHAR)SourceCode + 2; + PUCHAR CodeTail = (PUCHAR)code_hookcode + 2; + SIZE_T TailSize = patchNeedSize - 2; + + // 更新代码 + KIRQL irql = WPOFFx64(); + *DestHeader = 0xFEEB; + memcpy(DestTail, CodeTail, TailSize); + memset((PUCHAR)SourceCode + patchNeedSize, 0x90, hookSize - patchNeedSize); + *DestHeader = *CodeHeader; + WPONx64(irql); + + //UpdateCode(SourceCode, code_hookcode, patchNeedSize); + //KIRQL irql = WPOFFx64(); + //memcpy(SourceCode, code_hookcode, patchNeedSize); // 修改代码 + //memset((PUCHAR)SourceCode + patchNeedSize, // 填充空隙 + // 0x90, + // hookSize - patchNeedSize + //); + //WPONx64(irql); + + if (lpInterceptInfo) + { + lpInterceptInfo->hookFlag = TRUE; + + lpInterceptInfo->orignalCode = orginalCode; + lpInterceptInfo->orignalCodeSize = orignalCodeSize; + + lpInterceptInfo->sourceCode = SourceCode; + lpInterceptInfo->intercetCode = interceptCode; + lpInterceptInfo->intercetCodeSize = interceptCodeSize; + } + + KdPrint((PRINT_PREFIX "InterceptCode:%p HookSize:%ld\n", interceptCode, hookSize)); + return STATUS_SUCCESS; +} + +NTSTATUS RemoveIntercept(PINTERCEPT_INFO interceptInfo) +{ + if (interceptInfo->hookFlag == FALSE) + { + return STATUS_SUCCESS; + } + + PVOID SourceCode = interceptInfo->sourceCode; + PVOID InterceptCode = interceptInfo->intercetCode; + ULONG OrignalCodeSize = interceptInfo->orignalCodeSize; + + if (!MmIsAddressValid(SourceCode)) + { + KdPrint((PRINT_PREFIX "SourceCode is invaild! SourceCode=%p \n", SourceCode)); + return STATUS_UNSUCCESSFUL; + } + + if (!MmIsAddressValid(InterceptCode)) + { + KdPrint((PRINT_PREFIX "InterceptCode is invaild! InterceptCode=%p \n", InterceptCode)); + return STATUS_UNSUCCESSFUL; + } + + PVOID OrignalCode = interceptInfo->orignalCode; + + // 还原代码 + //KIRQL irql = WPOFFx64(); + //memcpy(SourceCode, OrignalCode, OrignalCodeSize); + //WPONx64(irql); + + KIRQL irql = WPOFFx64(); + *(PUSHORT)SourceCode = 0xFEEB; + memcpy(PUCHAR(SourceCode) + 2, (PUCHAR)OrignalCode +2, OrignalCodeSize - 2); + *(PUSHORT)SourceCode = *(PUSHORT)OrignalCode; + WPONx64(irql); + + + // 释放内存 + //ExFreePool(InterceptCode); + + return STATUS_SUCCESS; +} + diff --git a/BranchTracerSys/kernel-hooks/Hooks.h b/BranchTracerSys/kernel-hooks/Hooks.h new file mode 100644 index 0000000..738f652 --- /dev/null +++ b/BranchTracerSys/kernel-hooks/Hooks.h @@ -0,0 +1,94 @@ +#pragma once + +#include + +#pragma warning(disable:4201) +typedef struct _REGISTER_CONTEXT +{ + union + { + struct + { + ULONG eax; + ULONG ecx; + ULONG edx; + ULONG ebx; + ULONG esp; + ULONG ebp; + ULONG esi; + ULONG edi; + } reg32; + + struct + { + ULONG64 rax; + ULONG64 rcx; + ULONG64 rdx; + ULONG64 rbx; + ULONG64 rsp; + ULONG64 rbp; + ULONG64 rsi; + ULONG64 rdi; + ULONG64 r8; + ULONG64 r9; + ULONG64 r10; + ULONG64 r11; + ULONG64 r12; + ULONG64 r13; + ULONG64 r14; + ULONG64 r15; + } reg64; + }; +} REGISTER_CONTEXT, *PREGISTER_CONTEXT; + + +typedef struct _INTERCEPT_INFO +{ + BOOLEAN hookFlag; + + ULONG orignalCodeSize; + ULONG intercetCodeSize; + + PVOID sourceCode; + PVOID orignalCode; + PVOID intercetCode; +} INTERCEPT_INFO, *PINTERCEPT_INFO; + +enum INTERCEPT_HOOK_TYPE +{ + PUSH_RET_14, + MRAX_JMP_12 +}; + +typedef struct _INTERCEPT_CREATE +{ + ULONG patchType; + + PVOID preCode; + ULONG preCodeSize; +} INTERCEPT_CREATE, *PINTERCEPT_CREATE; + +typedef VOID (NTAPI* P_HANDLE)(PREGISTER_CONTEXT Context); + +KIRQL WPOFFx64(); +void WPONx64(KIRQL irql); +/* + * 使用inline-hook再目标代码位置插入代码. 让其可以执行HandleRoutine + * FBI WARNING: 没有处理多核并行的情况, 极端情况下可能导致蓝屏. + * + * 名词解释: + * HookCode: 用于替换源代码的跳转指令(push xx; mov [rsp+4], xx; ret) 固定大小为14字节. + * OriginalCode: 被替换的原始指令. Size >= 14 + * TemplateCode: HookCode需要跳转到该位置. 主要做3件事: pushad / call handle / popad + * + * 参数: + * SourceCode: 需要插入的代码位置. 注意:需要保证14+字节的代码内,没有使用相对地址硬编码. + * HandleRoutine: hook成功后. 每次都会调用这个例程. + */ +NTSTATUS InsertIntercept64(__in PVOID SourceCode,__in P_HANDLE HandleRoutine,__in PINTERCEPT_CREATE lpCreateInfo,__out PINTERCEPT_INFO lpInterceptInfo); + +/* + * 还原被hook的代码 + */ +NTSTATUS RemoveIntercept(PINTERCEPT_INFO interceptInfo); + diff --git a/BranchTracerSys/kernel-hooks/LDasm.c b/BranchTracerSys/kernel-hooks/LDasm.c new file mode 100644 index 0000000..7b4d179 --- /dev/null +++ b/BranchTracerSys/kernel-hooks/LDasm.c @@ -0,0 +1,851 @@ +/* +* +* Copyright (c) 2009-2011 +* vol4ok PGP KEY ID: 26EC143CCDC61C9D +* + +This program 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. + +This program 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 this program. If not, see . + +*/ + +#include "LDasm.h" + +/* + Instruction format: + + | prefix | REX | opcode | modR/M | SIB | disp8/16/32 | imm8/16/32/64 | + + */ + +#define OP_NONE 0x00 +#define OP_INVALID 0x80 + +#define OP_DATA_I8 0x01 +#define OP_DATA_I16 0x02 +#define OP_DATA_I16_I32 0x04 +#define OP_DATA_I16_I32_I64 0x08 +#define OP_EXTENDED 0x10 +#define OP_RELATIVE 0x20 +#define OP_MODRM 0x40 +#define OP_PREFIX 0x80 + + +static unsigned char flags_table[256] = +{ + /* 00 */ OP_MODRM, + /* 01 */ OP_MODRM, + /* 02 */ OP_MODRM, + /* 03 */ OP_MODRM, + /* 04 */ OP_DATA_I8, + /* 05 */ OP_DATA_I16_I32, + /* 06 */ OP_NONE, + /* 07 */ OP_NONE, + /* 08 */ OP_MODRM, + /* 09 */ OP_MODRM, + /* 0A */ OP_MODRM, + /* 0B */ OP_MODRM, + /* 0C */ OP_DATA_I8, + /* 0D */ OP_DATA_I16_I32, + /* 0E */ OP_NONE, + /* 0F */ OP_NONE, + + /* 10 */ OP_MODRM, + /* 11 */ OP_MODRM, + /* 12 */ OP_MODRM, + /* 13 */ OP_MODRM, + /* 14 */ OP_DATA_I8, + /* 15 */ OP_DATA_I16_I32, + /* 16 */ OP_NONE, + /* 17 */ OP_NONE, + /* 18 */ OP_MODRM, + /* 19 */ OP_MODRM, + /* 1A */ OP_MODRM, + /* 1B */ OP_MODRM, + /* 1C */ OP_DATA_I8, + /* 1D */ OP_DATA_I16_I32, + /* 1E */ OP_NONE, + /* 1F */ OP_NONE, + + /* 20 */ OP_MODRM, + /* 21 */ OP_MODRM, + /* 22 */ OP_MODRM, + /* 23 */ OP_MODRM, + /* 24 */ OP_DATA_I8, + /* 25 */ OP_DATA_I16_I32, + /* 26 */ OP_PREFIX, + /* 27 */ OP_NONE, + /* 28 */ OP_MODRM, + /* 29 */ OP_MODRM, + /* 2A */ OP_MODRM, + /* 2B */ OP_MODRM, + /* 2C */ OP_DATA_I8, + /* 2D */ OP_DATA_I16_I32, + /* 2E */ OP_PREFIX, + /* 2F */ OP_NONE, + + /* 30 */ OP_MODRM, + /* 31 */ OP_MODRM, + /* 32 */ OP_MODRM, + /* 33 */ OP_MODRM, + /* 34 */ OP_DATA_I8, + /* 35 */ OP_DATA_I16_I32, + /* 36 */ OP_PREFIX, + /* 37 */ OP_NONE, + /* 38 */ OP_MODRM, + /* 39 */ OP_MODRM, + /* 3A */ OP_MODRM, + /* 3B */ OP_MODRM, + /* 3C */ OP_DATA_I8, + /* 3D */ OP_DATA_I16_I32, + /* 3E */ OP_PREFIX, + /* 3F */ OP_NONE, + + /* 40 */ OP_NONE, + /* 41 */ OP_NONE, + /* 42 */ OP_NONE, + /* 43 */ OP_NONE, + /* 44 */ OP_NONE, + /* 45 */ OP_NONE, + /* 46 */ OP_NONE, + /* 47 */ OP_NONE, + /* 48 */ OP_NONE, + /* 49 */ OP_NONE, + /* 4A */ OP_NONE, + /* 4B */ OP_NONE, + /* 4C */ OP_NONE, + /* 4D */ OP_NONE, + /* 4E */ OP_NONE, + /* 4F */ OP_NONE, + + /* 50 */ OP_NONE, + /* 51 */ OP_NONE, + /* 52 */ OP_NONE, + /* 53 */ OP_NONE, + /* 54 */ OP_NONE, + /* 55 */ OP_NONE, + /* 56 */ OP_NONE, + /* 57 */ OP_NONE, + /* 58 */ OP_NONE, + /* 59 */ OP_NONE, + /* 5A */ OP_NONE, + /* 5B */ OP_NONE, + /* 5C */ OP_NONE, + /* 5D */ OP_NONE, + /* 5E */ OP_NONE, + /* 5F */ OP_NONE, + /* 60 */ OP_NONE, + + /* 61 */ OP_NONE, + /* 62 */ OP_MODRM, + /* 63 */ OP_MODRM, + /* 64 */ OP_PREFIX, + /* 65 */ OP_PREFIX, + /* 66 */ OP_PREFIX, + /* 67 */ OP_PREFIX, + /* 68 */ OP_DATA_I16_I32, + /* 69 */ OP_MODRM | OP_DATA_I16_I32, + /* 6A */ OP_DATA_I8, + /* 6B */ OP_MODRM | OP_DATA_I8, + /* 6C */ OP_NONE, + /* 6D */ OP_NONE, + /* 6E */ OP_NONE, + /* 6F */ OP_NONE, + + /* 70 */ OP_RELATIVE | OP_DATA_I8, + /* 71 */ OP_RELATIVE | OP_DATA_I8, + /* 72 */ OP_RELATIVE | OP_DATA_I8, + /* 73 */ OP_RELATIVE | OP_DATA_I8, + /* 74 */ OP_RELATIVE | OP_DATA_I8, + /* 75 */ OP_RELATIVE | OP_DATA_I8, + /* 76 */ OP_RELATIVE | OP_DATA_I8, + /* 77 */ OP_RELATIVE | OP_DATA_I8, + /* 78 */ OP_RELATIVE | OP_DATA_I8, + /* 79 */ OP_RELATIVE | OP_DATA_I8, + /* 7A */ OP_RELATIVE | OP_DATA_I8, + /* 7B */ OP_RELATIVE | OP_DATA_I8, + /* 7C */ OP_RELATIVE | OP_DATA_I8, + /* 7D */ OP_RELATIVE | OP_DATA_I8, + /* 7E */ OP_RELATIVE | OP_DATA_I8, + /* 7F */ OP_RELATIVE | OP_DATA_I8, + + /* 80 */ OP_MODRM | OP_DATA_I8, + /* 81 */ OP_MODRM | OP_DATA_I16_I32, + /* 82 */ OP_MODRM | OP_DATA_I8, + /* 83 */ OP_MODRM | OP_DATA_I8, + /* 84 */ OP_MODRM, + /* 85 */ OP_MODRM, + /* 86 */ OP_MODRM, + /* 87 */ OP_MODRM, + /* 88 */ OP_MODRM, + /* 89 */ OP_MODRM, + /* 8A */ OP_MODRM, + /* 8B */ OP_MODRM, + /* 8C */ OP_MODRM, + /* 8D */ OP_MODRM, + /* 8E */ OP_MODRM, + /* 8F */ OP_MODRM, + + /* 90 */ OP_NONE, + /* 91 */ OP_NONE, + /* 92 */ OP_NONE, + /* 93 */ OP_NONE, + /* 94 */ OP_NONE, + /* 95 */ OP_NONE, + /* 96 */ OP_NONE, + /* 97 */ OP_NONE, + /* 98 */ OP_NONE, + /* 99 */ OP_NONE, + /* 9A */ OP_DATA_I16 | OP_DATA_I16_I32, + /* 9B */ OP_NONE, + /* 9C */ OP_NONE, + /* 9D */ OP_NONE, + /* 9E */ OP_NONE, + /* 9F */ OP_NONE, + + /* A0 */ OP_DATA_I8, + /* A1 */ OP_DATA_I16_I32_I64, + /* A2 */ OP_DATA_I8, + /* A3 */ OP_DATA_I16_I32_I64, + /* A4 */ OP_NONE, + /* A5 */ OP_NONE, + /* A6 */ OP_NONE, + /* A7 */ OP_NONE, + /* A8 */ OP_DATA_I8, + /* A9 */ OP_DATA_I16_I32, + /* AA */ OP_NONE, + /* AB */ OP_NONE, + /* AC */ OP_NONE, + /* AD */ OP_NONE, + /* AE */ OP_NONE, + /* AF */ OP_NONE, + + /* B0 */ OP_DATA_I8, + /* B1 */ OP_DATA_I8, + /* B2 */ OP_DATA_I8, + /* B3 */ OP_DATA_I8, + /* B4 */ OP_DATA_I8, + /* B5 */ OP_DATA_I8, + /* B6 */ OP_DATA_I8, + /* B7 */ OP_DATA_I8, + /* B8 */ OP_DATA_I16_I32_I64, + /* B9 */ OP_DATA_I16_I32_I64, + /* BA */ OP_DATA_I16_I32_I64, + /* BB */ OP_DATA_I16_I32_I64, + /* BC */ OP_DATA_I16_I32_I64, + /* BD */ OP_DATA_I16_I32_I64, + /* BE */ OP_DATA_I16_I32_I64, + /* BF */ OP_DATA_I16_I32_I64, + + /* C0 */ OP_MODRM | OP_DATA_I8, + /* C1 */ OP_MODRM | OP_DATA_I8, + /* C2 */ OP_DATA_I16, + /* C3 */ OP_NONE, + /* C4 */ OP_MODRM, + /* C5 */ OP_MODRM, + /* C6 */ OP_MODRM | OP_DATA_I8, + /* C7 */ OP_MODRM | OP_DATA_I16_I32, + /* C8 */ OP_DATA_I8 | OP_DATA_I16, + /* C9 */ OP_NONE, + /* CA */ OP_DATA_I16, + /* CB */ OP_NONE, + /* CC */ OP_NONE, + /* CD */ OP_DATA_I8, + /* CE */ OP_NONE, + /* CF */ OP_NONE, + + /* D0 */ OP_MODRM, + /* D1 */ OP_MODRM, + /* D2 */ OP_MODRM, + /* D3 */ OP_MODRM, + /* D4 */ OP_DATA_I8, + /* D5 */ OP_DATA_I8, + /* D6 */ OP_NONE, + /* D7 */ OP_NONE, + /* D8 */ OP_MODRM, + /* D9 */ OP_MODRM, + /* DA */ OP_MODRM, + /* DB */ OP_MODRM, + /* DC */ OP_MODRM, + /* DD */ OP_MODRM, + /* DE */ OP_MODRM, + /* DF */ OP_MODRM, + + /* E0 */ OP_RELATIVE | OP_DATA_I8, + /* E1 */ OP_RELATIVE | OP_DATA_I8, + /* E2 */ OP_RELATIVE | OP_DATA_I8, + /* E3 */ OP_RELATIVE | OP_DATA_I8, + /* E4 */ OP_DATA_I8, + /* E5 */ OP_DATA_I8, + /* E6 */ OP_DATA_I8, + /* E7 */ OP_DATA_I8, + /* E8 */ OP_RELATIVE | OP_DATA_I16_I32, + /* E9 */ OP_RELATIVE | OP_DATA_I16_I32, + /* EA */ OP_DATA_I16 | OP_DATA_I16_I32, + /* EB */ OP_RELATIVE | OP_DATA_I8, + /* EC */ OP_NONE, + /* ED */ OP_NONE, + /* EE */ OP_NONE, + /* EF */ OP_NONE, + + /* F0 */ OP_PREFIX, + /* F1 */ OP_NONE, + /* F2 */ OP_PREFIX, + /* F3 */ OP_PREFIX, + /* F4 */ OP_NONE, + /* F5 */ OP_NONE, + /* F6 */ OP_MODRM, + /* F7 */ OP_MODRM, + /* F8 */ OP_NONE, + /* F9 */ OP_NONE, + /* FA */ OP_NONE, + /* FB */ OP_NONE, + /* FC */ OP_NONE, + /* FD */ OP_NONE, + /* FE */ OP_MODRM, + /* FF */ OP_MODRM +}; + +static unsigned char flags_table_ex[256] = +{ + /* 0F00 */ OP_MODRM, + /* 0F01 */ OP_MODRM, + /* 0F02 */ OP_MODRM, + /* 0F03 */ OP_MODRM, + /* 0F04 */ OP_INVALID, + /* 0F05 */ OP_NONE, + /* 0F06 */ OP_NONE, + /* 0F07 */ OP_NONE, + /* 0F08 */ OP_NONE, + /* 0F09 */ OP_NONE, + /* 0F0A */ OP_INVALID, + /* 0F0B */ OP_NONE, + /* 0F0C */ OP_INVALID, + /* 0F0D */ OP_MODRM, + /* 0F0E */ OP_INVALID, + /* 0F0F */ OP_MODRM | OP_DATA_I8, //3Dnow + + /* 0F10 */ OP_MODRM, + /* 0F11 */ OP_MODRM, + /* 0F12 */ OP_MODRM, + /* 0F13 */ OP_MODRM, + /* 0F14 */ OP_MODRM, + /* 0F15 */ OP_MODRM, + /* 0F16 */ OP_MODRM, + /* 0F17 */ OP_MODRM, + /* 0F18 */ OP_MODRM, + /* 0F19 */ OP_INVALID, + /* 0F1A */ OP_INVALID, + /* 0F1B */ OP_INVALID, + /* 0F1C */ OP_INVALID, + /* 0F1D */ OP_INVALID, + /* 0F1E */ OP_INVALID, + /* 0F1F */ OP_NONE, + + /* 0F20 */ OP_MODRM, + /* 0F21 */ OP_MODRM, + /* 0F22 */ OP_MODRM, + /* 0F23 */ OP_MODRM, + /* 0F24 */ OP_MODRM | OP_EXTENDED, //SSE5 + /* 0F25 */ OP_INVALID, + /* 0F26 */ OP_MODRM, + /* 0F27 */ OP_INVALID, + /* 0F28 */ OP_MODRM, + /* 0F29 */ OP_MODRM, + /* 0F2A */ OP_MODRM, + /* 0F2B */ OP_MODRM, + /* 0F2C */ OP_MODRM, + /* 0F2D */ OP_MODRM, + /* 0F2E */ OP_MODRM, + /* 0F2F */ OP_MODRM, + + /* 0F30 */ OP_NONE, + /* 0F31 */ OP_NONE, + /* 0F32 */ OP_NONE, + /* 0F33 */ OP_NONE, + /* 0F34 */ OP_NONE, + /* 0F35 */ OP_NONE, + /* 0F36 */ OP_INVALID, + /* 0F37 */ OP_NONE, + /* 0F38 */ OP_MODRM | OP_EXTENDED, + /* 0F39 */ OP_INVALID, + /* 0F3A */ OP_MODRM | OP_EXTENDED | OP_DATA_I8, + /* 0F3B */ OP_INVALID, + /* 0F3C */ OP_INVALID, + /* 0F3D */ OP_INVALID, + /* 0F3E */ OP_INVALID, + /* 0F3F */ OP_INVALID, + + /* 0F40 */ OP_MODRM, + /* 0F41 */ OP_MODRM, + /* 0F42 */ OP_MODRM, + /* 0F43 */ OP_MODRM, + /* 0F44 */ OP_MODRM, + /* 0F45 */ OP_MODRM, + /* 0F46 */ OP_MODRM, + /* 0F47 */ OP_MODRM, + /* 0F48 */ OP_MODRM, + /* 0F49 */ OP_MODRM, + /* 0F4A */ OP_MODRM, + /* 0F4B */ OP_MODRM, + /* 0F4C */ OP_MODRM, + /* 0F4D */ OP_MODRM, + /* 0F4E */ OP_MODRM, + /* 0F4F */ OP_MODRM, + + /* 0F50 */ OP_MODRM, + /* 0F51 */ OP_MODRM, + /* 0F52 */ OP_MODRM, + /* 0F53 */ OP_MODRM, + /* 0F54 */ OP_MODRM, + /* 0F55 */ OP_MODRM, + /* 0F56 */ OP_MODRM, + /* 0F57 */ OP_MODRM, + /* 0F58 */ OP_MODRM, + /* 0F59 */ OP_MODRM, + /* 0F5A */ OP_MODRM, + /* 0F5B */ OP_MODRM, + /* 0F5C */ OP_MODRM, + /* 0F5D */ OP_MODRM, + /* 0F5E */ OP_MODRM, + /* 0F5F */ OP_MODRM, + + /* 0F60 */ OP_MODRM, + /* 0F61 */ OP_MODRM, + /* 0F62 */ OP_MODRM, + /* 0F63 */ OP_MODRM, + /* 0F64 */ OP_MODRM, + /* 0F65 */ OP_MODRM, + /* 0F66 */ OP_MODRM, + /* 0F67 */ OP_MODRM, + /* 0F68 */ OP_MODRM, + /* 0F69 */ OP_MODRM, + /* 0F6A */ OP_MODRM, + /* 0F6B */ OP_MODRM, + /* 0F6C */ OP_MODRM, + /* 0F6D */ OP_MODRM, + /* 0F6E */ OP_MODRM, + /* 0F6F */ OP_MODRM, + + /* 0F70 */ OP_MODRM | OP_DATA_I8, + /* 0F71 */ OP_MODRM | OP_DATA_I8, + /* 0F72 */ OP_MODRM | OP_DATA_I8, + /* 0F73 */ OP_MODRM | OP_DATA_I8, + /* 0F74 */ OP_MODRM, + /* 0F75 */ OP_MODRM, + /* 0F76 */ OP_MODRM, + /* 0F77 */ OP_NONE, + /* 0F78 */ OP_MODRM, + /* 0F79 */ OP_MODRM, + /* 0F7A */ OP_INVALID, + /* 0F7B */ OP_INVALID, + /* 0F7C */ OP_MODRM, + /* 0F7D */ OP_MODRM, + /* 0F7E */ OP_MODRM, + /* 0F7F */ OP_MODRM, + + /* 0F80 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F81 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F82 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F83 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F84 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F85 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F86 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F87 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F88 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F89 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8A */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8B */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8C */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8D */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8E */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8F */ OP_RELATIVE | OP_DATA_I16_I32, + + /* 0F90 */ OP_MODRM, + /* 0F91 */ OP_MODRM, + /* 0F92 */ OP_MODRM, + /* 0F93 */ OP_MODRM, + /* 0F94 */ OP_MODRM, + /* 0F95 */ OP_MODRM, + /* 0F96 */ OP_MODRM, + /* 0F97 */ OP_MODRM, + /* 0F98 */ OP_MODRM, + /* 0F99 */ OP_MODRM, + /* 0F9A */ OP_MODRM, + /* 0F9B */ OP_MODRM, + /* 0F9C */ OP_MODRM, + /* 0F9D */ OP_MODRM, + /* 0F9E */ OP_MODRM, + /* 0F9F */ OP_MODRM, + + /* 0FA0 */ OP_NONE, + /* 0FA1 */ OP_NONE, + /* 0FA2 */ OP_NONE, + /* 0FA3 */ OP_MODRM, + /* 0FA4 */ OP_MODRM | OP_DATA_I8, + /* 0FA5 */ OP_MODRM, + /* 0FA6 */ OP_INVALID, + /* 0FA7 */ OP_INVALID, + /* 0FA8 */ OP_NONE, + /* 0FA9 */ OP_NONE, + /* 0FAA */ OP_NONE, + /* 0FAB */ OP_MODRM, + /* 0FAC */ OP_MODRM | OP_DATA_I8, + /* 0FAD */ OP_MODRM, + /* 0FAE */ OP_MODRM, + /* 0FAF */ OP_MODRM, + + /* 0FB0 */ OP_MODRM, + /* 0FB1 */ OP_MODRM, + /* 0FB2 */ OP_MODRM, + /* 0FB3 */ OP_MODRM, + /* 0FB4 */ OP_MODRM, + /* 0FB5 */ OP_MODRM, + /* 0FB6 */ OP_MODRM, + /* 0FB7 */ OP_MODRM, + /* 0FB8 */ OP_MODRM, + /* 0FB9 */ OP_MODRM, + /* 0FBA */ OP_MODRM | OP_DATA_I8, + /* 0FBB */ OP_MODRM, + /* 0FBC */ OP_MODRM, + /* 0FBD */ OP_MODRM, + /* 0FBE */ OP_MODRM, + /* 0FBF */ OP_MODRM, + + /* 0FC0 */ OP_MODRM, + /* 0FC1 */ OP_MODRM, + /* 0FC2 */ OP_MODRM | OP_DATA_I8, + /* 0FC3 */ OP_MODRM, + /* 0FC4 */ OP_MODRM | OP_DATA_I8, + /* 0FC5 */ OP_MODRM | OP_DATA_I8, + /* 0FC6 */ OP_MODRM | OP_DATA_I8, + /* 0FC7 */ OP_MODRM, + /* 0FC8 */ OP_NONE, + /* 0FC9 */ OP_NONE, + /* 0FCA */ OP_NONE, + /* 0FCB */ OP_NONE, + /* 0FCC */ OP_NONE, + /* 0FCD */ OP_NONE, + /* 0FCE */ OP_NONE, + /* 0FCF */ OP_NONE, + + /* 0FD0 */ OP_MODRM, + /* 0FD1 */ OP_MODRM, + /* 0FD2 */ OP_MODRM, + /* 0FD3 */ OP_MODRM, + /* 0FD4 */ OP_MODRM, + /* 0FD5 */ OP_MODRM, + /* 0FD6 */ OP_MODRM, + /* 0FD7 */ OP_MODRM, + /* 0FD8 */ OP_MODRM, + /* 0FD9 */ OP_MODRM, + /* 0FDA */ OP_MODRM, + /* 0FDB */ OP_MODRM, + /* 0FDC */ OP_MODRM, + /* 0FDD */ OP_MODRM, + /* 0FDE */ OP_MODRM, + /* 0FDF */ OP_MODRM, + + /* 0FE0 */ OP_MODRM, + /* 0FE1 */ OP_MODRM, + /* 0FE2 */ OP_MODRM, + /* 0FE3 */ OP_MODRM, + /* 0FE4 */ OP_MODRM, + /* 0FE5 */ OP_MODRM, + /* 0FE6 */ OP_MODRM, + /* 0FE7 */ OP_MODRM, + /* 0FE8 */ OP_MODRM, + /* 0FE9 */ OP_MODRM, + /* 0FEA */ OP_MODRM, + /* 0FEB */ OP_MODRM, + /* 0FEC */ OP_MODRM, + /* 0FED */ OP_MODRM, + /* 0FEE */ OP_MODRM, + /* 0FEF */ OP_MODRM, + + /* 0FF0 */ OP_MODRM, + /* 0FF1 */ OP_MODRM, + /* 0FF2 */ OP_MODRM, + /* 0FF3 */ OP_MODRM, + /* 0FF4 */ OP_MODRM, + /* 0FF5 */ OP_MODRM, + /* 0FF6 */ OP_MODRM, + /* 0FF7 */ OP_MODRM, + /* 0FF8 */ OP_MODRM, + /* 0FF9 */ OP_MODRM, + /* 0FFA */ OP_MODRM, + /* 0FFB */ OP_MODRM, + /* 0FFC */ OP_MODRM, + /* 0FFD */ OP_MODRM, + /* 0FFE */ OP_MODRM, + /* 0FFF */ OP_INVALID, +}; + +unsigned char cflags(UINT8 op) +{ + return flags_table[op]; +} + + +unsigned char cflags_ex(UINT8 op) +{ + return flags_table_ex[op]; +} + +unsigned int __fastcall ldasm(void* code, ldasm_data* ld, UINT32 is64) +/* + Description: + Disassemble one instruction + + Arguments: + code - pointer to the code for disassemble + ld - pointer to structure ldasm_data + is64 - set this flag for 64-bit code, and clear for 32-bit + + Return: + length of instruction + */ +{ + UINT8* p = (UINT8*)code; + UINT8 s, op, f; + UINT8 rexw, pr_66, pr_67; + + s = rexw = pr_66 = pr_67 = 0; + + /* dummy check */ + if (!code || !ld) + return 0; + + /* init output data */ + memset(ld, 0, sizeof(ldasm_data)); + + /* phase 1: parse prefixies */ + while (cflags(*p) & OP_PREFIX) + { + if (*p == 0x66) + pr_66 = 1; + if (*p == 0x67) + pr_67 = 1; + p++; + s++; + ld->flags |= F_PREFIX; + if (s == 15) + { + ld->flags |= F_INVALID; + return s; + } + } + + /* parse REX prefix */ + if (is64 && *p >> 4 == 4) + { + ld->rex = *p; + rexw = (ld->rex >> 3) & 1; + ld->flags |= F_REX; + p++; + s++; + } + + /* can be only one REX prefix */ + if (is64 && *p >> 4 == 4) + { + ld->flags |= F_INVALID; + s++; + return s; + } + + /* phase 2: parse opcode */ + ld->opcd_offset = (UINT8)(p - (UINT8*)code); + ld->opcd_size = 1; + op = *p++; + s++; + + /* is 2 byte opcode? */ + if (op == 0x0F) + { + op = *p++; + s++; + ld->opcd_size++; + f = cflags_ex(op); + if (f & OP_INVALID) + { + ld->flags |= F_INVALID; + return s; + } + /* for SSE instructions */ + if (f & OP_EXTENDED) + { + op = *p++; + s++; + ld->opcd_size++; + } + } + else + { + f = cflags(op); + /* pr_66 = pr_67 for opcodes A0-A3 */ + if (op >= 0xA0 && op <= 0xA3) + pr_66 = pr_67; + } + + /* phase 3: parse ModR/M, SIB and DISP */ + if (f & OP_MODRM) + { + UINT8 mod = (*p >> 6); + UINT8 ro = (*p & 0x38) >> 3; + UINT8 rm = (*p & 7); + + ld->modrm = *p++; + s++; + ld->flags |= F_MODRM; + + /* in F6,F7 opcodes immediate data present if R/O == 0 */ + if (op == 0xF6 && (ro == 0 || ro == 1)) + f |= OP_DATA_I8; + if (op == 0xF7 && (ro == 0 || ro == 1)) + f |= OP_DATA_I16_I32_I64; + + /* is SIB byte exist? */ + if (mod != 3 && rm == 4 && !(!is64 && pr_67)) + { + ld->sib = *p++; + s++; + ld->flags |= F_SIB; + + /* if base == 5 and mod == 0 */ + if ((ld->sib & 7) == 5 && mod == 0) + { + ld->disp_size = 4; + } + } + + switch (mod) + { + case 0: + if (is64) + { + if (rm == 5) + { + ld->disp_size = 4; + if (is64) + ld->flags |= F_RELATIVE; + } + } + else if (pr_67) + { + if (rm == 6) + ld->disp_size = 2; + } + else + { + if (rm == 5) + ld->disp_size = 4; + } + break; + case 1: + ld->disp_size = 1; + break; + case 2: + if (is64) + ld->disp_size = 4; + else if (pr_67) + ld->disp_size = 2; + else + ld->disp_size = 4; + break; + } + + if (ld->disp_size) + { + ld->disp_offset = (UINT8)(p - (UINT8*)code); + p += ld->disp_size; + s += ld->disp_size; + ld->flags |= F_DISP; + } + } + + /* phase 4: parse immediate data */ + if (rexw && f & OP_DATA_I16_I32_I64) + ld->imm_size = 8; + else if (f & OP_DATA_I16_I32 || f & OP_DATA_I16_I32_I64) + ld->imm_size = 4 - (pr_66 << 1); + + /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */ + ld->imm_size += f & 3; + + if (ld->imm_size) + { + s += ld->imm_size; + ld->imm_offset = (UINT8)(p - (UINT8*)code); + ld->flags |= F_IMM; + if (f & OP_RELATIVE) + ld->flags |= F_RELATIVE; + } + + /* instruction is too long */ + if (s > 15) + ld->flags |= F_INVALID; + + return s; +} + +// Get function size +unsigned long __fastcall SizeOfProc(void* Proc) +{ + UINT32 Length; + UINT8* pOpcode; + UINT32 Result = 0; + ldasm_data data = {0}; + + do + { + Length = ldasm((UINT8*)Proc, &data, is_x64); + + pOpcode = (UINT8*)Proc + data.opcd_offset; + Result += Length; + + if ((Length == 1) && (*pOpcode == 0xCC)) + break; + + /*if ((Length == 1) && (*pOpcode == 0xC3)) + break; + + if ((Length == 3) && (*pOpcode == 0xC2)) + break;*/ + + Proc = (void*)((size_t)Proc + Length); + } + while (Length); + + return Result; +} + +// If function address is jmp - get jmp destination +void* __fastcall ResolveJmp(void* Proc) +{ + UINT32 Length; + UINT8* pOpcode; + ldasm_data data = {0}; + + Length = ldasm((UINT8*)Proc, &data, is_x64); + pOpcode = (UINT8*)Proc + data.opcd_offset; + + // Recursive unwind + if (Length == 5 && data.opcd_size == 1 && *pOpcode == 0xE9) + { + UINT32 delta = *(INT32*)((uintptr_t)Proc + data.opcd_size); + return ResolveJmp((void*)((uintptr_t)Proc + delta + Length)); + } + + return Proc; +} diff --git a/BranchTracerSys/kernel-hooks/LDasm.h b/BranchTracerSys/kernel-hooks/LDasm.h new file mode 100644 index 0000000..b747d9e --- /dev/null +++ b/BranchTracerSys/kernel-hooks/LDasm.h @@ -0,0 +1,48 @@ +#ifndef _LDASM_ +#define _LDASM_ + +#include + +#ifdef _WIN64 +#define is_x64 1 +#else +#define is_x64 0 +#endif//USE64 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define F_INVALID 0x01 +#define F_PREFIX 0x02 +#define F_REX 0x04 +#define F_MODRM 0x08 +#define F_SIB 0x10 +#define F_DISP 0x20 +#define F_IMM 0x40 +#define F_RELATIVE 0x80 + +typedef struct _ldasm_data +{ + UINT8 flags; + UINT8 rex; + UINT8 modrm; + UINT8 sib; + UINT8 opcd_offset; + UINT8 opcd_size; + UINT8 disp_offset; + UINT8 disp_size; + UINT8 imm_offset; + UINT8 imm_size; +} ldasm_data; + +unsigned int __fastcall ldasm(void* code, ldasm_data* ld, UINT32 is64); +unsigned long __fastcall SizeOfProc(void* Proc); +void* __fastcall ResolveJmp(void* Proc); + +#ifdef __cplusplus +} +#endif + +#endif//_LDASM_ diff --git a/BranchTracerSys/kernel-tools/KernelBase.c b/BranchTracerSys/kernel-tools/KernelBase.c new file mode 100644 index 0000000..4f69f3d --- /dev/null +++ b/BranchTracerSys/kernel-tools/KernelBase.c @@ -0,0 +1,57 @@ +#include "KernelBase.h" + +#include "nt_imports.h" + +PVOID g_KernelBase = NULL; +ULONG g_KernelSize = 0; + +PVOID GetKernelBase(OUT PULONG ImageSize) { + NTSTATUS Status; + if (g_KernelBase != NULL) { + if (ImageSize) { + *ImageSize = g_KernelSize; + } + return g_KernelBase; + } + + UNICODE_STRING RoutineName = RTL_CONSTANT_STRING(L"NtCreateFile"); + PVOID AnchorPointer = MmGetSystemRoutineAddress(&RoutineName); + if (AnchorPointer == NULL) { + return NULL; + } + + ULONG InfoSize = 0; + ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &InfoSize); + if (InfoSize == 0) { + return NULL; + } + PRTL_PROCESS_MODULES ModuleInfo = + (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(PagedPool, InfoSize, 'sabK'); + RtlZeroMemory(ModuleInfo, InfoSize); + + Status = ZwQuerySystemInformation(SystemModuleInformation, ModuleInfo, InfoSize, &InfoSize); + if (NT_SUCCESS(Status)) { + PRTL_PROCESS_MODULE_INFORMATION Module = ModuleInfo->Modules; + + for (size_t i = 0; i < ModuleInfo->NumberOfModules; i++) { + ULONG ModuleImageSize = Module[i].ImageSize; + PVOID ModuleImageBase = Module[i].ImageBase; + + if (AnchorPointer >= ModuleImageBase && (ULONG_PTR)AnchorPointer <= ((ULONG_PTR)ModuleImageBase + ModuleImageSize)) { + g_KernelBase = ModuleImageBase; + g_KernelSize = ModuleImageSize; + + if (ImageSize) { + *ImageSize = ModuleImageSize; + } + break; + } + } + } + + if (ModuleInfo) { + ExFreePool(ModuleInfo); + } + + return g_KernelBase; +} diff --git a/BranchTracerSys/kernel-tools/KernelBase.h b/BranchTracerSys/kernel-tools/KernelBase.h new file mode 100644 index 0000000..cf67307 --- /dev/null +++ b/BranchTracerSys/kernel-tools/KernelBase.h @@ -0,0 +1,8 @@ +#pragma once +#include "nt_include.h" + +EXTERN_C_START + +PVOID GetKernelBase(OUT PULONG ImageSize); + +EXTERN_C_END diff --git a/BranchTracerSys/kernel-tools/apc_ex.c b/BranchTracerSys/kernel-tools/apc_ex.c new file mode 100644 index 0000000..bb9e122 --- /dev/null +++ b/BranchTracerSys/kernel-tools/apc_ex.c @@ -0,0 +1,161 @@ +#include "apc_ex.h" +#include "nt_imports.h" +#include "my_ntstatus.h" + +#include + + +typedef struct _APCEX_COPYMEM_INFO +{ + PVOID Destination; + PVOID Source; + SIZE_T Length; + NTSTATUS Status; +} APCEX_COPYMEM_INFO, * PAPCEX_COPYMEM_INFO; + +VOID CopyProcessMemoryApc(PKAPC Apc, PVOID* NormalRoutine, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArgument2) +{ + UNREFERENCED_PARAMETER(NormalRoutine); + UNREFERENCED_PARAMETER(Apc); + UNREFERENCED_PARAMETER(NormalContext); + PAPCEX_COPYMEM_INFO Info = (PAPCEX_COPYMEM_INFO)*SystemArgument1; + PKEVENT Event = (PKEVENT)*SystemArgument2; + + //DbgPrint("Destination %p\n", Info->Destination); + //DbgPrint("Source %p\n", Info->Source); + //DbgPrint("Length %p\n", Info->Length); + + //PEPROCESS process = PsGetCurrentProcess(); + //PCHAR processName = PsGetProcessImageFileName(process); + //DbgPrint("process: %s\n", processName); + + _disable(); + __writecr0(__readcr0() & ~0x10000); + + RtlCopyMemory(Info->Destination, Info->Source, Info->Length); + + __writecr0(__readcr0() | 0x10000); + _enable(); + + Info->Status = STATUS_SUCCESS; + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + + +PETHREAD FindAnThread(PEPROCESS Process) +{ + // 遍历全局句柄表. 寻找一个目标进程的ETHREAD + PETHREAD Thread = NULL; + for (ULONG_PTR i = 8; i < 0x40000; i += 4) { + PETHREAD t; + + if (NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)i, &t))) { + if (PsGetThreadProcess(t) == Process) { + Thread = t; + break; + } + ObDereferenceObject(t); + } + } + return Thread; +} + +NTSTATUS ApcCopyProcessMemory(PEPROCESS Process, PVOID Destination, PVOID Source, SIZE_T BufferSize) +{ + NTSTATUS Status = STATUS_SUCCESS; + + PETHREAD Thread = FindAnThread(Process); + if (Thread == NULL) { + return STATUS_THREAD_NOT_FOUND; + } + + PKAPC Apc = (PKAPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), 'CPA.'); + PAPCEX_COPYMEM_INFO Info = (PAPCEX_COPYMEM_INFO)ExAllocatePoolWithTag(NonPagedPool, sizeof(APCEX_COPYMEM_INFO), 'CPA.'); + PKEVENT Event = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), 'CPA.'); + if (!Apc || !Event || !Info) { + Status = STATUS_MEMORY_ALLOCATE_UNSUCCESS; + goto Clear; + } + + Info->Destination = Destination; + Info->Source = Source; + Info->Length = BufferSize; + + KeInitializeEvent(Event, NotificationEvent, TRUE); + KeClearEvent(Event); + + KeInitializeApc(Apc, Thread, OriginalApcEnvironment, (PVOID)CopyProcessMemoryApc, NULL, NULL, KernelMode, NULL); + + if (!KeInsertQueueApc(Apc, Info, Event, IO_NO_INCREMENT)) { + Status = STATUS_APC_INSERT_FAILED; + goto Clear; + } + + KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); + Status = Info->Status; + +Clear: + if (Apc) { + ExFreePool(Apc); + } + if (Event) { + ExFreePool(Event); + } + if (Info) { + ExFreePool(Info); + } + + ObDereferenceObject(Thread); + return Status; +} + +void NTAPI KernelRoutine(PKAPC apc, PVOID* NormalRoutine, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArgument2) +{ + //ExFreePool(apc); + DbgPrint("KernelRoutine called!\n"); + DbgPrint("NormalRoutine %p! Value: %p\n", NormalRoutine, *(PULONG_PTR)NormalRoutine); + DbgPrint("NormalContext %p! Value: %p\n", NormalContext, *(PULONG_PTR)NormalContext); + DbgPrint("SystemArgument1 %p Value: %p!\n", SystemArgument1, *(PULONG_PTR)SystemArgument1); + DbgPrint("SystemArgument2 %p Value: %p!\n", SystemArgument2, *(PULONG_PTR)SystemArgument2); + + //KeTestAlertThread(UserMode); + ExFreePool(apc); +} + +VOID RundownRoutine(IN struct _KAPC* Apc) +{ + UNREFERENCED_PARAMETER(Apc); + DbgPrint("RundownRoutine called!"); +} + +NTSTATUS ApcInsertNormalApc(PEPROCESS Process, PVOID NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + NTSTATUS Status = STATUS_SUCCESS; + PETHREAD Thread = FindAnThread(Process); + if (Thread == NULL) { + return STATUS_THREAD_NOT_FOUND; + } + PKAPC Apc = (PKAPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), 'CPA.'); + if (!Apc) { + Status = STATUS_MEMORY_ALLOCATE_UNSUCCESS; + return Status; + } + + //在64位系统中插入32位用户apc时apc函数地址需要求补后左移两位 + //NormalRoutine = (~(ULONG_PTR)NormalRoutine + 1) << 2; + NormalRoutine = (PVOID)(((~(ULONG_PTR)NormalRoutine) + 1) << 2); + + + KeInitializeApc(Apc, Thread, OriginalApcEnvironment, (PVOID)KernelRoutine, NULL, NormalRoutine, UserMode, NormalContext); + + //0x07a + PKAPC_STATE ApcState = (PKAPC_STATE)((PUCHAR)Thread + 0x50); + ApcState->UserApcPending = TRUE; + + if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) + { + return STATUS_APC_INSERT_FAILED + } + + return STATUS_SUCCESS; +} diff --git a/BranchTracerSys/kernel-tools/apc_ex.h b/BranchTracerSys/kernel-tools/apc_ex.h new file mode 100644 index 0000000..b6fe878 --- /dev/null +++ b/BranchTracerSys/kernel-tools/apc_ex.h @@ -0,0 +1,21 @@ +#pragma once +#include "nt_include.h" + +EXTERN_C_START + +/* + Description: 使用APC的方式Copy目标进程内存 + ReturnValue: NTSTATUS + Parameters: + Process: 目标进程EPROCESS指针 + Destination: 目标指针 + Source: 源指针 + Length: Size +*/ +NTSTATUS ApcCopyProcessMemory(PEPROCESS Process, PVOID Destination, PVOID Source, SIZE_T BufferSize); + +/* 插入一个NormalApc*/ +NTSTATUS ApcInsertNormalApc(PEPROCESS Process, PVOID NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); + + +EXTERN_C_END diff --git a/BranchTracerSys/kernel-tools/my_ntstatus.h b/BranchTracerSys/kernel-tools/my_ntstatus.h new file mode 100644 index 0000000..6baecd5 --- /dev/null +++ b/BranchTracerSys/kernel-tools/my_ntstatus.h @@ -0,0 +1,19 @@ +#pragma once +#include "nt_include.h" + +#define FACILITY_MY 0xFFF + + +/*0x00 execption*/ +#define STATUS_EXECPTION_PROBEREAD (NTSTATUS)0xEFFF0001; +#define STATUS_EXECPTION_PROBEWRITE (NTSTATUS)0xEFFF0002; +#define STATUS_EXECPTION_PROBEREADWRITE (NTSTATUS)0xEFFF0003; + +/*0x01 memory*/ +#define STATUS_MEMORY_ALLOCATE_UNSUCCESS (NTSTATUS)0xEFFF0101; + +/*0x02 thread*/ +#define STATUS_THREAD_NOT_FOUND (NTSTATUS)0xEFFF0201; + +/*0x03 apc*/ +#define STATUS_APC_INSERT_FAILED (NTSTATUS)0xEFFF0301; diff --git a/BranchTracerSys/kernel-tools/nt_enums.h b/BranchTracerSys/kernel-tools/nt_enums.h new file mode 100644 index 0000000..435a711 --- /dev/null +++ b/BranchTracerSys/kernel-tools/nt_enums.h @@ -0,0 +1,170 @@ +#pragma once + + +typedef enum _KAPC_ENVIRONMENT { + OriginalApcEnvironment, + AttachedApcEnvironment, + CurrentApcEnvironment, + InsertApcEnvironment +} KAPC_ENVIRONMENT; + +typedef enum _SYSTEM_INFORMATION_CLASS { + SystemBasicInformation = 0x0, + SystemProcessorInformation = 0x1, + SystemPerformanceInformation = 0x2, + SystemTimeOfDayInformation = 0x3, + SystemPathInformation = 0x4, + SystemProcessInformation = 0x5, + SystemCallCountInformation = 0x6, + SystemDeviceInformation = 0x7, + SystemProcessorPerformanceInformation = 0x8, + SystemFlagsInformation = 0x9, + SystemCallTimeInformation = 0xa, + SystemModuleInformation = 0xb, + SystemLocksInformation = 0xc, + SystemStackTraceInformation = 0xd, + SystemPagedPoolInformation = 0xe, + SystemNonPagedPoolInformation = 0xf, + SystemHandleInformation = 0x10, + SystemObjectInformation = 0x11, + SystemPageFileInformation = 0x12, + SystemVdmInstemulInformation = 0x13, + SystemVdmBopInformation = 0x14, + SystemFileCacheInformation = 0x15, + SystemPoolTagInformation = 0x16, + SystemInterruptInformation = 0x17, + SystemDpcBehaviorInformation = 0x18, + SystemFullMemoryInformation = 0x19, + SystemLoadGdiDriverInformation = 0x1a, + SystemUnloadGdiDriverInformation = 0x1b, + SystemTimeAdjustmentInformation = 0x1c, + SystemSummaryMemoryInformation = 0x1d, + SystemMirrorMemoryInformation = 0x1e, + SystemPerformanceTraceInformation = 0x1f, + SystemObsolete0 = 0x20, + SystemExceptionInformation = 0x21, + SystemCrashDumpStateInformation = 0x22, + SystemKernelDebuggerInformation = 0x23, + SystemContextSwitchInformation = 0x24, + SystemRegistryQuotaInformation = 0x25, + SystemExtendServiceTableInformation = 0x26, + SystemPrioritySeperation = 0x27, + SystemVerifierAddDriverInformation = 0x28, + SystemVerifierRemoveDriverInformation = 0x29, + SystemProcessorIdleInformation = 0x2a, + SystemLegacyDriverInformation = 0x2b, + SystemCurrentTimeZoneInformation = 0x2c, + SystemLookasideInformation = 0x2d, + SystemTimeSlipNotification = 0x2e, + SystemSessionCreate = 0x2f, + SystemSessionDetach = 0x30, + SystemSessionInformation = 0x31, + SystemRangeStartInformation = 0x32, + SystemVerifierInformation = 0x33, + SystemVerifierThunkExtend = 0x34, + SystemSessionProcessInformation = 0x35, + SystemLoadGdiDriverInSystemSpace = 0x36, + SystemNumaProcessorMap = 0x37, + SystemPrefetcherInformation = 0x38, + SystemExtendedProcessInformation = 0x39, + SystemRecommendedSharedDataAlignment = 0x3a, + SystemComPlusPackage = 0x3b, + SystemNumaAvailableMemory = 0x3c, + SystemProcessorPowerInformation = 0x3d, + SystemEmulationBasicInformation = 0x3e, + SystemEmulationProcessorInformation = 0x3f, + SystemExtendedHandleInformation = 0x40, + SystemLostDelayedWriteInformation = 0x41, + SystemBigPoolInformation = 0x42, + SystemSessionPoolTagInformation = 0x43, + SystemSessionMappedViewInformation = 0x44, + SystemHotpatchInformation = 0x45, + SystemObjectSecurityMode = 0x46, + SystemWatchdogTimerHandler = 0x47, + SystemWatchdogTimerInformation = 0x48, + SystemLogicalProcessorInformation = 0x49, + SystemWow64SharedInformationObsolete = 0x4a, + SystemRegisterFirmwareTableInformationHandler = 0x4b, + SystemFirmwareTableInformation = 0x4c, + SystemModuleInformationEx = 0x4d, + SystemVerifierTriageInformation = 0x4e, + SystemSuperfetchInformation = 0x4f, + SystemMemoryListInformation = 0x50, + SystemFileCacheInformationEx = 0x51, + SystemThreadPriorityClientIdInformation = 0x52, + SystemProcessorIdleCycleTimeInformation = 0x53, + SystemVerifierCancellationInformation = 0x54, + SystemProcessorPowerInformationEx = 0x55, + SystemRefTraceInformation = 0x56, + SystemSpecialPoolInformation = 0x57, + SystemProcessIdInformation = 0x58, + SystemErrorPortInformation = 0x59, + SystemBootEnvironmentInformation = 0x5a, + SystemHypervisorInformation = 0x5b, + SystemVerifierInformationEx = 0x5c, + SystemTimeZoneInformation = 0x5d, + SystemImageFileExecutionOptionsInformation = 0x5e, + SystemCoverageInformation = 0x5f, + SystemPrefetchPatchInformation = 0x60, + SystemVerifierFaultsInformation = 0x61, + SystemSystemPartitionInformation = 0x62, + SystemSystemDiskInformation = 0x63, + SystemProcessorPerformanceDistribution = 0x64, + SystemNumaProximityNodeInformation = 0x65, + SystemDynamicTimeZoneInformation = 0x66, + SystemCodeIntegrityInformation = 0x67, + SystemProcessorMicrocodeUpdateInformation = 0x68, + SystemProcessorBrandString = 0x69, + SystemVirtualAddressInformation = 0x6a, + SystemLogicalProcessorAndGroupInformation = 0x6b, + SystemProcessorCycleTimeInformation = 0x6c, + SystemStoreInformation = 0x6d, + SystemRegistryAppendString = 0x6e, + SystemAitSamplingValue = 0x6f, + SystemVhdBootInformation = 0x70, + SystemCpuQuotaInformation = 0x71, + SystemNativeBasicInformation = 0x72, + SystemErrorPortTimeouts = 0x73, + SystemLowPriorityIoInformation = 0x74, + SystemBootEntropyInformation = 0x75, + SystemVerifierCountersInformation = 0x76, + SystemPagedPoolInformationEx = 0x77, + SystemSystemPtesInformationEx = 0x78, + SystemNodeDistanceInformation = 0x79, + SystemAcpiAuditInformation = 0x7a, + SystemBasicPerformanceInformation = 0x7b, + SystemQueryPerformanceCounterInformation = 0x7c, + SystemSessionBigPoolInformation = 0x7d, + SystemBootGraphicsInformation = 0x7e, + SystemScrubPhysicalMemoryInformation = 0x7f, + SystemBadPageInformation = 0x80, + SystemProcessorProfileControlArea = 0x81, + SystemCombinePhysicalMemoryInformation = 0x82, + SystemEntropyInterruptTimingInformation = 0x83, + SystemConsoleInformation = 0x84, + SystemPlatformBinaryInformation = 0x85, + SystemThrottleNotificationInformation = 0x86, + SystemHypervisorProcessorCountInformation = 0x87, + SystemDeviceDataInformation = 0x88, + SystemDeviceDataEnumerationInformation = 0x89, + SystemMemoryTopologyInformation = 0x8a, + SystemMemoryChannelInformation = 0x8b, + SystemBootLogoInformation = 0x8c, + SystemProcessorPerformanceInformationEx = 0x8d, + SystemSpare0 = 0x8e, + SystemSecureBootPolicyInformation = 0x8f, + SystemPageFileInformationEx = 0x90, + SystemSecureBootInformation = 0x91, + SystemEntropyInterruptTimingRawInformation = 0x92, + SystemPortableWorkspaceEfiLauncherInformation = 0x93, + SystemFullProcessInformation = 0x94, + SystemKernelDebuggerInformationEx = 0x95, + SystemBootMetadataInformation = 0x96, + SystemSoftRebootInformation = 0x97, + SystemElamCertificateInformation = 0x98, + SystemOfflineDumpConfigInformation = 0x99, + SystemProcessorFeaturesInformation = 0x9a, + SystemRegistryReconciliationInformation = 0x9b, + MaxSystemInfoClass = 0x9c, +} SYSTEM_INFORMATION_CLASS; + diff --git a/BranchTracerSys/kernel-tools/nt_imports.h b/BranchTracerSys/kernel-tools/nt_imports.h new file mode 100644 index 0000000..b963af1 --- /dev/null +++ b/BranchTracerSys/kernel-tools/nt_imports.h @@ -0,0 +1,21 @@ +#pragma once +#include "nt_include.h" +#include "nt_enums.h" +#include "nt_structs.h" + +EXTERN_C_START + +NTKERNELAPI VOID KeInitializeApc(__out PRKAPC Apc, __in PETHREAD Thread, __in KAPC_ENVIRONMENT Environment, __in PVOID KernelRoutine, + __in_opt PVOID RundownRoutine, __in_opt PVOID NormalRoutine, __in_opt KPROCESSOR_MODE ProcessorMode, __in_opt PVOID NormalContext); +NTSYSAPI BOOLEAN KeInsertQueueApc(__inout PRKAPC Apc, __in_opt PVOID SystemArgument1, __in_opt PVOID SystemArgument2, __in KPRIORITY Increment); +NTSYSAPI BOOLEAN KeTestAlertThread(__in KPROCESSOR_MODE AlertMode); + +NTSYSAPI PPEB PsGetProcessPeb(IN PEPROCESS Process); +NTSYSAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process); + +NTSYSAPI NTSTATUS IoCreateDriver(IN PUNICODE_STRING DriverName, OPTIONAL IN PDRIVER_INITIALIZE InitializationFunction); +NTSYSAPI NTSTATUS NTAPI MmCopyVirtualMemory(PEPROCESS SourceProcess, PVOID SourceAddress, PEPROCESS TargetProcess, PVOID TargetAddress, SIZE_T BufferSize, KPROCESSOR_MODE PreviousMode, PSIZE_T ReturnSize); +NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(__in HANDLE ProcessHandle, __inout PVOID* BaseAddress, __inout PSIZE_T RegionSize, __in ULONG NewProtect, __out PULONG OldProtect); +NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL); + +EXTERN_C_END diff --git a/BranchTracerSys/kernel-tools/nt_include.h b/BranchTracerSys/kernel-tools/nt_include.h new file mode 100644 index 0000000..af008c1 --- /dev/null +++ b/BranchTracerSys/kernel-tools/nt_include.h @@ -0,0 +1,5 @@ +#pragma once + +#include +#include + diff --git a/BranchTracerSys/kernel-tools/nt_structs.h b/BranchTracerSys/kernel-tools/nt_structs.h new file mode 100644 index 0000000..47650a8 --- /dev/null +++ b/BranchTracerSys/kernel-tools/nt_structs.h @@ -0,0 +1,20 @@ +#pragma once +#include "nt_include.h" + +typedef struct _RTL_PROCESS_MODULE_INFORMATION { + HANDLE Section; // Not filled in + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[MAXIMUM_FILENAME_LENGTH]; +} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES { + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;