mirror of
https://github.com/JKornev/hidden
synced 2024-06-28 18:02:15 +00:00
218 lines
6.2 KiB
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?
|
|
}
|