29 LOG(
"Registers state:\n");
31 LOG(
"RAX = 0x%016llx, RCX = 0x%016llx, RDX = 0x%016llx, RBX = 0x%016llx\n",
32 Registers->Rax, Registers->Rcx, Registers->Rdx, Registers->Rbx);
33 LOG(
"RSP = 0x%016llx, RBP = 0x%016llx, RSI = 0x%016llx, RDI = 0x%016llx\n",
34 Registers->Rsp, Registers->Rbp, Registers->Rsi, Registers->Rdi);
35 LOG(
"R8 = 0x%016llx, R9 = 0x%016llx, R10 = 0x%016llx, R11 = 0x%016llx\n",
36 Registers->R8, Registers->R9, Registers->R10, Registers->R11);
37 LOG(
"R12 = 0x%016llx, R13 = 0x%016llx, R14 = 0x%016llx, R15 = 0x%016llx\n",
38 Registers->R12, Registers->R13, Registers->R14, Registers->R15);
39 LOG(
"RIP = 0x%016llx, RFLAGS = 0x%016llx\n",
40 Registers->Rip, Registers->Flags);
41 LOG(
"CR0 = 0x%016llx, CR2 = 0x%016llx, CR3 = 0x%016llx, CR4 = 0x%016llx\n",
42 Registers->Cr0, Registers->Cr2, Registers->Cr3, Registers->Cr4);
81 const unsigned char *buf = Buffer;
88 if (0 == ElementLength)
93 if (1 != ElementLength && 2 != ElementLength && 4 != ElementLength && 8 != ElementLength)
95 WARNING(
"[WARNING] Only 1, 2, 4 or 8 element length are supported!\n");
101 WARNING(
"[ERROR] Maximum 16 elements per row are supported!\n");
105 #define IS_ASCII(x) ((x) >= 0x20 && (x) < 0x7f) 109 LOG(
"[DUMPER] Dumping buffer from GVA %016llx with size %d\n", Gva, Length);
112 for (
size_t i = 0; i < Length; i += (size_t)RowLength * ElementLength)
115 int ret, rem =
sizeof(line);
116 char rest[
sizeof(
QWORD)];
118 ret = snprintf(l,
sizeof(line),
"%016llx:", Gva + i);
122 for (
size_t j = 0; j < (size_t)RowLength * ElementLength; j += ElementLength)
124 BOOLEAN over = (i + j + ElementLength) > Length;
126 if (ElementLength != 1 && over)
128 memset(rest,
'x',
sizeof(rest));
132 memcpy(rest, buf + i + j, (i + j + ElementLength) - Length);
136 switch (ElementLength)
139 ret = snprintf(l, rem,
" %02x",
140 over ?
'x' : buf[i + j]);
143 ret = snprintf(l, rem,
" %04x",
144 over ? * (
WORD *)rest : * (
const WORD *)(buf + i + j));
147 ret = snprintf(l, rem,
" %08x",
148 over ? * (
DWORD *)rest : * (
const DWORD *)(buf + i + j));
151 ret = snprintf(l, rem,
" %016llx",
152 over ? * (
QWORD *)rest : * (
const QWORD *)(buf + i + j));
162 ret = snprintf(l, rem,
" ");
166 for (
size_t j = 0; j < (size_t)RowLength * ElementLength; j++)
168 ret = snprintf(l, rem,
"%c", (i + j >= Length) ?
'x' :
IS_ASCII(buf[i + j]) ? buf[i + j] :
'.');
223 ERROR(
"[ERROR] IntCr3Read failed: %08x\n", status);
237 ERROR(
"[ERROR] IntVirtMemRead failed for GVA 0x%016llx and length 0x%x: 0x%08x\n", Gva, Length, status);
241 IntDumpBuffer(buf, Gva, retLen, RowLength, ElementLength, LogHeader, DumpAscii);
291 ERROR(
"[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
295 for (
QWORD rip = Rip; rip < Rip + Length;)
297 char temp[ND_MIN_BUF_SIZE];
298 char _line[ND_MIN_BUF_SIZE * 2];
300 int ret, rem =
sizeof(_line);
305 LOG(
"0x%llx db %02x\n", rip, *p);
313 NdToText(&instrux, rip,
sizeof(temp), temp);
315 ret = snprintf(line, rem,
"0x%llx ", rip);
319 for (
DWORD i = 0; i < 14; i++)
321 if (i < instrux.Length)
323 ret = snprintf(line, rem,
"%02x", instrux.InstructionBytes[i]);
329 ret = snprintf(line, rem,
" ");
335 ret = snprintf(line, rem,
" %s", temp);
341 switch (instrux.Instruction)
346 ptr = rip + instrux.Length + instrux.Operands[0].Info.RelativeOffset.Rel;
364 ret = snprintf(line, rem,
" (%s + 0x%llx)", temp, ptr - symStart);
368 ret = snprintf(line, rem,
" (%s)", temp);
378 rip += instrux.Length;
400 QWORD rip = Gva, functionEnd = 0;
405 ERROR(
"[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
409 LOG(
"[DUMPER] Dumping first 0x%x bytes of instructions:\n", Length);
411 while (rip < Gva + Length)
413 char temp[ND_MIN_BUF_SIZE];
414 char _line[ND_MIN_BUF_SIZE * 2];
416 int ret, rem =
sizeof(_line);
436 LOG(
"0x%llx db %02x\n", rip, b);
442 NdToText(&instrux, rip,
sizeof(temp), temp);
444 ret = snprintf(line, rem,
"0x%llx ", rip);
448 for (
DWORD i = 0; i < 14; i++)
450 if (i < instrux.Length)
452 ret = snprintf(line, rem,
"%02x", instrux.InstructionBytes[i]);
458 ret = snprintf(line, rem,
" ");
464 ret = snprintf(line, rem,
" %s", temp);
470 switch (instrux.Instruction)
475 ptr = rip + instrux.Length + instrux.Operands[0].Info.RelativeOffset.Rel;
493 ret = snprintf(line, rem,
" (%s + 0x%llx)", temp, ptr - symStart);
497 ret = snprintf(line, rem,
" (%s)", temp);
507 rip += instrux.Length;
514 _In_ INSTRUX *Instruction,
524 char nd[ND_MIN_BUF_SIZE] = {0};
527 if (NULL == Instruction)
532 status = NdToText(Instruction, Rip,
sizeof(nd), nd);
533 if (!ND_SUCCESS(status))
535 snprintf(nd,
sizeof(nd),
"<invalid: %08x>", status);
538 LOG(
"[DUMPER] Dumping instruction at %llx: %s\n", Rip, nd);
545 _In_ const char *FunctionName
558 WARNING(
"[WARNING] IntKsymFindByName could not find %s\n", FunctionName);
584 INSTRUX instrux = { 0 };
585 char text[ND_MIN_BUF_SIZE];
589 LOG(
"First 256 instructions:\n");
591 while ((Offset + i <
PAGE_SIZE) && (insCount++ < 256))
600 NdToText(&instrux, Registers->Rip + i, ND_MIN_BUF_SIZE, text);
602 LOG(
" %llx: %s\n", Registers->Rip + i, text);
608 LOG(
"Raw page dump:\n");
612 LOG(
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
613 Page[i * 16 + 0x0], Page[i * 16 + 0x1], Page[i * 16 + 0x2], Page[i * 16 + 0x3],
614 Page[i * 16 + 0x4], Page[i * 16 + 0x5], Page[i * 16 + 0x6], Page[i * 16 + 0x7],
615 Page[i * 16 + 0x8], Page[i * 16 + 0x9], Page[i * 16 + 0xA], Page[i * 16 + 0xB],
616 Page[i * 16 + 0xC], Page[i * 16 + 0xD], Page[i * 16 + 0xE], Page[i * 16 + 0xF]);
638 DWORD offset, csType;
646 ERROR(
"[ERROR] IntPhysMemMap failed: 0x%08x\n", status);
656 ERROR(
"[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
679 LOG(
"R15 = %016llx R14 = %016llx R13 = %016llx R12 = %016llx Rbp = %016llx\n",
680 TrapFrame->R15, TrapFrame->R14, TrapFrame->R13, TrapFrame->R12, TrapFrame->Rbp);
682 LOG(
"Rbx = %016llx R11 = %016llx R10 = %016llx R9 = %016llx R8 = %016llx \n",
683 TrapFrame->Rbx, TrapFrame->R11, TrapFrame->R10, TrapFrame->R9, TrapFrame->R8);
685 LOG(
"Rax = %016llx Rcx = %016llx Rdx = %016llx Rsi = %016llx Rdi = %016llx\n",
686 TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx, TrapFrame->Rsi, TrapFrame->Rdi);
688 LOG(
"Oax = %016llx Rip = %016llx Cs = %016llx Flg = %016llx Rsp = %016llx Ss = %016llx\n",
689 TrapFrame->OrigRax, TrapFrame->Rip, TrapFrame->Cs, TrapFrame->Rflags, TrapFrame->Rsp, TrapFrame->Ss);
703 LOG(
"RAX = %016llx RCX = %016llx RDX = %016llx R8 = %016llx R9 = %016llx\n",
704 TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx, TrapFrame->R8, TrapFrame->R9);
706 LOG(
"R10 = %016llx GsSwap = %016llx DS = %04x ES = %04x FS = %04x \n",
707 TrapFrame->R10, TrapFrame->GsSwap, TrapFrame->SegDs, TrapFrame->SegEs, TrapFrame->SegFs);
709 LOG(
"GS = %04x RBX = %016llx RDI = %016llx RSI = %016llx RBP = %016llx\n",
710 TrapFrame->SegGs, TrapFrame->Rbx, TrapFrame->Rdi, TrapFrame->Rsi, TrapFrame->Rbp);
712 LOG(
"TrapFrame = 0x%016llx RIP = %016llx CS = %04x FLAGS = %08x RSP = %016llx SS = %04x\n",
713 TrapFrame->TrapFrame, TrapFrame->Rip, TrapFrame->SegCs, TrapFrame->EFlags, TrapFrame->Rsp, TrapFrame->SegSs);
727 LOG(
"GS = %08x ES = %08x DS = %08x EDX = %08x ECX = %08x\n",
728 TrapFrame->SegGs, TrapFrame->SegEs, TrapFrame->SegDs, TrapFrame->Edx, TrapFrame->Ecx);
730 LOG(
"EAX = %08x FS = %08x EDI = %08x ESI = %08x EBX = %08x \n",
731 TrapFrame->Eax, TrapFrame->SegFs, TrapFrame->Edi, TrapFrame->Esi, TrapFrame->Ebx);
733 LOG(
"EBP = %08x EIP = %08x CS = %08x FLAGS = %08x ESP = %08x SS = %08x\n",
738 TrapFrame->HardwareEsp,
739 TrapFrame->HardwareSegSs);
Exposes the functions used to used to dump (log) code and registers.
DWORD Index
The VCPU number.
INTSTATUS IntDumpCodeAndRegs(QWORD Gva, QWORD Gpa, IG_ARCH_REGS *Registers)
This function dumps an entire page (textual disassembly and opcodes) as well as the values of the reg...
#define INT_STATUS_SUCCESS
DWORD KernelSize
The size of the kernel.
void IntDumpWinTrapFrame32(KTRAP_FRAME32 *TrapFrame)
This function dumps a windows 64 guest trap frame.
INTSTATUS IntKsymFindByAddress(QWORD Gva, DWORD Length, char *SymName, QWORD *SymStart, QWORD *SymEnd)
Finds the symbol which is located at the given address.
#define INT_SUCCESS(Status)
TIMER_FRIENDLY void IntDumpBuffer(void *Buffer, QWORD Gva, DWORD Length, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given buffer in a user friendly format.
TIMER_FRIENDLY void IntDumpArchRegs(IG_ARCH_REGS const *Registers)
This function dumps the register values in a user friendly format.
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
TIMER_FRIENDLY void IntDumpInstruction(INSTRUX *Instruction, QWORD Rip)
This function dumps a given instruction (textual disassembly).
void IntDisasmGva(QWORD Gva, DWORD Length)
This function disassembles a code buffer (given its GVA) and then dumps the instructions (textual dis...
INTRO_GUEST_TYPE OSType
The type of the guest.
void IntDumpWinTrapFrame64(KTRAP_FRAME64 *TrapFrame)
This function dumps a windows 64 guest trap frame.
IG_CS_TYPE
The type of the code segment.
INTSTATUS IntGetCurrentMode(DWORD CpuNumber, DWORD *Mode)
Read the current CS type.
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
#define IN_RANGE_LEN(x, start, len)
INTSTATUS IntDecDecodeInstructionFromBuffer(PBYTE Buffer, size_t BufferSize, IG_CS_TYPE CsType, void *Instrux)
Decode an instruction from the provided buffer.
#define HpFreeAndNullWithTag(Add, Tag)
void IntDisasmBuffer(void *Buffer, DWORD Length, QWORD Rip)
This function disassembles a given code buffer and then dumps the instructions (textual disassembly)...
QWORD KernelVa
The guest virtual address at which the kernel image.
void IntDisasmLixFunction(const char *FunctionName)
This function dumps a Linux function (textual disassembly) given its name.
TIMER_FRIENDLY void IntDumpGva(QWORD Gva, DWORD Length, QWORD Cr3)
This function is a wrapper over IntDumpGvaEx (it uses RowLength = 16, ElementLength = 1...
#define _In_reads_bytes_(expr)
TIMER_FRIENDLY void IntDumpGvaEx(QWORD Gva, DWORD Length, QWORD Cr3, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given GVA in a user friendly format. This function uses IntDumpBuffer to perfor...
void IntDumpLixUmTrapFrame(LIX_TRAP_FRAME *TrapFrame)
This function dumps a Linux UM trap frame.
GUEST_STATE gGuest
The current guest state.
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
INTSTATUS IntCr3Read(DWORD CpuNumber, QWORD *Cr3Value)
Reads the value of the guest CR3.
void IntDumpCode(BYTE *Page, DWORD Offset, IG_CS_TYPE CsType, IG_ARCH_REGS *Registers)
This function dumps an entire page (textual disassembly and opcodes).
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
VCPU_STATE * gVcpu
The state of the current VCPU.
VE_CACHE_LINE * Page
Mapped page inside Introspection virtual address space.
QWORD IntKsymFindByName(const char *Name, QWORD *SymEnd)
Searches the given Name in kallsyms and returns the Start & End offset.
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
INTSTATUS IntDecDecodeInstruction(IG_CS_TYPE CsType, QWORD Gva, void *Instrux)
Decode an instruction from the provided guest linear address.