[SecurityCritical] // Req'd on .NET 4.0 private static unsafe IntPtr FindTimeOutOptionAddress() { try { var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(IntPtr.Zero); } IntPtr sectionAddr; uint sectionSize; if (!peInfo.FindSection(".rdata", out sectionAddr, out sectionSize) && !peInfo.FindSection(".text", out sectionAddr, out sectionSize)) { return(IntPtr.Zero); } var p = (byte *)sectionAddr; var end = (byte *)sectionAddr + sectionSize; for (; p < end; p++) { try { var name = *(char **)(p + ConfigDWORDInfo_name); if (!PEInfo.IsAligned(new IntPtr(name), 2)) { continue; } if (!peInfo.IsValidImageAddress(name)) { continue; } if (!Equals(name, ProfAPIMaxWaitForTriggerMs_name)) { continue; } return(new IntPtr(p)); } catch { } } } catch { } return(IntPtr.Zero); }
[HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 private unsafe bool FindProfilerControlBlock() { // Record each hit here and pick the one with the most hits var addrCounts = new Dictionary <IntPtr, int>(); try { var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(false); } if (!peInfo.FindSection(".text", out IntPtr sectionAddr, out uint sectionSize)) { return(false); } const int MAX_COUNTS = 50; byte * p = (byte *)sectionAddr; byte * end = (byte *)sectionAddr + sectionSize; for (; p < end; p++) { IntPtr addr; // A1 xx xx xx xx mov eax,[mem] // 83 F8 04 cmp eax,4 if (*p == 0xA1 && p[5] == 0x83 && p[6] == 0xF8 && p[7] == 0x04) { if (IntPtr.Size == 4) { addr = new IntPtr((void *)*(uint *)(p + 1)); } else { addr = new IntPtr(p + 5 + *(int *)(p + 1)); } } // 8B 05 xx xx xx xx mov eax,[mem] // 83 F8 04 cmp eax,4 else if (*p == 0x8B && p[1] == 0x05 && p[6] == 0x83 && p[7] == 0xF8 && p[8] == 0x04) { if (IntPtr.Size == 4) { addr = new IntPtr((void *)*(uint *)(p + 2)); } else { addr = new IntPtr(p + 6 + *(int *)(p + 2)); } } // 83 3D XX XX XX XX 04 cmp dword ptr [mem],4 else if (*p == 0x83 && p[1] == 0x3D && p[6] == 0x04) { if (IntPtr.Size == 4) { addr = new IntPtr((void *)*(uint *)(p + 2)); } else { addr = new IntPtr(p + 7 + *(int *)(p + 2)); } } else { continue; } if (!PEInfo.IsAligned(addr, 4)) { continue; } if (!peInfo.IsValidImageAddress(addr, 4)) { continue; } // Valid values are 0-4. 4 being attached. try { if (*(uint *)addr > 4) { continue; } *(uint *)addr = *(uint *)addr; } catch { continue; } addrCounts.TryGetValue(addr, out int count); count++; addrCounts[addr] = count; if (count >= MAX_COUNTS) { break; } } } catch { } IntPtr foundAddr = GetMax(addrCounts, 5); if (foundAddr == IntPtr.Zero) { return(false); } this.profilerControlBlock = new IntPtr((byte *)foundAddr - (IntPtr.Size + 4)); return(true); }
[HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 private unsafe IntPtr FindAttacherThreadProc() { try { var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(IntPtr.Zero); } if (!peInfo.FindSection(".text", out IntPtr sectionAddr, out uint sectionSize)) { return(IntPtr.Zero); } byte *p = (byte *)sectionAddr; byte *start = p; byte *end = (byte *)sectionAddr + sectionSize; if (IntPtr.Size == 4) { for (; p < end; p++) { // Find this code: // 50+r push reg // 50+r push reg // 50+r push reg // 68 XX XX XX XX push offset ThreadProc // 50+r push reg // 50+r push reg // FF 15 XX XX XX XX call dword ptr [mem] // CreateThread() byte push = *p; if (push < 0x50 || push > 0x57) { continue; } if (p[1] != push || p[2] != push || p[8] != push || p[9] != push) { continue; } if (p[3] != 0x68) { continue; } if (p[10] != 0xFF || p[11] != 0x15) { continue; } var threadProc = new IntPtr((void *)*(uint *)(p + 4)); if (!CheckThreadProc(start, end, threadProc)) { continue; } return(threadProc); } } else { for (; p < end; p++) { // Find this code: // 45 33 C9 xor r9d,r9d // 4C 8D 05 XX XX XX XX lea r8,ThreadProc // 33 D2 xor edx,edx // 33 C9 xor ecx,ecx // FF 15 XX XX XX XX call dword ptr [mem] // CreateThread() if (*p != 0x45 && p[1] != 0x33 && p[2] != 0xC9) { continue; } if (p[3] != 0x4C && p[4] != 0x8D && p[5] != 0x05) { continue; } if (p[10] != 0x33 && p[11] != 0xD2) { continue; } if (p[12] != 0x33 && p[13] != 0xC9) { continue; } if (p[14] != 0xFF && p[15] != 0x15) { continue; } var threadProc = new IntPtr(p + 10 + *(int *)(p + 6)); if (!CheckThreadProc(start, end, threadProc)) { continue; } return(threadProc); } } } catch { } return(IntPtr.Zero); }
[HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 private static unsafe IntPtr FindThreadingModeAddress() { try { // Find this code in clr!ProfilingAPIAttachServer::ExecutePipeRequests() // 83 3D XX XX XX XX 02 cmp dword ptr [mem],2 // 74 / 0F 84 XX je there // 83 E8+r 00 / 85 C0+rr sub reg,0 / test reg,reg // 74 / 0F 84 XX je there // 48+r / FF C8+r dec reg // 74 / 0F 84 XX je there // 48+r / FF C8+r dec reg var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(IntPtr.Zero); } if (!peInfo.FindSection(".text", out IntPtr sectionAddr, out uint sectionSize)) { return(IntPtr.Zero); } byte *ptr = (byte *)sectionAddr; byte *end = (byte *)sectionAddr + sectionSize; for (; ptr < end; ptr++) { IntPtr addr; try { // 83 3D XX XX XX XX 02 cmp dword ptr [mem],2 byte *p = ptr; if (*p != 0x83 || p[1] != 0x3D || p[6] != 2) { continue; } if (IntPtr.Size == 4) { addr = new IntPtr((void *)*(uint *)(p + 2)); } else { addr = new IntPtr(p + 7 + *(int *)(p + 2)); } if (!PEInfo.IsAligned(addr, 4)) { continue; } if (!peInfo.IsValidImageAddress(addr)) { continue; } p += 7; // 1 = normal lazy thread creation. 2 = thread is always present if (*(uint *)addr < 1 || *(uint *)addr > 2) { continue; } *(uint *)addr = *(uint *)addr; // 74 / 0F 84 XX je there if (!NextJz(ref p)) { continue; } // 83 E8+r 00 / 85 C0+rr sub reg,0 / test reg,reg SkipRex(ref p); if (*p == 0x83 && p[2] == 0) { if ((uint)(p[1] - 0xE8) > 7) { continue; } p += 3; } else if (*p == 0x85) { int reg = (p[1] >> 3) & 7; int rm = p[1] & 7; if (reg != rm) { continue; } p += 2; } else { continue; } // 74 / 0F 84 XX je there if (!NextJz(ref p)) { continue; } // 48+r / FF C8+r dec reg if (!SkipDecReg(ref p)) { continue; } // 74 / 0F 84 XX je there if (!NextJz(ref p)) { continue; } // 48+r / FF C8+r dec reg if (!SkipDecReg(ref p)) { continue; } return(addr); } catch { } } } catch { } return(IntPtr.Zero); }
/// <summary> /// This code tries to find the CLR 2.0 profiler status flag. It searches the whole /// .text section for a certain instruction. /// </summary> /// <returns><c>true</c> if it was found, <c>false</c> otherwise</returns> private unsafe bool FindProfilerStatus() { // Record each hit here and pick the one with the most hits var addrCounts = new Dictionary <IntPtr, int>(); try { var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(false); } if (!peInfo.FindSection(".text", out IntPtr sectionAddr, out uint sectionSize)) { return(false); } const int MAX_COUNTS = 50; byte * p = (byte *)sectionAddr; byte * end = (byte *)sectionAddr + sectionSize; for (; p < end; p++) { IntPtr addr; // F6 05 XX XX XX XX 06 test byte ptr [mem],6 if (*p == 0xF6 && p[1] == 0x05 && p[6] == 0x06) { if (IntPtr.Size == 4) { addr = new IntPtr((void *)*(uint *)(p + 2)); } else { addr = new IntPtr(p + 7 + *(int *)(p + 2)); } } else { continue; } if (!PEInfo.IsAligned(addr, 4)) { continue; } if (!peInfo.IsValidImageAddress(addr, 4)) { continue; } try { *(uint *)addr = *(uint *)addr; } catch { continue; } addrCounts.TryGetValue(addr, out int count); count++; addrCounts[addr] = count; if (count >= MAX_COUNTS) { break; } } } catch { } IntPtr foundAddr = GetMax(addrCounts, 5); if (foundAddr == IntPtr.Zero) { return(false); } this.profilerStatusFlag = foundAddr; return(true); }
[HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 private static unsafe IntPtr FindDebuggerRCThreadAddress(Info info) { uint pid = GetCurrentProcessId(); try { var peInfo = PEInfo.GetCLR(); if (peInfo == null) { return(IntPtr.Zero); } if (!peInfo.FindSection(".data", out IntPtr sectionAddr, out uint sectionSize)) { return(IntPtr.Zero); } // Try to find the Debugger instance location in the data section byte *p = (byte *)sectionAddr; byte *end = (byte *)sectionAddr + sectionSize; for (; p + IntPtr.Size <= end; p += IntPtr.Size) { IntPtr pDebugger = *(IntPtr *)p; if (pDebugger == IntPtr.Zero) { continue; } try { // All allocations are pointer-size aligned if (!PEInfo.IsAlignedPointer(pDebugger)) { continue; } // Make sure pid is correct uint pid2 = *(uint *)((byte *)pDebugger + info.Debugger_pid); if (pid != pid2) { continue; } IntPtr pDebuggerRCThread = *(IntPtr *)((byte *)pDebugger + info.Debugger_pDebuggerRCThread); // All allocations are pointer-size aligned if (!PEInfo.IsAlignedPointer(pDebuggerRCThread)) { continue; } // Make sure it points back to Debugger IntPtr pDebugger2 = *(IntPtr *)((byte *)pDebuggerRCThread + info.DebuggerRCThread_pDebugger); if (pDebugger != pDebugger2) { continue; } return(pDebuggerRCThread); } catch { } } } catch { } return(IntPtr.Zero); }