16 #define TRAPFRAME_MAX_ITERATIONS 0x100 36 BYTE defCode, defData;
37 BYTE code[0x20] = { 0 };
39 QWORD calledFuncAddress, i;
50 calledFuncAddress = 0;
59 for (i = 0; i <= 5; i++)
65 ndstatus = NdDecodeEx(&instruction, code + i,
sizeof(code) - i, defCode, defData);
66 if (!ND_SUCCESS(ndstatus))
72 switch (instruction.Instruction)
76 bIsInstruxCall =
TRUE;
78 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
84 bIsInstruxCall =
TRUE;
86 if (ND_OP_IMM == instruction.Operands[0].Type)
88 calledFuncAddress = instruction.Operands[0].Info.Immediate.Imm;
90 else if (ND_OP_MEM == instruction.Operands[0].Type)
94 if (instruction.Operands[0].Info.Memory.IsRipRel)
97 fetchAddress = Gva + instruction.Operands[0].Info.Memory.Disp;
99 else if (instruction.Operands[0].Info.Memory.HasDisp &&
100 !instruction.Operands[0].Info.Memory.HasBase &&
101 !instruction.Operands[0].Info.Memory.HasIndex)
103 fetchAddress = instruction.Operands[0].Info.Memory.Disp;
115 WARNING(
"[WARNING] Failed to get function address from 0x%016llx (Call RIP 0x%016llx): 0x%08x\n",
116 fetchAddress, Gva, status);
117 calledFuncAddress = 0;
120 else if (ND_OP_OFFS == instruction.Operands[0].Type)
122 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
130 bIsInstruxCall =
TRUE;
132 if (ND_OP_OFFS == instruction.Operands[0].Type)
134 calledFuncAddress = Gva + instruction.Operands[0].Info.RelativeOffset.Rel;
136 else if (ND_OP_MEM == instruction.Operands[0].Type)
140 if (instruction.Operands[0].Info.Memory.IsRipRel)
143 fetchAddress = Gva + instruction.Operands[0].Info.Memory.Disp;
145 else if (instruction.Operands[0].Info.Memory.HasDisp &&
146 !instruction.Operands[0].Info.Memory.HasBase &&
147 !instruction.Operands[0].Info.Memory.HasIndex)
149 fetchAddress = instruction.Operands[0].Info.Memory.Disp;
161 WARNING(
"[WARNING] Failed to get function address from 0x%016llx (Call RIP 0x%016llx): 0x%08x\n",
162 fetchAddress, Gva, status);
163 calledFuncAddress = 0;
166 else if (ND_OP_REG == instruction.Operands[0].Type)
168 calledFuncAddress = 0;
183 if (Gva == Gva - (7 - i) + instruction.Length && bIsInstruxCall)
185 goto cleanup_and_leave;
198 if (NULL != CallAddress)
231 QWORD currentRip, currentRsp, newRsp, currentModBase;
232 PBYTE pStack, pStackBase, pModBaseMap;
237 if (NULL == StackTrace || NULL == StackTrace->Traces)
244 StackTrace->NumberOfTraces = 0;
245 StackTrace->StartRip = Rip;
246 StackTrace->Bits64 =
TRUE;
247 pStack = pModBaseMap = pStackBase = NULL;
249 currentRsp = Rsp & ~7;
253 ripInsideSameModule =
FALSE;
258 DWORD prologueSize, tries, beginRva;
259 QWORD retAddress, retModuleBase, calledAddress, retAddrPtr;
260 BOOLEAN interrupt, exception, hasFramePointer, found, fErrorCode;
262 memzero(&runtimeFunction,
sizeof(runtimeFunction));
263 prologueSize = tries = beginRva = 0;
264 found = hasFramePointer = interrupt = exception = fErrorCode =
FALSE;
265 retModuleBase = retAddress = calledAddress = retAddrPtr = 0;
269 if (!ripInsideSameModule)
272 if (NULL != pModBaseMap)
278 if (0 == currentModBase)
284 StackTrace->NumberOfTraces > 0)
286 ERROR(
"[ERROR] Failed to find the module base of RIP 0x%016llx RSP 0x%016llx at try %d\n",
287 currentRip, currentRsp, StackTrace->NumberOfTraces);
289 else if (StackTrace->NumberOfTraces == 0)
292 goto _start_searching;
297 currentModBase = pDriver->
BaseVa;
300 if (0 == currentModBase)
304 goto _cleanup_and_leave;
308 goto _start_searching;
321 if (pDriver != NULL &&
332 ERROR(
"[ERROR] Failed mapping driver base 0x%016llx to host: 0x%08x\n",
333 currentModBase, status);
336 goto _cleanup_and_leave;
340 else if (currentModBase == 0)
344 goto _cleanup_and_leave;
348 goto _start_searching;
356 (
DWORD)(currentRip - currentModBase),
364 (
DWORD)(currentRip - currentModBase),
370 ERROR(
"[ERROR] Failed getting runtime function for module 0x%016llx RIP 0x%016llx: 0x%08x\n",
371 currentModBase, currentRip, status);
372 goto _cleanup_and_leave;
381 DWORD ripOffset = (
DWORD)(currentRip - currentModBase);
388 if (ripOffset < runtimeFunction.BeginAddress || ripOffset > runtimeFunction.
EndAddress)
390 ripOffset = runtimeFunction.
EndAddress - beginRva;
394 ripOffset -= beginRva;
425 ERROR(
"[ERROR] IntPeParseUnwindData failed for driver 0x%016llx with RIP 0x%016llx and begining " 426 "RVA 0x%x: 0x%08x\n", currentModBase, currentRip, runtimeFunction.
BeginAddress, status);
427 goto _cleanup_and_leave;
433 newRsp = currentRsp + prologueSize;
447 if (!hasFramePointer && (interrupt || exception))
453 ERROR(
"[ERROR] Failed getting the return address form GVA 0x%016llx: 0x%08x",
454 newRsp + (exception ? 8 : 0), status);
455 goto _cleanup_and_leave;
462 retModuleBase = pDriver ? pDriver->
BaseVa : 0;
470 LOG(
"[STACK] NONHEUR : Found trap frame at stack address 0x%016llx with ret address 0x%016llx \n",
473 retAddrPtr = newRsp + ((exception) ? 8 : 0);
474 newRsp += (exception) ? (6 * 8) : (5 * 8);
477 goto _next_stack_frame;
481 fErrorCode = exception;
490 if (NULL != pStackBase)
502 goto _cleanup_and_leave;
512 if (hasFramePointer && (exception || interrupt))
515 BOOLEAN um, km, fRip, fCs, fSs, fRsp, fEflags;
516 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
521 if (*pTrapFrame > 0xffffffff)
523 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
524 fErrorCode = exception;
541 else if (*pTrapFrame > 0xffffffff && *pTrapFrame != 0xffffffffffffffff)
547 newRsp -= interrupt ? 8 : 0;
548 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
549 fErrorCode = exception;
556 retAddress = *pTrapFrame;
565 if (*pTrapFrame > 0xff)
567 newRsp -= interrupt ? 8 * 2 : 8;
568 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
569 fErrorCode = exception;
570 retAddrPtr = retAddress = 0;
575 if (km && (*pTrapFrame % 8 != 0))
577 newRsp -= interrupt ? 8 * 2 : 8;
578 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
579 fErrorCode = exception;
580 retAddrPtr = retAddress = 0;
591 if (*pTrapFrame == 0)
593 newRsp -= interrupt ? 8 * 3 : 8 * 2;
594 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
595 fErrorCode = exception;
596 retAddrPtr = retAddress = 0;
603 if ((*pTrapFrame > (1 << 22)) ||
604 (*pTrapFrame & (1 << 14)) ||
605 (*pTrapFrame & (1 << 5)) ||
606 (*pTrapFrame & (1 << 3)) ||
607 (0 == (*pTrapFrame & (1 << 1))))
609 newRsp -= interrupt ? 8 * 3 : 8 * 2;
610 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
611 fErrorCode = exception;
612 retAddrPtr = retAddress = 0;
623 if (0 != *pTrapFrame % 8)
625 newRsp -= interrupt ? 8 * 4 : 8 * 3;
626 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
627 fErrorCode = exception;
628 retAddrPtr = retAddress = 0;
635 newRsp -= interrupt ? 8 * 4 : 8 * 3;
636 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
637 fErrorCode = exception;
638 retAddrPtr = retAddress = 0;
643 newRsp -= interrupt ? 8 * 4 : 8 * 3;
644 um = km = fRip = fCs = fSs = fRsp = fEflags =
FALSE;
645 fErrorCode = exception;
646 retAddrPtr = retAddress = 0;
655 if (fErrorCode && fRip && fCs && fEflags && fRsp && fSs)
657 newRsp -= interrupt ? 5 * 8 : 4 * 8;
665 calledAddress = currentModBase + beginRva;
676 retAddress = *(
PQWORD)pStack;
694 if (calledAddress != 0 && currentModBase != 0 && beginRva != 0 &&
695 calledAddress != currentModBase + beginRva)
699 if (calledAddress < currentModBase + beginRva &&
702 goto _analyze_jmp_after_call_case;
705 else if (calledAddress != 0 &&
706 (calledAddress < currentRip - MAX_FUNC_LENGTH || calledAddress > currentRip))
710 goto _analyze_jmp_after_call_case;
715 goto _stack_trace_ok;
717 _analyze_jmp_after_call_case:
726 crip = calledAddress;
728 for (
DWORD i = 0; i < 100; i++)
731 QWORD calledFuncAddress = 0;
740 switch (instrux.Instruction)
746 if (ND_OP_MEM == instrux.Operands[0].Type)
750 if (instrux.Operands[0].Info.Memory.IsRipRel)
753 fetchAddress = crip + instrux.Length + instrux.Operands[0].Info.Memory.Disp;
755 else if (instrux.Operands[0].Info.Memory.HasDisp &&
756 !instrux.Operands[0].Info.Memory.HasBase &&
757 !instrux.Operands[0].Info.Memory.HasIndex)
759 fetchAddress = instrux.Operands[0].Info.Memory.Disp;
771 WARNING(
"[WARNING] Failed to get function address from 0x%016llx " 772 "(Call RIP 0x%016llx): 0x%08x\n", fetchAddress, crip, status);
773 calledFuncAddress = 0;
777 else if (ND_OP_REG == instrux.Operands[0].Type)
779 calledFuncAddress = 0;
793 calledFuncAddress = crip + instrux.Length + instrux.Operands[0].Info.RelativeOffset.Rel;
804 if (calledFuncAddress == 0 ||
805 (calledFuncAddress >= currentRip -
MAX_FUNC_LENGTH && calledFuncAddress <= currentRip))
808 calledAddress = calledFuncAddress;
809 goto _stack_trace_ok;
814 crip += instrux.Length;
842 goto _finish_searching_data_sec;
851 _finish_searching_data_sec:
856 if (!bIsCode && pDriver && calledAddress == 0)
861 retModuleBase = pDriver ? pDriver->
BaseVa : 0;
871 goto _next_stack_frame;
883 if (
INT_SUCCESS(status) && 0 == StackTrace->NumberOfTraces)
888 goto _cleanup_and_leave;
891 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = currentRip;
892 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = retAddrPtr;
893 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
894 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pDriver;
897 currentRip = retAddress;
900 if (calledAddress != currentModBase + beginRva)
915 if (calledAddress != 0)
917 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = calledAddress;
919 else if (beginRva > 0)
921 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = currentModBase + beginRva;
925 if (retModuleBase == currentModBase)
927 ripInsideSameModule =
TRUE;
931 ripInsideSameModule =
FALSE;
932 currentModBase = retModuleBase;
936 StackTrace->NumberOfTraces++;
939 currentRsp = newRsp + (interrupt ? 5 * 8 : exception ? 4 * 8 : 0);
941 if (retAddrPtr == currentRsp && 0 == retModuleBase && !interrupt && !exception)
951 ERROR(
"[ERROR] Didn't found a trace on the stack. RIP at 0x%016llx in module 0x%016llx\n",
952 currentRip, currentModBase);
956 goto _cleanup_and_leave;
964 }
while (StackTrace->NumberOfTraces < MaxTraces);
973 if (NULL != pModBaseMap)
1014 PDWORD pStack, pOrigStack;
1015 DWORD currentRip = 0;
1016 QWORD calledAddr = 0;
1025 if (0 == MaxNumberOfTraces)
1030 if (NULL == StackTrace || NULL == StackTrace->Traces)
1037 StackTrace->StartRip = Eip;
1038 StackTrace->NumberOfTraces = 0;
1039 StackTrace->Bits64 =
FALSE;
1042 pStack = pOrigStack = NULL;
1047 for (
DWORD frame = 0; frame < MaxNumberOfTraces; frame++)
1049 DWORD retAddress = 0;
1050 DWORD nextFrame = 0;
1058 if (NULL != pOrigStack)
1063 status =
IntVirtMemMap(ebp, remaining, cr3, 0, &pOrigStack);
1066 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp, status);
1067 goto _check_and_leave;
1070 pStack = pOrigStack;
1074 nextFrame = pStack[0];
1076 if (nextFrame % 4 != 0)
1078 WARNING(
"[WARNING] Unaligned stack: %08x\n", nextFrame);
1079 goto _check_and_leave;
1083 TRACE(
"[INFO] User-Mode stack: %08x\n", nextFrame);
1084 goto _check_and_leave;
1089 retAddress = pStack[1];
1096 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp + 4, status);
1097 goto _check_and_leave;
1112 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
1113 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1115 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = ebp + 4;
1116 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = calledAddr;
1117 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = currentRip;
1119 currentRip = retAddress;
1121 ++StackTrace->NumberOfTraces;
1123 if ((ebp &
PAGE_MASK) != (nextFrame & PAGE_MASK))
1130 DWORD diff = (ebp > nextFrame) ? (
DWORD)(ebp - nextFrame) : (
DWORD)(nextFrame - ebp);
1142 if (NULL != pOrigStack)
1149 if (0 == StackTrace->NumberOfTraces)
1214 PDWORD pStack, pOrigStack;
1218 cr3 = Registers->Cr3;
1219 ebp = Registers->Rbp;
1220 pStack = pOrigStack = NULL;
1223 for (
DWORD frame = 0; frame < MaxNumberOfTraces; frame++)
1225 DWORD retAddress = 0;
1226 DWORD nextFrame = 0;
1234 if (NULL != pOrigStack)
1239 status =
IntVirtMemMap(ebp, remaining, cr3, 0, &pOrigStack);
1242 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp, status);
1243 goto _check_and_leave;
1246 pStack = pOrigStack;
1250 nextFrame = pStack[0];
1252 if (nextFrame % 4 != 0)
1254 ERROR(
"[ERROR] Unaligned stack value %08x (current %08llx)\n", nextFrame, ebp);
1255 goto _check_and_leave;
1259 TRACE(
"[INFO] Kernel-Mode stack %08x (current %08llx)\n", nextFrame, ebp);
1260 goto _check_and_leave;
1262 else if (0 == nextFrame)
1265 goto _check_and_leave;
1268 if (nextFrame < ebp)
1270 ERROR(
"[ERROR] Return stack frame %x is smaller than current %llx\n", nextFrame, ebp);
1271 goto _check_and_leave;
1276 retAddress = pStack[1];
1283 LOG(
"[ERROR] Got to the end of the stack at 0x%016llx: 0x%08x\n", ebp + 4, status);
1284 goto _check_and_leave;
1291 WARNING(
"[WARNING] Failed getting the dll base for RIP %08x\n", retAddress);
1292 goto _check_and_leave;
1307 goto _save_and_next;
1312 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = retAddress;
1313 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1315 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = ebp + 4;
1316 StackTrace->Traces[StackTrace->NumberOfTraces].CalledAddress = 0;
1317 StackTrace->Traces[StackTrace->NumberOfTraces].CurrentRip = 0;
1319 ++StackTrace->NumberOfTraces;
1321 if ((ebp &
PAGE_MASK) != (nextFrame & PAGE_MASK))
1346 if (0 == StackTrace->NumberOfTraces)
1385 stackFrame = Registers->Rsp;
1387 for (
DWORD j = 0; j < pagesToParse; j++)
1391 status =
IntVirtMemMap(stackFrame, remaining, Registers->Cr3, 0, &pStack);
1394 ERROR(
"[ERROR] Cannot get a stack at address %llx (start RSP %llx): 0x%08x\n",
1395 stackFrame, Registers->Rsp, status);
1400 for (
DWORD i = 0; i < remaining; i += 8)
1406 ret = *(
QWORD *)(pStack + i);
1432 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnAddress = ret;
1433 StackTrace->Traces[StackTrace->NumberOfTraces].ReturnModule = pMod;
1434 StackTrace->Traces[StackTrace->NumberOfTraces].RetAddrPointer = stackFrame + i;
1436 if (++StackTrace->NumberOfTraces >= MaxNumberOfTraces)
1444 if (StackTrace->NumberOfTraces >= MaxNumberOfTraces)
1449 stackFrame += remaining;
1452 if (StackTrace->NumberOfTraces == 0)
1495 QWORD tibBase, stackBase, stackLimit;
1497 VAD stackVad = { 0 };
1500 tibBase = stackBase = stackLimit = 0;
1518 LOG(
"TIB is not present! Will inject #PF for %llx!\n", tibBase);
1526 NULL, 0, NULL, NULL, NULL);
1529 ERROR(
"[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1538 ERROR(
"[ERROR] IntWinThrGetCurrentStackBaseAndLimit failed: 0x%08x\n", status);
1545 ERROR(
"[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
1552 ERROR(
"[ERROR] IntWinVadFetchByRange failed: 0x%08x\n", status);
1581 ERROR(
"[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1585 foundSwappedOut =
TRUE;
1589 ERROR(
"[ERROR] IntTranslateVirtualAddress failed: 0x%08x\n", status);
1594 if (foundSwappedOut)
1623 QWORD remaining = 0;
1625 if (NULL == Registers)
1630 if (NULL == Process)
1635 if (0 == MaxNumberOfTraces)
1646 StackTrace->StartRip = Registers->Rip;
1647 StackTrace->NumberOfTraces = 0;
1652 TRACE(
"[INFO] IntWinStackHandleUserStackPagedOut failed: 0x%08x\n", status);
1659 ERROR(
"[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
1665 ERROR(
"[ERROR] Unsupported CS type: %d\n", csType);
1671 QWORD stackFrame = Registers->Rbp;
1673 StackTrace->Bits64 =
FALSE;
1675 if ((stackFrame > Registers->Rsp &&
1676 stackFrame - Registers->Rsp > 3 *
PAGE_SIZE) ||
1677 (stackFrame < Registers->Rsp &&
1678 Registers->Rsp - stackFrame > 3 *
PAGE_SIZE))
1683 DWORD retAddress = 0;
1686 stackFrame = Registers->Rsp;
1691 for (
size_t stackIndex = 0; stackIndex <
MIN(8u, remaining / 4); stackIndex++)
1693 status =
IntVirtMemRead(stackFrame + stackIndex * 4, 4, Registers->Cr3, &retAddress, NULL);
1696 ERROR(
"[ERROR] RSP 0x%016llx is not present: %08x\n", stackFrame + stackIndex * 4, status);
1712 ERROR(
"[ERROR] DLL base was not found on stack 0x%016llx\n", stackFrame);
1716 StackTrace->NumberOfTraces = 1;
1718 StackTrace->Traces[0].ReturnAddress = retAddress;
1719 StackTrace->Traces[0].ReturnModule = pMod;
1720 StackTrace->Traces[0].RetAddrPointer = stackFrame;
1734 StackTrace->Bits64 =
TRUE;
1776 if (NULL == IsPivoted)
1790 alignSize =
sizeof(
DWORD);
1798 ERROR(
"[ERROR] Unrecognized CS value: 0x%08x\n", SegCs);
1809 UserRsp % alignSize != 0)
1818 ERROR(
"[ERROR] IntWinThrGetCurrentTib failed: 0x%08x\n", status);
1834 WARNING(
"[WARNING] IntWinThrGetUmStackBaseAndLimitFromTib failed: 0x%08x\n", status);
1838 ERROR(
"[ERROR] IntWinThrGetUmStackBaseAndLimitFromTib failed: 0x%08x\n", status);
1844 DpiExtraInfo->DpiPivotedStackExtraInfo.Wow64StackBase = stackBase;
1845 DpiExtraInfo->DpiPivotedStackExtraInfo.Wow64StackLimit = stackLimit;
1849 DpiExtraInfo->DpiPivotedStackExtraInfo.StackBase = stackBase;
1850 DpiExtraInfo->DpiPivotedStackExtraInfo.StackLimit = stackLimit;
1853 if (UserRsp < stackLimit || UserRsp > stackBase)
1855 WARNING(
"[WARNING] UM stack (0x%016llx) outside of the limit and base interval " 1856 "from the current TIB [0x%016llx, 0x%016llx].\n", UserRsp, stackLimit, stackBase);
1888 QWORD stackPointerGVA;
1891 stackPointer = NULL;
1892 stackPointerGVA = 0;
1900 if (NULL == TrapFrame)
1911 ERROR(
"[ERROR] IntVirtMemMap failed from GVA 0x%016llx: 0x%08x\n", stackPointerGVA, status);
1923 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = stackPointerGVA + i;
1925 TRACE(
"[INFO] TrapFrame found: 0x%016llx\n", stackPointerGVA + i);
1965 QWORD stackPointerGVA;
1969 stackPointer = NULL;
1970 stackPointerGVA = 0;
1978 if (NULL == TrapFrame)
1989 ERROR(
"[ERROR] IntVirtMemMap failed from GVA 0x%016llx: 0x%08x\n", stackPointerGVA, status);
2001 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = stackPointerGVA + i;
2003 TRACE(
"[INFO] TrapFrame found: 0x%016llx\n", stackPointerGVA + i);
2042 QWORD currentThread = 0;
2044 if (NULL == UserRsp)
2060 ERROR(
"[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
2066 QWORD trapFrameAddress = 0;
2067 QWORD stackBase = 0;
2073 ERROR(
"[ERROR] Failed getting the TrapFrame from Ethread 0x%016llx: 0x%08x\n", currentThread, status);
2085 ERROR(
"[ERROR] Failed getting the trap frame from CurrentThread 0x%016llx: 0x%08x\n",
2086 currentThread, status);
2090 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
2100 ERROR(
"[ERROR] Failed getting the TrapFrame from CurrentThread 0x%016llx: 0x%08x\n",
2101 currentThread, status);
2105 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
2110 WARNING(
"[WARNING] Specially crafted TrapFrame somehow: 0x%016llx\n", trapFrameAddress);
2121 ERROR(
"[ERROR] Failed getting the StackBase from CurrentThread 0x%016llx: 0x%08x\n",
2122 currentThread, status);
2129 ERROR(
"[ERROR] Failed getting a TrapFrame: 0x%08x.\n", status);
2134 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentStack = trapFrame.
Rsp;
2136 *UserRsp = trapFrame.
Rsp;
2137 *SegCs = trapFrame.
SegCs;
2142 DWORD trapFrameAddress = 0;
2143 DWORD stackBase = 0;
2148 ERROR(
"[ERROR] Failed getting the TrapFrame from Ethread 0x%016llx: 0x%08x\n", currentThread, status);
2158 ERROR(
"[ERROR] Failed reading the TrapFrame from CurrentThread 0x%016llx: 0x%08x\n",
2159 currentThread, status);
2165 WARNING(
"[WARNING] Current TrapFrame 0x%08x has a kernel mode Eip: 0x%08x \n",
2166 trapFrameAddress, trapFrame.
Eip);
2171 DpiExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress = trapFrameAddress;
2180 ERROR(
"[ERROR] Failed getting the StackBase from CurrentThread 0x%016llx: 0x%08x\n",
2181 currentThread, status);
2188 ERROR(
"[ERROR] Failed getting a TrapFrame: 0x%08x.\n", status);
2193 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentStack = trapFrame.
HardwareEsp;
2223 QWORD wow64SaveArea = 0;
2224 QWORD userWow64Rsp = 0;
2230 ERROR(
"[ERROR] IntWinThrGetCurrentTib failed: 0x%08x\n", status);
2239 INFO(
"[INFO] IntVirtMemRead failed: 0x%08x, the page 0x%016llx seems to be swapped out...\n", status,
2245 ERROR(
"[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
2250 &userWow64Rsp, NULL);
2253 INFO(
"[INFO] IntVirtMemRead failed: 0x%08x, the page 0x%016llx seems to be swapped out...\n", status,
2254 wow64SaveArea +
WIN_UM_FIELD(Teb, Wow64StackInSaveArea));
2259 ERROR(
"[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
2263 DpiExtraInfo->DpiPivotedStackExtraInfo.CurrentWow64Stack = userWow64Rsp;
2267 &Process->CreationInfo.ParentHasPivotedStack);
2270 ERROR(
"[ERROR] IntWinStackUserCheckIsPivoted failed: 0x%08x.\n", status);
2273 else if (Process->CreationInfo.ParentHasPivotedStack)
2275 WARNING(
"[WARNING] Process 0x%016llx created with WoW64 pivoted stack.\n", Process->EprocessAddress);
2284 _In_ void *TrapFrame
2299 if ((trapFrame->
EFlags >= (1 << 22)) ||
2300 (trapFrame->
EFlags & (1 << 1)) == 0 ||
2301 (trapFrame->
EFlags & (1 << 3)) != 0 ||
2302 (trapFrame->
EFlags & (1 << 5)) != 0 ||
2303 (trapFrame->
EFlags & (1 << 15)) != 0)
2315 if (trapFrame->
Rsp % 8 != 0 ||
2317 trapFrame->
Rsp == 0 ||
2325 trapFrame->
Rip == 0 ||
2336 if ((trapFrame->
EFlags >= (1 << 22)) ||
2337 (trapFrame->
EFlags & (1 << 1)) == 0 ||
2338 (trapFrame->
EFlags & (1 << 3)) != 0 ||
2339 (trapFrame->
EFlags & (1 << 5)) != 0 ||
2340 (trapFrame->
EFlags & (1 << 15)) != 0)
2362 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...
INTSTATUS IntWinThrGetCurrentStackBaseAndLimit(QWORD *TibBase, QWORD *StackBase, QWORD *StackLimit)
Obtains the stack base, stack limit and TIB address of the current thread.
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.
INTSTATUS IntSwapMemReadData(QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle)
Reads a region of guest virtual memory, and calls the indicated callback when all the data is availab...
#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.
#define SWAPMEM_OPT_NO_DUPS
If set, will make sure that a single PF is scheduled for this page.
Structure that describes a stack trace element.
PBYTE MzPeHeaders
The driver`s MZ/PE headers (cached internally).
#define INT_STATUS_NOT_NEEDED_HINT
INTSTATUS IntKernVirtMemFetchWordSize(QWORD GuestVirtualAddress, void *Data)
Reads a guest pointer from the guest kernel memory.
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.
static INTSTATUS IntWinStackTraceGetUser64(PIG_ARCH_REGS Registers, PWIN_PROCESS_OBJECT Process, DWORD MaxNumberOfTraces, QWORD Remaining, STACK_TRACE *StackTrace)
Get the user stack trace of a 64 bit windows process.
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.
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
static INTSTATUS IntWinStackHandleUserStackPagedOut(WIN_PROCESS_OBJECT *Process, QWORD *Remaining)
Handles the case when the stack is needed but is swapped out.
#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.
INTSTATUS IntWinVadFetchByRange(QWORD VadRoot, QWORD StartPage, QWORD EndPage, VAD *Vad)
Fetches and returns a VAD object containing the range represented by [StartPage, EndPage].
DWORD KernelBufferSize
The size of the KernelBuffer.
#define INT_STATUS_INVALID_DATA_VALUE
#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.
#define INT_STATUS_STACK_SWAPPED_OUT
Indicates that the stack was needed in order to match the exceptions, but it is swapped out...
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.
A representation of a Windows VAD structure.
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.
#define SWAPMEM_OPT_UM_FAULT
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory...
This structure describes a running process inside the guest.
#define INT_STATUS_INVALID_PARAMETER_3