15 #define TRAPFRAME_MAX_ITERATIONS 0x100 35 BYTE defCode, defData;
36 BYTE code[0x20] = { 0 };
38 QWORD calledFuncAddress, i;
49 calledFuncAddress = 0;
58 for (i = 0; i <= 5; i++)
64 ndstatus = NdDecodeEx(&instruction, code + i,
sizeof(code) - i, defCode, defData);
65 if (!ND_SUCCESS(ndstatus))
71 switch (instruction.Instruction)
75 bIsInstruxCall =
TRUE;
77 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
83 bIsInstruxCall =
TRUE;
85 if (ND_OP_IMM == instruction.Operands[0].Type)
87 calledFuncAddress = instruction.Operands[0].Info.Immediate.Imm;
89 else if (ND_OP_MEM == instruction.Operands[0].Type)
93 if (instruction.Operands[0].Info.Memory.IsRipRel)
96 fetchAddress = Gva + instruction.Operands[0].Info.Memory.Disp;
98 else if (instruction.Operands[0].Info.Memory.IsDirect)
100 fetchAddress = instruction.Operands[0].Info.Memory.Disp;
112 WARNING(
"[WARNING] Failed to get function address from 0x%016llx (Call RIP 0x%016llx): 0x%08x\n",
113 fetchAddress, Gva, status);
114 calledFuncAddress = 0;
117 else if (ND_OP_OFFS == instruction.Operands[0].Type)
119 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
127 bIsInstruxCall =
TRUE;
129 if (ND_OP_OFFS == instruction.Operands[0].Type)
131 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
133 else if (ND_OP_MEM == instruction.Operands[0].Type)
137 if (instruction.Operands[0].Info.Memory.IsRipRel)
140 fetchAddress = Gva + instruction.Operands[0].Info.Memory.Disp;
142 else if (instruction.Operands[0].Info.Memory.IsDirect)
144 fetchAddress = instruction.Operands[0].Info.Memory.Disp;
156 WARNING(
"[WARNING] Failed to get function address from 0x%016llx (Call RIP 0x%016llx): 0x%08x\n",
157 fetchAddress, Gva, status);
158 calledFuncAddress = 0;
161 else if (ND_OP_REG == instruction.Operands[0].Type)
163 calledFuncAddress = 0;
178 if (Gva == Gva - (7 - i) + instruction.Length && bIsInstruxCall)
180 goto cleanup_and_leave;
194 if (calledFuncAddress == 0)
200 calledFuncAddress, &instruction);
208 if ((ND_CAT_COND_BR != instruction.Category) && (ND_CAT_UNCOND_BR != instruction.Category))
213 switch (instruction.Instruction)
217 if (ND_OP_MEM == instruction.Operands[0].Type)
221 if (instruction.Operands[0].Info.Memory.IsRipRel)
224 fetchAddress = calledFuncAddress + instruction.Length + instruction.Operands[0].Info.Memory.Disp;
226 else if (instruction.Operands[0].Info.Memory.IsDirect)
228 fetchAddress = instruction.Operands[0].Info.Memory.Disp;
240 ERROR(
"[ERROR] Failed to get function address from 0x%016llx (Call RIP 0x%016llx): 0x%08x\n",
241 fetchAddress, calledFuncAddress, status);
242 calledFuncAddress = 0;
245 else if (ND_OP_REG == instruction.Operands[0].Type)
247 calledFuncAddress = 0;
255 calledFuncAddress = calledFuncAddress + instruction.Length + instruction.Operands[0].Info.RelativeOffset.Rel;
264 if (NULL != CallAddress)
297 QWORD currentRip, currentRsp, newRsp, currentModBase;
298 PBYTE pStack, pStackBase, pModBaseMap;
303 if (NULL == StackTrace || NULL == StackTrace->Traces)
310 StackTrace->NumberOfTraces = 0;
311 StackTrace->StartRip = Rip;
312 StackTrace->Bits64 =
TRUE;
313 pStack = pModBaseMap = pStackBase = NULL;
315 currentRsp = Rsp & ~7;
319 ripInsideSameModule =
FALSE;
324 DWORD prologueSize, tries, beginRva;
325 QWORD retAddress, retModuleBase, calledAddress, retAddrPtr;
326 BOOLEAN interrupt, exception, hasFramePointer, found, fErrorCode;
328 memzero(&runtimeFunction,
sizeof(runtimeFunction));
329 prologueSize = tries = beginRva = 0;
330 found = hasFramePointer = interrupt = exception = fErrorCode =
FALSE;
331 retModuleBase = retAddress = calledAddress = retAddrPtr = 0;
335 if (!ripInsideSameModule)
338 if (NULL != pModBaseMap)
344 if (0 == currentModBase)
350 StackTrace->NumberOfTraces > 0)
352 ERROR(
"[ERROR] Failed to find the module base of RIP 0x%016llx RSP 0x%016llx at try %d\n",
353 currentRip, currentRsp, StackTrace->NumberOfTraces);
355 else if (StackTrace->NumberOfTraces == 0)
358 goto _start_searching;
363 currentModBase = pDriver->
BaseVa;
366 if (0 == currentModBase)
370 goto _cleanup_and_leave;
374 goto _start_searching;
387 if (pDriver != NULL &&
398 ERROR(
"[ERROR] Failed mapping driver base 0x%016llx to host: 0x%08x\n",
399 currentModBase, status);
402 goto _cleanup_and_leave;
406 else if (currentModBase == 0)
410 goto _cleanup_and_leave;
414 goto _start_searching;
422 (
DWORD)(currentRip - currentModBase),
430 (
DWORD)(currentRip - currentModBase),
436 ERROR(
"[ERROR] Failed getting runtime function for module 0x%016llx RIP 0x%016llx: 0x%08x\n",
437 currentModBase, currentRip, status);
438 goto _cleanup_and_leave;
447 DWORD ripOffset = (
DWORD)(currentRip - currentModBase);
454 if (ripOffset < runtimeFunction.BeginAddress || ripOffset > runtimeFunction.
EndAddress)
456 ripOffset = runtimeFunction.
EndAddress - beginRva;
460 ripOffset -= beginRva;
491 ERROR(
"[ERROR] IntPeParseUnwindData failed for driver 0x%016llx with RIP 0x%016llx and begining " 492 "RVA 0x%x: 0x%08x\n", currentModBase, currentRip, runtimeFunction.
BeginAddress, status);
493 goto _cleanup_and_leave;
499 newRsp = currentRsp + prologueSize;
513 if (!hasFramePointer && (interrupt || exception))
519 ERROR(
"[ERROR] Failed getting the return address form GVA 0x%016llx: 0x%08x",
520 newRsp + (exception ? 8 : 0), status);
521 goto _cleanup_and_leave;
528 retModuleBase = pDriver ? pDriver->
BaseVa : 0;
536 LOG(
"[STACK] NONHEUR : Found trap frame at stack address 0x%016llx with ret address 0x%016llx \n",
539 retAddrPtr = newRsp + ((exception) ? 8 : 0);
540 newRsp += (exception) ? (6 * 8) : (5 * 8);
543 goto _next_stack_frame;
547 fErrorCode = exception;
556 if (NULL != pStackBase)
568 goto _cleanup_and_leave;
578 if (hasFramePointer && (exception || interrupt))
581 BOOLEAN um, km, fRip, fCs, fSs, fRsp, fEflags;
582 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
587 if (*pTrapFrame > 0xffffffff)
589 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
590 fErrorCode = exception;
607 else if (*pTrapFrame > 0xffffffff && *pTrapFrame != 0xffffffffffffffff)
613 newRsp -= interrupt ? 8 : 0;
614 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
615 fErrorCode = exception;
622 retAddress = *pTrapFrame;
631 if (*pTrapFrame > 0xff)
633 newRsp -= interrupt ? 8 * 2 : 8;
634 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
635 fErrorCode = exception;
636 retAddrPtr = retAddress = 0;
641 if (km && (*pTrapFrame % 8 != 0))
643 newRsp -= interrupt ? 8 * 2 : 8;
644 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
645 fErrorCode = exception;
646 retAddrPtr = retAddress = 0;
657 if (*pTrapFrame == 0)
659 newRsp -= interrupt ? 8 * 3 : 8 * 2;
660 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
661 fErrorCode = exception;
662 retAddrPtr = retAddress = 0;
669 if ((*pTrapFrame > (1 << 22)) ||
670 (*pTrapFrame & (1 << 14)) ||
671 (*pTrapFrame & (1 << 5)) ||
672 (*pTrapFrame & (1 << 3)) ||
673 (0 == (*pTrapFrame & (1 << 1))))
675 newRsp -= interrupt ? 8 * 3 : 8 * 2;
676 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
677 fErrorCode = exception;
678 retAddrPtr = retAddress = 0;
689 if (0 != *pTrapFrame % 8)
691 newRsp -= interrupt ? 8 * 4 : 8 * 3;
692 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
693 fErrorCode = exception;
694 retAddrPtr = retAddress = 0;
701 newRsp -= interrupt ? 8 * 4 : 8 * 3;
702 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
703 fErrorCode = exception;
704 retAddrPtr = retAddress = 0;
709 newRsp -= interrupt ? 8 * 4 : 8 * 3;
710 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
711 fErrorCode = exception;
712 retAddrPtr = retAddress = 0;
721 if (fErrorCode && fRip && fCs && fEflags && fRsp && fSs)
723 newRsp -= interrupt ? 5 * 8 : 4 * 8;
731 calledAddress = currentModBase + beginRva;
742 retAddress = *(
PQWORD)pStack;
760 if (calledAddress != 0 && currentModBase != 0 && calledAddress != currentModBase + beginRva)
764 if (calledAddress < currentModBase + beginRva &&
767 goto _analyze_jmp_after_call_case;
770 else if (calledAddress != 0 &&
771 (calledAddress < currentRip - MAX_FUNC_LENGTH || calledAddress > currentRip))
775 goto _analyze_jmp_after_call_case;
780 goto _stack_trace_ok;
782 _analyze_jmp_after_call_case:
791 crip = calledAddress;
793 for (
DWORD i = 0; i < 100; i++)
796 QWORD calledFuncAddress = 0;
805 switch (instrux.Instruction)
811 if (ND_OP_MEM == instrux.Operands[0].Type)
815 if (instrux.Operands[0].Info.Memory.IsRipRel)
818 fetchAddress = crip + instrux.Length + instrux.Operands[0].Info.Memory.Disp;
820 else if (instrux.Operands[0].Info.Memory.IsDirect)
822 fetchAddress = instrux.Operands[0].Info.Memory.Disp;
834 WARNING(
"[WARNING] Failed to get function address from 0x%016llx " 835 "(Call RIP 0x%016llx): 0x%08x\n", fetchAddress, crip, status);
836 calledFuncAddress = 0;
840 else if (ND_OP_REG == instrux.Operands[0].Type)
842 calledFuncAddress = 0;
861 if (calledFuncAddress == 0 ||
862 (calledFuncAddress >= currentRip -
MAX_FUNC_LENGTH && calledFuncAddress <= currentRip))
865 calledAddress = calledFuncAddress;
866 goto _stack_trace_ok;
871 crip += instrux.Length;
899 goto _finish_searching_data_sec;
908 _finish_searching_data_sec:
913 if (!bIsCode && pDriver && calledAddress == 0)
918 retModuleBase = pDriver ? pDriver->
BaseVa : 0;
928 goto _next_stack_frame;
940 if (
INT_SUCCESS(status) && 0 == StackTrace->NumberOfTraces)
945 goto _cleanup_and_leave;
948 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = currentRip;
949 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = retAddrPtr;
950 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
951 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pDriver;
954 currentRip = retAddress;
957 if (calledAddress != currentModBase + beginRva)
972 if (calledAddress != 0)
974 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = calledAddress;
976 else if (beginRva > 0)
978 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = currentModBase + beginRva;
982 if (retModuleBase == currentModBase)
984 ripInsideSameModule =
TRUE;
988 ripInsideSameModule =
FALSE;
989 currentModBase = retModuleBase;
993 StackTrace->NumberOfTraces++;
996 currentRsp = newRsp + (interrupt ? 5 * 8 : exception ? 4 * 8 : 0);
998 if (retAddrPtr == currentRsp && 0 == retModuleBase && !interrupt && !exception)
1008 ERROR(
"[ERROR] Didn't found a trace on the stack. RIP at 0x%016llx in module 0x%016llx\n",
1009 currentRip, currentModBase);
1013 goto _cleanup_and_leave;
1021 }
while (StackTrace->NumberOfTraces < MaxTraces);
1026 pStack = pStackBase;
1030 if (NULL != pModBaseMap)
1071 PDWORD pStack, pOrigStack;
1080 if (0 == MaxNumberOfTraces)
1085 if (NULL == StackTrace || NULL == StackTrace->Traces)
1092 StackTrace->StartRip = Eip;
1093 StackTrace->NumberOfTraces = 0;
1094 StackTrace->Bits64 =
FALSE;
1097 pStack = pOrigStack = NULL;
1101 for (
DWORD frame = 0; frame < MaxNumberOfTraces; frame++)
1103 DWORD retAddress = 0;
1104 DWORD nextFrame = 0;
1112 if (NULL != pOrigStack)
1117 status =
IntVirtMemMap(ebp, remaining, cr3, 0, &pOrigStack);
1120 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp, status);
1121 goto _check_and_leave;
1124 pStack = pOrigStack;
1128 nextFrame = pStack[0];
1130 if (nextFrame % 4 != 0)
1132 WARNING(
"[WARNING] Unaligned stack: %08x\n", nextFrame);
1133 goto _check_and_leave;
1137 TRACE(
"[INFO] User-Mode stack: %08x\n", nextFrame);
1138 goto _check_and_leave;
1143 retAddress = pStack[1];
1150 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp + 4, status);
1151 goto _check_and_leave;
1160 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
1161 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1163 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = ebp + 4;
1164 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = 0;
1165 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = 0;
1167 ++StackTrace->NumberOfTraces;
1169 if ((ebp &
PAGE_MASK) != (nextFrame & PAGE_MASK))
1176 DWORD diff = (ebp > nextFrame) ? (
DWORD)(ebp - nextFrame) : (
DWORD)(nextFrame - ebp);
1188 if (NULL != pOrigStack)
1195 if (0 == StackTrace->NumberOfTraces)
1260 PDWORD pStack, pOrigStack;
1264 cr3 = Registers->Cr3;
1265 ebp = Registers->Rbp;
1266 pStack = pOrigStack = NULL;
1269 for (
DWORD frame = 0; frame < MaxNumberOfTraces; frame++)
1271 DWORD retAddress = 0;
1272 DWORD nextFrame = 0;
1280 if (NULL != pOrigStack)
1285 status =
IntVirtMemMap(ebp, remaining, cr3, 0, &pOrigStack);
1288 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp, status);
1289 goto _check_and_leave;
1292 pStack = pOrigStack;
1296 nextFrame = pStack[0];
1298 if (nextFrame % 4 != 0)
1300 ERROR(
"[ERROR] Unaligned stack value %08x (current %08llx)\n", nextFrame, ebp);
1301 goto _check_and_leave;
1305 TRACE(
"[INFO] Kernel-Mode stack %08x (current %08llx)\n", nextFrame, ebp);
1306 goto _check_and_leave;
1308 else if (0 == nextFrame)
1311 goto _check_and_leave;
1314 if (nextFrame < ebp)
1316 ERROR(
"[ERROR] Return stack frame %x is smaller than current %llx\n", nextFrame, ebp);
1317 goto _check_and_leave;
1322 retAddress = pStack[1];
1329 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp + 4, status);
1330 goto _check_and_leave;
1337 WARNING(
"[WARNING] Failed getting the dll base for RIP %08x\n", retAddress);
1338 goto _check_and_leave;
1353 goto _save_and_next;
1358 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
1359 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1361 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = ebp + 4;
1362 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = 0;
1363 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = 0;
1365 ++StackTrace->NumberOfTraces;
1367 if ((ebp &
PAGE_MASK) != (nextFrame & PAGE_MASK))
1392 if (0 == StackTrace->NumberOfTraces)
1428 stackFrame = Registers->Rsp;
1430 for (
DWORD j = 0; j < 2; j++)
1434 status =
IntVirtMemMap(stackFrame, remaining, Registers->Cr3, 0, &pStack);
1437 TRACE(
"[WARNING] Cannot get a stack at address %llx (start RSP %llx): 0x%08x\n",
1438 stackFrame, Registers->Rsp, status);
1442 for (
DWORD i = 0; i < remaining; i += 8)
1448 ret = *(
QWORD *)(pStack + i);
1474 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = ret;
1475 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1476 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = stackFrame + i;
1478 if (++StackTrace->NumberOfTraces >= MaxNumberOfTraces)
1486 if (StackTrace->NumberOfTraces >= MaxNumberOfTraces)
1492 if (StackTrace->NumberOfTraces == 0)
1522 if (NULL == Registers)
1527 if (NULL == Process)
1532 if (0 == MaxNumberOfTraces)
1543 StackTrace->StartRip = Registers->Rip;
1544 StackTrace->NumberOfTraces = 0;
1549 ERROR(
"[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
1555 ERROR(
"[ERROR] Unsupported CS type: %d\n", csType);
1561 QWORD stackFrame = Registers->Rbp;
1563 StackTrace->Bits64 =
FALSE;
1565 if ((stackFrame > Registers->Rsp &&
1566 stackFrame - Registers->Rsp > 3 *
PAGE_SIZE) ||
1567 (stackFrame < Registers->Rsp &&
1568 Registers->Rsp - stackFrame > 3 *
PAGE_SIZE))
1573 DWORD retAddress = 0;
1576 stackFrame = Registers->Rsp;
1581 for (
size_t stackIndex = 0; stackIndex < 8; stackIndex++)
1583 status =
IntVirtMemRead(stackFrame + stackIndex * 4, 4, Registers->Cr3, &retAddress, NULL);
1586 ERROR(
"[ERROR] RSP 0x%016llx is not present: %08x\n", stackFrame + stackIndex * 4, status);
1602 ERROR(
"[ERROR] DLL base was not found on stack 0x%016llx\n", stackFrame);
1606 StackTrace->NumberOfTraces = 1;
1608 StackTrace->Traces[0].ReturnAddress = retAddress;
1609 StackTrace->Traces[0].ReturnModule = pMod;
1610 StackTrace->Traces[0].RetAddrPointer = stackFrame;
1624 StackTrace->Bits64 =
TRUE;
1666 if (NULL == IsPivoted)
1680 alignSize =
sizeof(
DWORD);
1688 ERROR(
"[ERROR] Unrecognized CS value: 0x%08x\n", SegCs);
1699 UserRsp % alignSize != 0)
1708 ERROR(
"[ERROR] IntWinThrGetCurrentTib failed: 0x%08x\n", status);
1724 WARNING(
"[WARNING] IntWinThrGetUmStackBaseAndLimitFromTib failed: 0x%08x\n", status);
1728 ERROR(
"[ERROR] IntWinThrGetUmStackBaseAndLimitFromTib failed: 0x%08x\n", status);
1734 DpiExtraInfo->DpiPivotedStackExtraInfo.Wow64StackBase = stackBase;
1735 DpiExtraInfo->DpiPivotedStackExtraInfo.Wow64StackLimit = stackLimit;
1739 DpiExtraInfo->DpiPivotedStackExtraInfo.StackBase = stackBase;
1740 DpiExtraInfo->DpiPivotedStackExtraInfo.StackLimit = stackLimit;
1743 if (UserRsp < stackLimit || UserRsp > stackBase)
1745 WARNING(
"[WARNING] UM stack (0x%016llx) outside of the limit and base interval " 1746 "from the current TIB [0x%016llx, 0x%016llx].\n", UserRsp, stackLimit, stackBase);
1778 QWORD stackPointerGVA;
1781 stackPointer = NULL;
1782 stackPointerGVA = 0;
1790 if (NULL == TrapFrame)
1801 ERROR(
"[ERROR] IntVirtMemMap failed from GVA 0x%016llx: 0x%08x\n", stackPointerGVA, status);
1813 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = stackPointerGVA + i;
1815 TRACE(
"[INFO] TrapFrame found: 0x%016llx\n", stackPointerGVA + i);
1855 QWORD stackPointerGVA;
1859 stackPointer = NULL;
1860 stackPointerGVA = 0;
1868 if (NULL == TrapFrame)
1879 ERROR(
"[ERROR] IntVirtMemMap failed from GVA 0x%016llx: 0x%08x\n", stackPointerGVA, status);
1891 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = stackPointerGVA + i;
1893 TRACE(
"[INFO] TrapFrame found: 0x%016llx\n", stackPointerGVA + i);
1932 QWORD currentThread = 0;
1934 if (NULL == UserRsp)
1950 ERROR(
"[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
1956 QWORD trapFrameAddress = 0;
1957 QWORD stackBase = 0;
1963 ERROR(
"[ERROR] Failed getting the TrapFrame from Ethread 0x%016llx: 0x%08x\n", currentThread, status);
1975 ERROR(
"[ERROR] Failed getting the trap frame from CurrentThread 0x%016llx: 0x%08x\n",
1976 currentThread, status);
1980 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
1990 ERROR(
"[ERROR] Failed getting the TrapFrame from CurrentThread 0x%016llx: 0x%08x\n",
1991 currentThread, status);
1995 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
2000 WARNING(
"[WARNING] Specially crafted TrapFrame somehow: 0x%016llx\n", trapFrameAddress);
2011 ERROR(
"[ERROR] Failed getting the StackBase from CurrentThread 0x%016llx: 0x%08x\n",
2012 currentThread, status);
2019 ERROR(
"[ERROR] Failed getting a TrapFrame: 0x%08x.\n", status);
2024 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentStack = trapFrame.
Rsp;
2026 *UserRsp = trapFrame.
Rsp;
2027 *SegCs = trapFrame.
SegCs;
2032 DWORD trapFrameAddress = 0;
2033 DWORD stackBase = 0;
2038 ERROR(
"[ERROR] Failed getting the TrapFrame from Ethread 0x%016llx: 0x%08x\n", currentThread, status);
2048 ERROR(
"[ERROR] Failed reading the TrapFrame from CurrentThread 0x%016llx: 0x%08x\n",
2049 currentThread, status);
2055 WARNING(
"[WARNING] Current TrapFrame 0x%08x has a kernel mode Eip: 0x%08x \n",
2056 trapFrameAddress, trapFrame.
Eip);
2061 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
2070 ERROR(
"[ERROR] Failed getting the StackBase from CurrentThread 0x%016llx: 0x%08x\n",
2071 currentThread, status);
2078 ERROR(
"[ERROR] Failed getting a TrapFrame: 0x%08x.\n", status);
2083 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentStack = trapFrame.
HardwareEsp;
2113 QWORD wow64SaveArea = 0;
2114 QWORD userWow64Rsp = 0;
2120 ERROR(
"[ERROR] IntWinThrGetCurrentTib failed: 0x%08x\n", status);
2129 INFO(
"[INFO] IntVirtMemRead failed: 0x%08x, the page 0x%016llx seems to be swapped out...\n", status,
2135 ERROR(
"[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
2140 &userWow64Rsp, NULL);
2143 INFO(
"[INFO] IntVirtMemRead failed: 0x%08x, the page 0x%016llx seems to be swapped out...\n", status,
2144 wow64SaveArea +
WIN_UM_FIELD(Teb, Wow64StackInSaveArea));
2149 ERROR(
"[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
2153 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentWow64Stack = userWow64Rsp;
2157 &Process->CreationInfo.ParentHasPivotedStack);
2160 ERROR(
"[ERROR] IntWinStackUserCheckIsPivoted failed: 0x%08x.\n", status);
2163 else if (Process->CreationInfo.ParentHasPivotedStack)
2165 WARNING(
"[WARNING] Process 0x%016llx created with WoW64 pivoted stack.\n", Process->EprocessAddress);
2174 _In_ void *TrapFrame
2189 if ((trapFrame->
EFlags >= (1 << 22)) ||
2190 (trapFrame->
EFlags & (1 << 1)) == 0 ||
2191 (trapFrame->
EFlags & (1 << 3)) != 0 ||
2192 (trapFrame->
EFlags & (1 << 5)) != 0 ||
2193 (trapFrame->
EFlags & (1 << 15)) != 0)
2199 switch (trapFrame->
SegCs)
2209 if (trapFrame->
Rsp % 8 != 0 ||
2211 trapFrame->
Rsp == 0 ||
2219 trapFrame->
Rip == 0 ||
2230 if ((trapFrame->
EFlags >= (1 << 22)) ||
2231 (trapFrame->
EFlags & (1 << 1)) == 0 ||
2232 (trapFrame->
EFlags & (1 << 3)) != 0 ||
2233 (trapFrame->
EFlags & (1 << 5)) != 0 ||
2234 (trapFrame->
EFlags & (1 << 15)) != 0)
2256 trapFrame->
Eip == 0 ||
#define IMAGE_SCN_MEM_EXECUTE
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
INTSTATUS IntPeParseUnwindDataInBuffer(QWORD ImageBase, BYTE *Buffer, DWORD BufferSize, RUNTIME_FUNCTION *RuntimeFunction, DWORD RipOffset, DWORD *ReservedStack, DWORD *BeginAddress, BOOLEAN *InterruptFunction, BOOLEAN *ExceptionFunction, BOOLEAN *HasFramePointer)
Parse the unwind data for the indicated function and return the prologue size.
#define MAX_FUNC_LENGTH
The maximum length (in bytes) of a function.
INTSTATUS IntPeGetSectionHeaderByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD GuestRva, IMAGE_SECTION_HEADER *SectionHeader)
Given a relative virtual address, return the section header which describes the section the RVA lies ...
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
INTSTATUS IntPeGetRuntimeFunctionInBuffer(QWORD ImageBase, BYTE *Buffer, DWORD BufferSize, DWORD Rva, RUNTIME_FUNCTION *RuntimeFunction)
Parses the exception directory and gets the runtime function corresponding to the Rva...
struct _KTRAP_FRAME32 KTRAP_FRAME32
static INTSTATUS IntWinStackTraceGetUser32(PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace)
Get the user stack trace of a 32 bit windows process.
struct _KTRAP_FRAME32 * PKTRAP_FRAME32
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
IG_ARCH_REGS Regs
The current state of the guest registers.
static INTSTATUS IntWinStackTraceGet32(DWORD Stack, DWORD Eip, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace)
Get a kernel stack trace starting from the current stack pointer for 32 bit systems.
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
INTSTATUS IntWinStackUserCheckIsPivoted(QWORD UserRsp, DWORD SegCs, BOOLEAN IsWow64Stack, DPI_EXTRA_INFO *DpiExtraInfo, BOOLEAN *IsPivoted)
Check whether the stack is pivoted by checking if it's in the bounds of the stack base and limit from...
#define PAGE_REMAINING(addr)
WIN_KERNEL_DRIVER Win
Valid only for Windows guests.
INTSTATUS IntWinThrGetCurrentTib(IG_CS_RING CurrentRing, IG_CS_TYPE CsType, QWORD *Tib)
Obtain the TIB (Thread Information Block) of the thread running on the current CPU.
#define CODE_SEG_UM_32_GUEST_64
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
#define WIN_UM_FIELD(Structure, Field)
Macro used to access user mode fields inside the WIN_OPAQUE_FIELDS structure.
BOOLEAN IntWinIsUmTrapFrame(void *TrapFrame)
Checks whether a TrapFrame is valid or not.
#define INT_SUCCESS(Status)
INTSTATUS IntWinThrGetCurrentThread(DWORD CpuNumber, QWORD *EthreadAddress)
Get the ETHREAD structure address of the thread currently running on the given CPU.
Structure that describes a stack trace element.
PBYTE MzPeHeaders
The driver`s MZ/PE headers (cached internally).
#define INT_STATUS_NOT_NEEDED_HINT
int INTSTATUS
The status data type.
Measures the cases in which the stack trace mechanism encounters a JMP after a CALL.
#define INT_STATUS_NOT_FOUND
INTSTATUS IntWinStackTraceGet(QWORD StackFrame, QWORD Rip, DWORD MaxNumberOfTraces, QWORD Flags, STACK_TRACE *StackTrace)
Get a kernel stack trace starting from the current stack pointer for 64 bit systems.
QWORD VirtualBase
Guest virtual address of the loaded module.
INTSTATUS IntPeParseUnwindData(QWORD ImageBase, BYTE *ImageBaseBuffer, RUNTIME_FUNCTION *RuntimeFunction, DWORD RipOffset, DWORD *ReservedStack, DWORD *BeginAddress, BOOLEAN *InterruptFunction, BOOLEAN *ExceptionFunction, BOOLEAN *HasFramePointer)
Parse the unwind data for the indicated function and return the prologue size.
INTSTATUS IntWinStackWow64CheckIsPivoted(WIN_PROCESS_OBJECT *Process, WIN_PROCESS_OBJECT *RealParent, DPI_EXTRA_INFO *DpiExtraInfo)
Check whether a wow64 process' stack is pivoted.
Describes a kernel driver.
#define STACK_CALL_ADDRESS_IMPRECISE
Flag used to tell that the CalledAddress in a STACK_ELEMENT is not precise (it's an approximation)...
PWIN_PROCESS_MODULE IntWinUmModFindByAddress(PWIN_PROCESS_OBJECT Process, QWORD Gva)
Searches for a user-mode module which contains the indicated guest virtual address.
Exposes the functions used to provide Windows Threads related support.
INTSTATUS IntGetCurrentMode(DWORD CpuNumber, DWORD *Mode)
Read the current CS type.
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
#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...
struct _KTRAP_FRAME64 * PKTRAP_FRAME64
#define INT_STATUS_UNSUCCESSFUL
struct _KTRAP_FRAME64 KTRAP_FRAME64
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
#define STACK_INTERRUPT_ROUTINE
Flag used to tell that the ReturnAddress in a STACK_ELEMENT is an interrupt routine.
Measures the stack trace mechanism for 32-bit execution contexts.
#define INT_STATUS_INVALID_PARAMETER_4
static INTSTATUS IntWinStackUserTrapFrameGet32(DWORD KernelStack, DPI_EXTRA_INFO *DpiExtraInfo, KTRAP_FRAME32 *TrapFrame)
Get a 32 bit trap frame from a kernel stack.
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
#define CODE_SEG_UM_64_GUEST_64
#define INT_STATUS_INVALID_PARAMETER_5
void * Name
The name of the driver.
INTSTATUS IntWinStackUserTrapFrameGetGeneric(QWORD *UserRsp, DWORD *SegCs, BOOLEAN Fallback, DPI_EXTRA_INFO *DpiExtraInfo)
Get a bit trap frame from a kernel stack.
QWORD KernelVa
The guest virtual address at which the kernel image.
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
#define STACK_EXCEPTION_ROUTINE
Flag used to tell that the ReturnAddress in a STACK_ELEMENT is an exception routine.
#define UNREFERENCED_PARAMETER(P)
INTSTATUS IntWinThrGetUmStackBaseAndLimitFromTib(QWORD Tib, IG_CS_TYPE CsType, QWORD Cr3, QWORD *StackBase, QWORD *StackLimit)
Obtains the user mode stack base and stack limit values.
#define TRAPFRAME_MAX_ITERATIONS
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
DWORD KernelBufferSize
The size of the KernelBuffer.
static INTSTATUS IntWinStackTraceGetUser64(PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace)
Get the user stack trace of a 64 bit windows process.
#define IMAGE_SCN_CNT_CODE
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
GUEST_STATE gGuest
The current guest state.
WINUM_MODULE_CACHE * Cache
Module headers cache.
#define CODE_SEG_UM_32_GUEST_32
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
#define FIX_GUEST_POINTER(is64, x)
Masks the unused part of a Windows guest virtual address.
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
BYTE * KernelBuffer
A buffer containing the entire kernel image.
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
VCPU_STATE * gVcpu
The state of the current VCPU.
static INTSTATUS IntWinStackUserTrapFrameGet64(QWORD KernelStack, DPI_EXTRA_INFO *DpiExtraInfo, KTRAP_FRAME64 *TrapFrame)
Get a 64 bit trap frame from a kernel stack.
static INTSTATUS IntWinStackTraceGet64(QWORD Rsp, QWORD Rip, DWORD MaxTraces, QWORD Flags, STACK_TRACE *StackTrace)
Get a kernel stack trace starting from the current stack pointer for 64 bit systems.
Structure that describes a stack trace.
#define STACK_FLG_ONLY_DRIVER_ADDRS
Flag that tells to only get addresses inside drivers.
INTSTATUS IntWinStackTraceGetUser(PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, STACK_TRACE *StackTrace)
Get the user stack trace of a windows process.
unsigned long long * PQWORD
static INTSTATUS IntStackAnalyzePointer(QWORD Gva, QWORD *CallAddress)
Get the address of the kernel function that was called in order to push Gva on the stack as a return ...
BYTE * Headers
A buffer containing the MZ/PE headers of this module.
INTSTATUS IntPeGetRuntimeFunction(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD Rva, RUNTIME_FUNCTION *RuntimeFunction)
Parses the exception directory and gets the runtime function corresponding to the Rva...
#define INT_STATUS_INVALID_PARAMETER_2
INTSTATUS IntDecDecodeInstruction(IG_CS_TYPE CsType, QWORD Gva, void *Instrux)
Decode an instruction from the provided guest linear address.
This structure describes a running process inside the guest.
#define INT_STATUS_INVALID_PARAMETER_3