6
0
mirror of https://github.com/JKornev/hidden synced 2024-06-28 18:02:15 +00:00
hidden/Hidden/KernelAnalyzer.c

218 lines
6.2 KiB
C

#include "KernelAnalyzer.h"
#include "Helper.h"
#include <Zydis/Zydis.h>
typedef struct _KernelInternals {
ULONG ActiveProcessLinksOffset;
PVOID PspActiveProcessLock;
PVOID PspCidTable;
} KernelInternals, *PKernelInternals;
static KernelInternals s_NTinternals;
static ZydisDecoder s_disasmDecoder;
static ZydisFormatter s_disasmFormatter;
// =========================================================================================
PVOID GetPspCidTablePointer()
{
return s_NTinternals.PspCidTable;
}
// =========================================================================================
BOOLEAN Disassemble(PVOID fn, SIZE_T size, BOOLEAN(*InstructionCallback)(ZyanU64,ZydisDecodedInstruction*,PVOID), PVOID params)
{
LogInfo("Routine %p", fn);
__try
{
ZydisDecodedInstruction instruction;
SIZE_T offset = 0;
UINT_PTR target = (UINT_PTR)fn;
CHAR printBuffer[128];
do
{
ZyanStatus status = ZydisDecoderDecodeBuffer(&s_disasmDecoder, (PVOID)(target + offset), size - offset, &instruction);
if (!ZYAN_SUCCESS(status))
break;
const ZyanU64 address = (ZyanU64)(target + offset);
ZydisFormatterFormatInstruction(&s_disasmFormatter, &instruction, printBuffer, sizeof(printBuffer), address);
LogInfo("\t+%-4X 0x%-16llX\t\t%hs", (ULONG)offset, address, printBuffer);
if (!InstructionCallback(address, &instruction, params))
break;
offset += instruction.length;
}
while (offset <= size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
LogWarning("Exception while disassemblying %p", fn);
return FALSE;
}
return TRUE;
}
// =========================================================================================
//
// Case #1 Win7
// Solution: Disassemble a code before we meet 'MOV REG, PspCidTable'
//
// PAGE : 0065B960 _PsLookupProcessByProcessId@8 proc near
// PAGE : 0065B960 mov edi, edi
// PAGE : 0065B962 push ebp
// PAGE : 0065B963 mov ebp, esp
// PAGE : 0065B965 sub esp, 0Ch
// PAGE : 0065B968 push ebx
// PAGE : 0065B969 push esi
// PAGE : 0065B96A mov esi, large fs : 124h
// PAGE : 0065B971 xor ebx, ebx
// PAGE : 0065B973 dec word ptr[esi + 84h]
// PAGE : 0065B97A push edi
// PAGE : 0065B97B push [ebp + arg_0]
// PAGE : 0065B97E mov edi, _PspCidTable <----- Looking for this
//
// Case #2 Win10
// Solution: Disassemble before we meet first a call to not-exported PspReferenceCidTableEntry
// enter it and disassemble before 'MOV REG, PspCidTable'
//
// PAGE : 006C98E0 _PsLookupProcessByProcessId@8 proc near
// PAGE : 006C98E0 mov edi, edi
// PAGE : 006C98E2 push ebp
// PAGE : 006C98E3 mov ebp, esp
// PAGE : 006C98E5 push ecx
// PAGE : 006C98E6 push ebx
// PAGE : 006C98E7 push esi
// PAGE : 006C98E8 push edi .----> PAGE : 006C99B0 _PspReferenceCidTableEntry@8 proc near
// PAGE : 006C98E9 mov edi, large fs : 124h | PAGE : 006C99B0 mov edi, edi
// PAGE : 006C98F0 dec word ptr[edi + 13Eh] | PAGE : 006C99B2 push ebp
// PAGE : 006C98F7 mov ecx, [ebp + arg_0] | PAGE : 006C99B3 mov ebp, esp
// PAGE : 006C98FA mov dl, 3 | PAGE : 006C99B5 mov eax, ds : _PspCidTable <----- Looking for this
// PAGE : 006C98FC call _PspReferenceCidTableEntry@8 ----' PAGE : 006C99BA sub esp, 0Ch
//
BOOLEAN LookForPspCidTableCallback(ZyanU64 address, ZydisDecodedInstruction* instruction, PVOID params)
{
BOOLEAN EnterCalls = *(BOOLEAN*)params;
if (instruction->mnemonic == ZYDIS_MNEMONIC_RET)
return FALSE; // Stop scan if the function is ended
if (instruction->mnemonic == ZYDIS_MNEMONIC_MOV)
{
ZyanU64 pointer = 0;
ZyanStatus status = ZydisCalcAbsoluteAddress(instruction, instruction->operands + 1, address, &pointer);
if (!ZYAN_SUCCESS(status))
return TRUE;
//TODO: validate PspCidTable
if (instruction->operands[1].type != ZYDIS_OPERAND_TYPE_MEMORY)
return TRUE;
#if _M_AMD64
if (instruction->operands[1].mem.segment == ZYDIS_REGISTER_GS)
#else
if (instruction->operands[1].mem.segment == ZYDIS_REGISTER_FS)
#endif
return TRUE;
s_NTinternals.PspCidTable = *(PVOID*)(ULONG_PTR)pointer;
LogInfo("PspCidTable address: %p", pointer);
// Stop scanning if we found a PspCidTable
return FALSE;
}
if (EnterCalls && instruction->mnemonic == ZYDIS_MNEMONIC_CALL)
{
ZyanU64 callAddress = 0;
if (!instruction->operand_count)
return FALSE; // This should never happens
ZyanStatus status = ZydisCalcAbsoluteAddress(instruction, instruction->operands, address, &callAddress);
if (!ZYAN_SUCCESS(status))
return TRUE;
EnterCalls = FALSE;
Disassemble((PVOID)(ULONG_PTR)callAddress, 0x20, &LookForPspCidTableCallback, &EnterCalls);
// Stop scan after a first entering a call instruction
return FALSE;
}
// Scan next command
return TRUE;
}
VOID LookForPspCidTable()
{
BOOLEAN EnterCalls = TRUE;
s_NTinternals.PspCidTable = 0;
Disassemble((PVOID)PsLookupProcessByProcessId, 0x40, LookForPspCidTableCallback, &EnterCalls);
if (!s_NTinternals.PspCidTable)
{
LogWarning("Failed to find PspCidTable");
return;
}
}
VOID LookActiveProcessLock()
{
//Disassemble()
}
// =========================================================================================
BOOLEAN InitializeDisasm()
{
if (ZydisGetVersion() != ZYDIS_VERSION)
{
LogWarning("Error, invalid disasm version");
return FALSE;
}
#ifdef _M_AMD64
if (!ZYAN_SUCCESS(ZydisDecoderInit(&s_disasmDecoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64)))
#else
if (!ZYAN_SUCCESS(ZydisDecoderInit(&s_disasmDecoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32)))
#endif
{
LogWarning("Error, failed to initialize disasm decoder");
return FALSE;
}
//TODO: mb we need remove it
if (!ZYAN_SUCCESS(ZydisFormatterInit(&s_disasmFormatter, ZYDIS_FORMATTER_STYLE_INTEL)))
return FALSE;
return TRUE;
}
VOID InitializeKernelAnalyzer()
{
RtlZeroMemory(&s_NTinternals, sizeof(s_NTinternals));
if (!InitializeDisasm())
return;
LookForPspCidTable();
LookActiveProcessLock();
}
VOID DestroyKernelAnalyzer()
{
//TODO: do we need this routine?
}