1 static partial class AntiDebugAntinet { 2 3 [DllImport("kernel32", CharSet = CharSet.Auto)] 4 private static extern uint GetCurrentProcessId(); 5 6 [DllImport("kernel32")] 7 private static extern bool SetEvent(IntPtr hEvent); 8 9 /// <摘要> 10 ///必须调用以初始化反托管调试器代码 11 /// </ summary> 12 /// <returns> <c> true </ c>如果成功,则<c> false </ c>否则</ returns> 13 private static unsafe bool InitializeAntiDebugger() { 14 Info info = GetInfo(); 15 IntPtr pDebuggerRCThread = FindDebuggerRCThreadAddress(info); 16 if (pDebuggerRCThread == IntPtr.Zero) 17 return false; 18 19 //这不是必需的,但至少会阻止调试器附加。 20 //即使它们确实附加了,自调试器以来也不会收到任何消息 21 //线程已退出。 尝试附加的用户将收到一个 22 //“由于版本不同等原因无法附加”消息。 这不会停止 23 //已附加的调试器。 杀死调试器线程将。 24 var pDebuggerIPCControlBlock = (byte*)*(IntPtr*)((byte*)pDebuggerRCThread + info.DebuggerRCThread_pDebuggerIPCControlBlock); 25 if (Environment.Version.Major == 2) 26 pDebuggerIPCControlBlock = (byte*)*(IntPtr*)pDebuggerIPCControlBlock; 27 //将大小字段设置为0。mscordbi!CordbProcess :: VerifyControlBlock()将失败 28 //当检测到未知大小时。 29 *(uint *)pDebuggerIPCControlBlock = 0; 30 31 //信号调试器线程退出 32 *((byte*)pDebuggerRCThread + info.DebuggerRCThread_shouldKeepLooping) = 0; 33 IntPtr hEvent = *(IntPtr*)((byte*)pDebuggerRCThread + info.DebuggerRCThread_hEvent1); 34 SetEvent(hEvent); 35 36 return true; 37 } 38 39 /// <summary> 40 /// Returns the correct <see cref="Info" /> instance 41 /// </summary> 42 private static Info GetInfo() { 43 switch (Environment.Version.Major) { 44 case 2: 45 return IntPtr.Size == 4 ? Infos.info_CLR20_x86 : Infos.info_CLR20_x64; 46 case 4: 47 if (Environment.Version.Revision <= 17020) 48 return IntPtr.Size == 4 ? Infos.info_CLR40_x86_1 : Infos.info_CLR40_x64; 49 return IntPtr.Size == 4 ? Infos.info_CLR40_x86_2 : Infos.info_CLR40_x64; 50 default: 51 goto case 4; // Assume CLR 4.0 52 } 53 } 54 55 /// <summary> 56 /// Tries to find the address of the <c>DebuggerRCThread</c> instance in memory 57 /// </summary> 58 /// <param name="info">The debugger info we need</param> 59 [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req‘d on .NET 4.0 60 private static unsafe IntPtr FindDebuggerRCThreadAddress(Info info) { 61 uint pid = GetCurrentProcessId(); 62 63 try { 64 PEInfo peInfo = PEInfo.GetCLR(); 65 if (peInfo == null) 66 return IntPtr.Zero; 67 68 IntPtr sectionAddr; 69 uint sectionSize; 70 if (!peInfo.FindSection(".data", out sectionAddr, out sectionSize)) 71 return IntPtr.Zero; 72 73 // Try to find the Debugger instance location in the data section 74 var p = (byte*)sectionAddr; 75 byte* end = (byte*)sectionAddr + sectionSize; 76 for (; p + IntPtr.Size <= end; p += IntPtr.Size) { 77 IntPtr pDebugger = *(IntPtr*)p; 78 if (pDebugger == IntPtr.Zero) 79 continue; 80 81 try { 82 // All allocations are pointer-size aligned 83 if (!PEInfo.IsAlignedPointer(pDebugger)) 84 continue; 85 86 // Make sure pid is correct 87 uint pid2 = *(uint*)((byte*)pDebugger + info.Debugger_pid); 88 if (pid != pid2) 89 continue; 90 91 IntPtr pDebuggerRCThread = *(IntPtr*)((byte*)pDebugger + info.Debugger_pDebuggerRCThread); 92 93 // All allocations are pointer-size aligned 94 if (!PEInfo.IsAlignedPointer(pDebuggerRCThread)) 95 continue; 96 97 // Make sure it points back to Debugger 98 IntPtr pDebugger2 = *(IntPtr*)((byte*)pDebuggerRCThread + info.DebuggerRCThread_pDebugger); 99 if (pDebugger != pDebugger2) 100 continue; 101 102 return pDebuggerRCThread; 103 } 104 catch { } 105 } 106 } 107 catch { } 108 109 return IntPtr.Zero; 110 } 111 112 private class Info { 113 114 /// <summary> 115 /// Offset in <c>DebuggerRCThread</c> of event to signal to wake it up. 116 /// See <c>Debugger::StopDebugger()</c> or one of the first methods it calls. 117 /// </summary> 118 public int DebuggerRCThread_hEvent1; 119 120 /// <summary> 121 /// Offset in <c>DebuggerRCThread</c> of pointer to <c>Debugger</c>. 122 /// See <c>DebuggerRCThread::DebuggerRCThread()</c>. 123 /// </summary> 124 public int DebuggerRCThread_pDebugger; 125 126 /// <summary> 127 /// Offset in <c>DebuggerRCThread</c> of pointer to <c>DebuggerIPCControlBlock</c>. 128 /// See <c>DebuggerRCThread::Start() after it creates the thread.</c>. 129 /// </summary> 130 public int DebuggerRCThread_pDebuggerIPCControlBlock; 131 132 /// <summary> 133 /// Offset in <c>DebuggerRCThread</c> of keep-looping boolean (1 byte). 134 /// See <c>Debugger::StopDebugger()</c> or one of the first methods it calls. 135 /// </summary> 136 public int DebuggerRCThread_shouldKeepLooping; 137 138 /// <summary> 139 /// Offset in <c>Debugger</c> of pointer to <c>DebuggerRCThread</c>. 140 /// See <c>Debugger::Startup()</c> (after creating DebuggerRCThread). 141 /// </summary> 142 public int Debugger_pDebuggerRCThread; 143 144 /// <summary> 145 /// Offset in <c>Debugger</c> of the <c>pid</c>. 146 /// See <c>Debugger::Debugger()</c>. 147 /// </summary> 148 public int Debugger_pid; 149 150 } 151 152 private static class Infos { 153 154 /// <summary> 155 /// CLR 2.0 x86 offsets 156 /// </summary> 157 public static readonly Info info_CLR20_x86 = new Info { 158 Debugger_pDebuggerRCThread = 4, 159 Debugger_pid = 8, 160 DebuggerRCThread_pDebugger = 0x30, 161 DebuggerRCThread_pDebuggerIPCControlBlock = 0x34, 162 DebuggerRCThread_shouldKeepLooping = 0x3C, 163 DebuggerRCThread_hEvent1 = 0x40, 164 }; 165 166 /// <summary> 167 /// CLR 2.0 x64 offsets 168 /// </summary> 169 public static readonly Info info_CLR20_x64 = new Info { 170 Debugger_pDebuggerRCThread = 8, 171 Debugger_pid = 0x10, 172 DebuggerRCThread_pDebugger = 0x58, 173 DebuggerRCThread_pDebuggerIPCControlBlock = 0x60, 174 DebuggerRCThread_shouldKeepLooping = 0x70, 175 DebuggerRCThread_hEvent1 = 0x78, 176 }; 177 178 /// <summary> 179 /// CLR 4.0 x86 offsets 180 /// </summary> 181 public static readonly Info info_CLR40_x86_1 = new Info { 182 Debugger_pDebuggerRCThread = 8, 183 Debugger_pid = 0xC, 184 DebuggerRCThread_pDebugger = 0x34, 185 DebuggerRCThread_pDebuggerIPCControlBlock = 0x38, 186 DebuggerRCThread_shouldKeepLooping = 0x40, 187 DebuggerRCThread_hEvent1 = 0x44, 188 }; 189 190 /// <summary> 191 /// CLR 4.0 x86 offsets (rev >= 17379 (.NET 4.5 Beta, but not .NET 4.5 Dev Preview)) 192 /// </summary> 193 public static readonly Info info_CLR40_x86_2 = new Info { 194 Debugger_pDebuggerRCThread = 8, 195 Debugger_pid = 0xC, 196 DebuggerRCThread_pDebugger = 0x30, 197 DebuggerRCThread_pDebuggerIPCControlBlock = 0x34, 198 DebuggerRCThread_shouldKeepLooping = 0x3C, 199 DebuggerRCThread_hEvent1 = 0x40, 200 }; 201 202 /// <summary> 203 /// CLR 4.0 x64 offsets (this is the same in all CLR 4.0 versions, even in .NET 4.5 RTM) 204 /// </summary> 205 public static readonly Info info_CLR40_x64 = new Info { 206 Debugger_pDebuggerRCThread = 0x10, 207 Debugger_pid = 0x18, 208 DebuggerRCThread_pDebugger = 0x58, 209 DebuggerRCThread_pDebuggerIPCControlBlock = 0x60, 210 DebuggerRCThread_shouldKeepLooping = 0x70, 211 DebuggerRCThread_hEvent1 = 0x78, 212 }; 213 214 } 215 216 } 217 }