| 35 | } |
| 36 | |
| 37 | void GetCallStack(std::string& callStack) { |
| 38 | CONTEXT context; |
| 39 | RtlCaptureContext(&context); |
| 40 | |
| 41 | DWORD64 imageBase; |
| 42 | DWORD64 controlPc = context.Rip; //EIP |
| 43 | DWORD64 frameBase = context.Rbp; //EBP |
| 44 | |
| 45 | HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); |
| 46 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); |
| 47 | MODULEINFO kernel32Info = { 0 }; |
| 48 | MODULEINFO ntdllInfo = { 0 }; |
| 49 | GetModuleInformation(GetCurrentProcess(), hKernel32, &kernel32Info, sizeof(kernel32Info)); |
| 50 | GetModuleInformation(GetCurrentProcess(), hNtdll, &ntdllInfo, sizeof(ntdllInfo)); |
| 51 | |
| 52 | |
| 53 | std::ostringstream oss; |
| 54 | |
| 55 | oss << "�Ѵ���QQ�ļ�У���˳�����, һ��������п�����LLQQNT���/������µ�����\n���κ������뵽Repo��issue, ������Ľ�ͼ\nCallStack:\n"; |
| 56 | |
| 57 | /*Skip self*/ |
| 58 | UNWIND_HISTORY_TABLE historyTable; |
| 59 | ZeroMemory(&historyTable, sizeof(UNWIND_HISTORY_TABLE)); |
| 60 | PRUNTIME_FUNCTION pFunction = RtlLookupFunctionEntry(controlPc, &imageBase, &historyTable); |
| 61 | if (pFunction != NULL) { |
| 62 | PVOID handlerData; |
| 63 | ULONG64 establisherFrame; |
| 64 | RtlVirtualUnwind(UNW_FLAG_NHANDLER, imageBase, controlPc, pFunction, &context, &handlerData, &establisherFrame, NULL); |
| 65 | controlPc = context.Rip; |
| 66 | frameBase = context.Rbp; |
| 67 | } |
| 68 | /*---------*/ |
| 69 | |
| 70 | for (int i = 0; i < 16; ++i) { |
| 71 | if (controlPc == 0) { |
| 72 | break; |
| 73 | } |
| 74 | |
| 75 | if ((controlPc >= (DWORD64)hKernel32 && controlPc < (DWORD64)hKernel32 + kernel32Info.SizeOfImage)) |
| 76 | { |
| 77 | oss << "in module kernel32.dll | Maybe BaseThreadInitThunk\n"; |
| 78 | } |
| 79 | else if ((controlPc >= (DWORD64)hNtdll && controlPc < (DWORD64)hNtdll + ntdllInfo.SizeOfImage)) |
| 80 | { |
| 81 | oss << "in module ntdll.dll | Maybe RtlUserThreadStart\n"; |
| 82 | } |
| 83 | |
| 84 | oss << "Address: 0x" << std::hex << controlPc << std::endl; |
| 85 | |
| 86 | BYTE buffer[32]; |
| 87 | SIZE_T bytesRead; |
| 88 | if (ReadProcessMemory(GetCurrentProcess(), (LPCVOID)controlPc, buffer, sizeof(buffer), &bytesRead)) |
| 89 | { |
| 90 | oss << "Data: "; |
| 91 | for (SIZE_T j = 0; j < bytesRead; ++j) { |
| 92 | oss << std::setw(2) << std::setfill('0') << std::hex << (int)buffer[j] << " "; |
| 93 | } |
| 94 | oss << std::endl; |