· 4 years ago · Jun 21, 2021, 08:56 PM
1/*
2Antidebugging Breakpoints IDC script for IDA PRO by JSacco v0.2
3How to use? Open IDA Pro, press shift+F2 paste the code and run.
4Last modification date: 2021216
5*/
6#include <idc.idc>
7
8static main()
9{
10 // Trace everything in the cosmos? ( Not recommended )
11 auto trace_kernel32 = 1; // (1) Enabled
12 auto trace_ntdll = 0; // (0) Disabled
13 auto trace_user32 = 0; // (0) Disabled
14
15 // Autorun ?
16 // RunTo(BeginEA());
17 // GetDebuggerEvent(WFNE_SUSP, -1);
18
19 if (get_process_state() == 0){
20 warning("Ooops! Antidebugging breakpoints cannot be configured\n\nNo process is currently debugged..");
21 return;
22 }
23 if (get_process_state() != -1){
24 warning("Ooops! Antidebugging breakpoints cannot be configured\n\nPlease suspend the debugger first..");
25 return;
26 }
27
28 Message("[?] API - Antidebugging Breakpoints for IDA PRO by jSacco <jsacco@exploitpack.com>\n");
29 Message("[?] Based on the \"Ultimate\" Antidebugging-Reference by Peter Ferrie\n");
30 Message("[?] Breakpoints properties: Trace on - enabled [ No-Break ]\n\n");
31
32 if (trace_kernel32){
33 kernel32_brk();
34 }
35
36 if (trace_ntdll){
37 ntdll_brk();
38 }
39
40 if (trace_user32){
41 user32_brk();
42 }
43}
44
45static kernel32_brk()
46{
47 // KERNEL32
48 auto addr1 = LocByName("kernel32_CheckRemoteDebuggerPresent");
49 auto addr2 = LocByName("kernel32_CreateToolhelp32Snapshot");
50 auto addr3 = LocByName("kernel32_IsDebuggerPresent");
51 auto addr4 = LocByName("kernel32_SuspendThread");
52 auto addr5 = LocByName("kernel32_QueueUserAPC");
53 auto addr6 = LocByName("kernel32_CreateProcessA");
54 auto addr7 = LocByName("kernel32_CreateThread");
55 auto addr8 = LocByName("kernel32_DebugActiveProcess");
56 auto addr9 = LocByName("kernel32_RaiseException");
57 auto addr10 = LocByName("kernel32_WriteProcessMemory");
58 auto addr11 = LocByName("kernel32_CloseHandle");
59 auto addr12 = LocByName("kernel32_LoadLibraryA");
60 auto addr13 = LocByName("kernel32_LoadLibraryExA");
61 auto addr14 = LocByName("kernel32_ReadFile");
62 auto addr15 = LocByName("kernel32_GetLocalTime");
63 auto addr16 = LocByName("kernel32_GetSystemTime");
64 auto addr17 = LocByName("kernel32_GetTickCount");
65 auto addr18 = LocByName("kernel32_timeGetTime");
66 auto addr19 = LocByName("kernel32_QueryPerformanceCounter");
67 auto addr20 = LocByName("kernel32_SwitchToThread");
68 auto addr21 = LocByName("kernel32_Toolhelp32ReadProcessMemory");
69 auto addr22 = LocByName("kernel32_UnhandledExceptionFilter");
70 auto addr23 = LocByName("kernel32_VirtualProtect");
71 auto addr24 = LocByName("kernel32_VirtualProtectEx");
72
73 if (addr1 != BADADDR){
74 Message("[*] Kernel32 CheckRemoteDebuggerPresent at address, breakpoint set %x\n", addr1);
75 AddBpt(addr1);
76 SetBptAttr(addr1, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
77 SetBptCnd(addr1, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_CheckRemoteDebuggerPresent: The kernel32 CheckRemoteDebuggerPresent function was introduced in Windows XP SP1 to query a value that has existed since Windows NT. Remote in this sense refers to a separate process on the same machine.\\n\")");
78
79 // Add runtime patching here if necessary
80 // PatchDword(addr1, 0x8B55FF8B);
81 // PatchDword(addr1 + 4, 0x0C458BEC);
82 // PatchDword(addr1 + 8, 0x008F006A);
83 // PatchDword(addr1 + 12, 0xC25DC033);
84 // PatchWord(addr1 + 16, 0x0008);
85 }
86
87 if (addr2 != BADADDR){
88 Message("[*] Kernel32 CreateToolhelp32Snapshot at address, breakpoint set %x\n", addr2);
89 AddBpt(addr2);
90 SetBptAttr(addr2, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
91 SetBptCnd(addr2, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_CreateToolhelp32Snapshot: The process ID of both Explorer.exe and the parent process of the current process, and the name of that parent process, can be obtained by the kernel32 CreateToolhelp32Snapshot() function and a kernel32 Process32Next() function enumeration.\\n\")");
92
93 // Add runtime patching here if necessary
94 }
95
96 if (addr3 != BADADDR){
97 Message("[*] Kernel32 IsDebuggerPresent at address, breakpoint set %x\n", addr3);
98 AddBpt(addr3);
99 SetBptAttr(addr3, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
100 SetBptCnd(addr3, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_IsDebuggerPresent: The kernel32 IsDebuggerPresent() function was introduced in Windows 95. It returns a non-zero value if a debugger is present.\\n\")");
101
102 // Add runtime patching here if necessary
103 }
104
105 if (addr4 != BADADDR){
106 Message("[*] Kernel32 SuspendThread at address, breakpoint set %x\n", addr4);
107 AddBpt(addr4);
108 SetBptAttr(addr4, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
109 SetBptCnd(addr4, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_SuspendThread: The kernel32 SuspendThread() function can be another very effective way to disable user-mode debuggers. This can be achieved by enumerating the threads of a given process, or searching for a named window and opening its owner thread, and then suspending that thread.\\n\")");
110
111 // Add runtime patching here if necessary
112 }
113
114 if (addr5 != BADADDR){
115 Message("[*] Kernel32 QueueUserAPC at address, breakpoint set %x\n", addr5);
116 AddBpt(addr5);
117 SetBptAttr(addr5, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
118 SetBptCnd(addr5, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_QueueUserAPC: The kernel32 QueueUserAPC() function can be used to register Asynchronous Procedure Calls (APCs). Asynchronous Procedure Calls are functions that are called when the associated thread enters an alertable state, such as by calling the kernel32 Sleep() function. \\n\")");
119
120 // Add runtime patching here if necessary
121 }
122
123 if (addr6 != BADADDR){
124 Message("[*] Kernel32 CreateProcessA at address, breakpoint set %x\n", addr6);
125 AddBpt(addr6);
126 SetBptAttr(addr6, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
127 SetBptCnd(addr6, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_CreateProcessA: Creates a new process and its primary thread. The new process runs in the security context of the calling process.\\n\")");
128
129 // Add runtime patching here if necessary
130 }
131
132 if (addr7 != BADADDR){
133 Message("[*] Kernel32 CreateThread at address, breakpoint set %x\n", addr7);
134 AddBpt(addr7);
135 SetBptAttr(addr7, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
136 SetBptCnd(addr7, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_CreateThread: Threads are a simple way for the debuggee to transfer control to a memory location where execution can resume freely, unless a breakpoint is placed at the appropriate location. They can also be used to interfere with the execution of the other threads (including the main thread), and thus interfere with debugging. \\n\")");
137
138 // Add runtime patching here if necessary
139 }
140
141 if (addr8 != BADADDR){
142 Message("[*] Kernel32 DebugActiveProcess at address, breakpoint set %x\n", addr8);
143 AddBpt(addr8);
144 SetBptAttr(addr8, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
145 SetBptCnd(addr8, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_DebugActiveProcess: The kernel32 DebugActiveProcess() function can be used to attach as a debugger to an already running process. Since only one debugger can be attached to a process at a time, a failure to attach to the process might indicate the presence of anotherdebugger. \\n\")");
146
147 // Add runtime patching here if necessary
148 }
149
150 if (addr9 != BADADDR){
151 Message("[*] Kernel32 RaiseException at address, breakpoint set %x\n", addr9);
152 AddBpt(addr9);
153 SetBptAttr(addr9, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
154 SetBptCnd(addr9, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_RaiseException: The kernel32 RaiseException() function can be used to force certain exceptions to occur, which includes exceptions that a debugger would normally consume.\\n\")");
155
156 // Add runtime patching here if necessary
157 }
158
159 if (addr10 != BADADDR){
160 Message("[*] Kernel32 WriteProcessMemory at address, breakpoint set %x\n", addr10);
161 AddBpt(addr10);
162 SetBptAttr(addr10, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
163 SetBptCnd(addr10, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_WriteProcessMemory: The kernel32 WriteProcessMemory() function can be used to perform self-modification of the code stream, by reading file content to a location after the call to the function.\\n\")");
164
165 // Add runtime patching here if necessary
166 }
167
168 if (addr11 != BADADDR){
169 Message("[*] Kernel32 CloseHandle at address, breakpoint set %x\n", addr11);
170 AddBpt(addr11);
171 SetBptAttr(addr11, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
172 SetBptCnd(addr11, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_CloseHandle: One well-known technique for detecting a debugger involves the kernel32 CloseHandle() function. If an invalid handle is passed to the kernel32 CloseHandle() function and a debugger is present, then an EXCEPTION_INVALID_HANDLE (0xC0000008) exception will be raised.\\n\")");
173
174 // Add runtime patching here if necessary
175 }
176
177 if (addr12 != BADADDR){
178 Message("[*] Kernel32 LoadLibraryA at address, breakpoint set %x\n", addr12);
179 AddBpt(addr12);
180 SetBptAttr(addr12, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
181 SetBptCnd(addr12, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_LoadLibraryA: The kernel32 LoadLibrary() function is a surprisingly simple and effective way to detect a debugger. When a file is loaded in the presence of a debugger, using the kernel32 LoadLibrary() function, a handle to the file is opened. This allows the debugger to read the debug information from the file (assuming that it is present).\\n\")");
182
183 // Add runtime patching here if necessary
184 }
185
186 if (addr13 != BADADDR){
187 Message("[*] Kernel32 LoadLibraryExA at address, breakpoint set %x\n", addr13);
188 AddBpt(addr13);
189 SetBptAttr(addr13, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
190 SetBptCnd(addr13, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_LoadLibraryExA: The kernel32 LoadLibraryExA() function is a surprisingly simple and effective way to detect a debugger. When a file is loaded in the presence of a debugger, using the kernel32 LoadLibrary() function, a handle to the file is opened. This allows the debugger to read the debug information from the file (assuming that it is present).\\n\")");
191
192 // Add runtime patching here if necessary
193 }
194
195 if (addr14 != BADADDR){
196 Message("[*] Kernel32 ReadFile at address, breakpoint set %x\n", addr14);
197 AddBpt(addr14);
198 SetBptAttr(addr14, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
199 SetBptCnd(addr14, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_ReadFile: The kernel32 ReadFile() function can be used to perform self-modification of the code stream, by reading file content to a location after the call to the function.\\n\")");
200
201 // Add runtime patching here if necessary
202 }
203
204 if (addr15 != BADADDR){
205 Message("[*] Kernel32 GetLocalTime at address, breakpoint set %x\n", addr15);
206 AddBpt(addr15);
207 SetBptAttr(addr15, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
208 SetBptCnd(addr15, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_GetLocalTime: When a debugger is present, and used to single-step through the code, there is a significant delay between the executions of the individual instructions, when compared to native execution. This delay can be measured using one of several possible time sources.\\n\")");
209
210 // Add runtime patching here if necessary
211 }
212
213 if (addr16 != BADADDR){
214 Message("[*] Kernel32 GetSystemTime at address, breakpoint set %x\n", addr16);
215 AddBpt(addr16);
216 SetBptAttr(addr16, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
217 SetBptCnd(addr16, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_GetSystemTime: When a debugger is present, and used to single-step through the code, there is a significant delay between the executions of the individual instructions, when compared to native execution. This delay can be measured using one of several possible time sources.\\n\")");
218
219 // Add runtime patching here if necessary
220 }
221
222 if (addr17 != BADADDR){
223 Message("[*] Kernel32 GetTickCount at address, breakpoint set %x\n", addr17);
224 AddBpt(addr17);
225 SetBptAttr(addr17, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
226 SetBptCnd(addr17, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_GetTickCount: When a debugger is present, and used to single-step through the code, there is a significant delay between the executions of the individual instructions, when compared to native execution. This delay can be measured using one of several possible time sources.\\n\")");
227
228 // Add runtime patching here if necessary
229 }
230
231 if (addr18 != BADADDR){
232 Message("[*] Kernel32 timeGetTime at address, breakpoint set %x\n", addr18);
233 AddBpt(addr18);
234 SetBptAttr(addr18, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
235 SetBptCnd(addr18, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_timeGetTime: When a debugger is present, and used to single-step through the code, there is a significant delay between the executions of the individual instructions, when compared to native execution. This delay can be measured using one of several possible time sources.\\n\")");
236
237 // Add runtime patching here if necessary
238 }
239
240 if (addr19 != BADADDR){
241 Message("[*] Kernel32 QueryPerformanceCounter at address, breakpoint set %x\n", addr19);
242 AddBpt(addr19);
243 SetBptAttr(addr19, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
244 SetBptCnd(addr19, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_QueryPerformanceCounter: When a debugger is present, and used to single-step through the code, there is a significant delay between the executions of the individual instructions, when compared to native execution. This delay can be measured using one of several possible time sources.\\n\")");
245
246 // Add runtime patching here if necessary
247 }
248
249 if (addr20 != BADADDR){
250 Message("[*] Kernel32 SwitchToThread at address, breakpoint set %x\n", addr20);
251 AddBpt(addr20);
252 SetBptAttr(addr20, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
253 SetBptCnd(addr20, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_SwitchToThread: The kernel32 SwitchToThread() function allows the current thread to offer to give up the rest of its time slice. When an application is being debugged, the act of single-stepping through the code causes debug events and often results in no yield being allowed.\\n\")");
254
255 // Add runtime patching here if necessary
256 }
257
258 if (addr21 != BADADDR){
259 Message("[*] Kernel32 Toolhelp32ReadProcessMemory at address, breakpoint set %x\n", addr21);
260 AddBpt(addr21);
261 SetBptAttr(addr21, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
262 SetBptCnd(addr21, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_Toolhelp32ReadProcessMemory: The kernel32 Toolhelp32ReadProcessMemory() allows one process to open and read the memory of another process. This function can be used as another way to detect a step-over condition, by checking for a breakpoint after the function call.\\n\")");
263
264 // Add runtime patching here if necessary
265 }
266
267 if (addr22 != BADADDR){
268 Message("[*] Kernel32 UnhandledExceptionFilter at address, breakpoint set %x\n", addr22);
269 AddBpt(addr22);
270 SetBptAttr(addr22, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
271 SetBptCnd(addr22, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_UnhandledExceptionFilter: When an exception occurs, and no registered Exception Handlers exist (neither Structured nor Vectored), or if none of the registered handlers handles the exception, then the kernel32 UnhandledExceptionFilter() function will be called as a last resort. If a debugger is present, then that call will not be reached.\\n\")");
272
273 // Add runtime patching here if necessary
274 }
275
276 if (addr23 != BADADDR){
277 Message("[*] Kernel32 VirtualProtect at address, breakpoint set %x\n", addr23);
278 AddBpt(addr23);
279 SetBptAttr(addr23, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
280 SetBptCnd(addr23, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_VirtualProtect: The kernel32 VirtualProtect() can be used to allocate guard pages. Guard pages are pages that trigger an exception the first time that they are accessed. Guard pages can also be used to detect a debugger. \\n\")");
281
282 // Add runtime patching here if necessary
283 }
284
285 if (addr24 != BADADDR){
286 Message("[*] Kernel32 VirtualProtectEx at address, breakpoint set %x\n", addr24);
287 AddBpt(addr24);
288 SetBptAttr(addr24, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
289 SetBptCnd(addr24, "Message(\"[!] ANTI-DBG TRIGGERED - kernel32_Vkernel32_VirtualProtectEx: The kernel32 VirtualProtectEx() can be used to allocate guard pages. Guard pages are pages that trigger an exception the first time that they are accessed. Guard pages can also be used to detect a debugger.\\n\")");
290
291 // Add runtime patching here if necessary
292 }
293}
294
295static ntdll_brk()
296{
297 // NTDLL
298 auto addr25 = LocByName("ntdll_NtQueryInformationProcess");
299 auto addr26 = LocByName("ntdll_RtlQueryProcessHeapInformation");
300 auto addr27 = LocByName("ntdll_RtlQueryProcessDebugInformation");
301 auto addr28 = LocByName("ntdll_NtYieldExecution");
302 auto addr29 = LocByName("ntdll_NtProtectVirtualMemory");
303 auto addr30 = LocByName("ntdll_NtSetInformationThread");
304 auto addr31 = LocByName("ntdll_DbgUiDebugActiveProcess");
305 auto addr32 = LocByName("ntdll_NtDebugActiveProcess");
306 auto addr33 = LocByName("ntdll_NtSetInformationProcess");
307 auto addr34 = LocByName("ntdll_NtQueryObject");
308 auto addr35 = LocByName("ntdll_NtQuerySystemInformation");
309 auto addr36 = LocByName("ntdll_NtSetLdtEntries");
310 auto addr37 = LocByName("ntdll_NtQueueApcThread");
311 auto addr38 = LocByName("ntdll_NtRaiseException");
312 auto addr39 = LocByName("ntdll_RtlRaiseException");
313 auto addr40 = LocByName("ntdll_RtlProcessFlsData");
314 auto addr41 = LocByName("ntdll_DbgPrint");
315 auto addr42 = LocByName("ntdll_DbgSetDebugFilterState");
316 auto addr43 = LocByName("ntdll_DbgBreakPoint");
317 auto addr44 = LocByName("ntdll_NtSuspendThread");
318 auto addr45 = LocByName("ntdll_NtWriteVirtualMemory");
319 auto addr46 = LocByName("ntdll_NtClose");
320 auto addr47 = LocByName("ntdll_LdrLoadDll");
321
322 if (addr25 != BADADDR){
323 Message("[*] NTDLL NtQueryInformationProcess at address, breakpoint set %x\n", addr25);
324 AddBpt(addr25);
325 SetBptAttr(addr25, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
326 SetBptCnd(addr25, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtQueryInformationProcess: The ntdll NtQueryInformationProcess() function accepts a parameter which is the class of information to query. The return value is 0xffffffff if the process is being debugged. \\n\")");
327
328 // Add runtime patching here if necessary
329 }
330
331 if (addr26 != BADADDR){
332 Message("[*] NTDLL RtlQueryProcessHeapInformation at address, breakpoint set %x\n", addr26);
333 AddBpt(addr26);
334 SetBptAttr(addr26, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
335 SetBptCnd(addr26, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_RtlQueryProcessHeapInformation: The ntdll RtlQueryProcessHeapInformation() function can be used to read the heap flags from the process memory of the current process.\\n\")");
336
337 // Add runtime patching here if necessary
338 }
339
340 if (addr27 != BADADDR){
341 Message("[*] NTDLL RtlQueryProcessDebugInformation at address, breakpoint set %x\n", addr27);
342 AddBpt(addr27);
343 SetBptAttr(addr27, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
344 SetBptCnd(addr27, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_RtlQueryProcessDebugInformation: The ntdll RtlQueryProcessDebugInformation() function can be used to read certain fields from the process memory of the requested process, including the heap flags. \\n\")");
345
346 // Add runtime patching here if necessary
347 }
348
349 if (addr28 != BADADDR){
350 Message("[*] NTDLL NtYieldExecution at address, breakpoint set %x\n", addr28);
351 AddBpt(addr28);
352 SetBptAttr(addr28, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
353 SetBptCnd(addr28, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtYieldExecution: The NTDLL NtYieldExecution() function allows the current thread to offer to give up the rest of its time slice. When an application is being debugged, the act of single-stepping through the code causes debug events and often results in no yield being allowed.\\n\")");
354
355 // Add runtime patching here if necessary
356 }
357
358 if (addr29 != BADADDR){
359 Message("[*] NTDLL NtProtectVirtualMemory at address, breakpoint set %x\n", addr29);
360 AddBpt(addr29);
361 SetBptAttr(addr29, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
362 SetBptCnd(addr29, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtProtectVirtualMemory: The kernel32 NtProtectVirtualMemory() can be used to allocate guard pages. Guard pages are pages that trigger an exception the first time that they are accessed. Guard pages can also be used to detect a debugger.\\n\")");
363
364 // Add runtime patching here if necessary
365 }
366
367 if (addr30 != BADADDR){
368 Message("[*] NTDLL NtSetInformationThread at address, breakpoint set %x\n", addr30);
369 AddBpt(addr30);
370 SetBptAttr(addr30, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
371 SetBptCnd(addr30, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtSetInformationThread: Windows 2000 introduced a function extension which, at first glance, might appear to exist only for anti-debugging purposes. It is the ThreadHideFromDebugger (0x11) member of the ThreadInformationClass class. It can be set on a per-thread basis by calling the ntdll NtSetInformationThread() function.\\n\")");
372
373 // Add runtime patching here if necessary
374 }
375
376 if (addr31 != BADADDR){
377 Message("[*] NTDLL DbgUiDebugActiveProcess at address, breakpoint set %x\n", addr31);
378 AddBpt(addr31);
379 SetBptAttr(addr31, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
380 SetBptCnd(addr31, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_DbgUiDebugActiveProcess: The kernel32 DbgUiDebugActiveProcess() can be used to attach as a debugger to an already running process. Since only one debugger can be attached to a process at a time, a failure to attach to the process might indicate the presence of anotherdebugger. \\n\")");
381
382 // Add runtime patching here if necessary
383 }
384
385 if (addr32 != BADADDR){
386 Message("[*] NTDLL NtDebugActiveProcess at address, breakpoint set %x\n", addr32);
387 AddBpt(addr32);
388 SetBptAttr(addr32, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
389 SetBptCnd(addr32, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtDebugActiveProcess: The kernel32 NtDebugActiveProcess() can be used to attach as a debugger to an already running process. Since only one debugger can be attached to a process at a time, a failure to attach to the process might indicate the presence of anotherdebugger. \\n\")");
390
391 // Add runtime patching here if necessary
392 }
393
394 if (addr33 != BADADDR){
395 Message("[*] NTDLL NtSetInformationProcess at address, breakpoint set %x\n", addr33);
396 AddBpt(addr33);
397 SetBptAttr(addr33, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
398 SetBptCnd(addr33, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtSetInformationProcess: Perhaps because the value of the Local Descriptor Table (LDT) register is zero in user-mode in a physical (as opposed to a virtual) Windows environment, it is generally not supported properly (or at all) by debuggers. As a result, it can be used as a simple anti-debugger technique.\\n\")");
399
400 // Add runtime patching here if necessary
401 }
402
403 if (addr34 != BADADDR){
404 Message("[*] NTDLL NtQueryObject at address, breakpoint set %x\n", addr34);
405 AddBpt(addr34);
406 SetBptAttr(addr34, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
407 SetBptCnd(addr34, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtQueryObject: Windows XP introduced a debug object. When a debugging session begins, a debug object is created, and a handle is associated with it. Using the ntdll NtQueryObject() function, it is possible to query for the list of existing objects, and check the number of handles associated with any debug objectthat exists.\\n\")");
408
409 // Add runtime patching here if necessary
410 }
411
412 if (addr35 != BADADDR){
413 Message("[*] NTDLL NtQuerySystemInformation at address, breakpoint set %x\n", addr35);
414 AddBpt(addr35);
415 SetBptAttr(addr35, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
416 SetBptCnd(addr35, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtQuerySystemInformation: The ntdll NtQuerySystemInformation() function accepts a parameter which is the class of information to query. Most of the classes are not documented. This includes the SystemKernelDebuggerInformation (0x23) class, which has existed since Windows NT. The SystemKernelDebuggerInformation class returns the value of two flags: KdDebuggerEnabled in al, and KdDebuggerNotPresent in ah. Thus, the return value in ah is zero if a debugger is present. \\n\")");
417
418 // Add runtime patching here if necessary
419 }
420
421 if (addr36 != BADADDR){
422 Message("[*] NTDLL NtSetLdtEntries at address, breakpoint set %x\n", addr36);
423 AddBpt(addr36);
424 SetBptAttr(addr36, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
425 SetBptCnd(addr36, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtSetLdtEntries: The ntdll NtSetLdtEntries() function also allows setting the Local Descriptor Table values directly, but only for the current process. It is an entirely separate function with a slightly different parameter format compared to the ProcessLdtInformation technique.\\n\")");
426
427 // Add runtime patching here if necessary
428 }
429
430 if (addr37 != BADADDR){
431 Message("[*] NTDLL NtQueueApcThread at address, breakpoint set %x\n", addr37);
432 AddBpt(addr37);
433 SetBptAttr(addr37, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
434 SetBptCnd(addr37, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtQueueApcThread: The ntdll NtQueueApcThread() function can be used to register Asynchronous Procedure Calls (APCs). Asynchronous Procedure Calls are functions that are called when the associated thread enters an alertable state, such as by calling the kernel32 Sleep() function. \\n\")");
435
436 // Add runtime patching here if necessary
437 }
438
439 if (addr38 != BADADDR){
440 Message("[*] NTDLL NtRaiseException at address, breakpoint set %x\n", addr38);
441 AddBpt(addr38);
442 SetBptAttr(addr38, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
443 SetBptCnd(addr38, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtRaiseException: The ntdll NtRaiseException() function can be used to force certain exceptions to occur, which includes exceptions that a debugger would normally consume. \\n\")");
444
445 // Add runtime patching here if necessary
446 }
447
448 if (addr39 != BADADDR){
449 Message("[*] NTDLL RtlRaiseException at address, breakpoint set %x\n", addr39);
450 AddBpt(addr39);
451 SetBptAttr(addr39, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
452 SetBptCnd(addr39, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_RtlRaiseException: The ntdll RtlRaiseException() function can be used to force certain exceptions to occur, which includes exceptions that a debugger would normally consume. \\n\")");
453
454 // Add runtime patching here if necessary
455 }
456
457 if (addr40 != BADADDR){
458 Message("[*] NTDLL RtlProcessFlsData at address, breakpoint set %x\n", addr40);
459 AddBpt(addr40);
460 SetBptAttr(addr40, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
461 SetBptCnd(addr40, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_RtlProcessFlsData: The ntdll RtlProcessFlsData() function is an undocumented function When called with the appropriate parameter and memory values, the function will execute code at a user-specified pointer in memory. If a debugger is unaware of this fact, then execution control might be lost.\\n\")");
462
463 // Add runtime patching here if necessary
464 }
465
466 if (addr41 != BADADDR){
467 Message("[*] Ntdll DbgPrint at address, breakpoint set %x\n", addr41);
468 AddBpt(addr41);
469 SetBptAttr(addr41, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
470 SetBptCnd(addr41, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_DbgPrint: Normally, the ntdll DbgPrint() function raises an exception, but a registered Structured Exception Handler will not see it.\\n\")");
471
472 // Add runtime patching here if necessary
473 }
474
475 if (addr42 != BADADDR){
476 Message("[*] Ntdll DbgSetDebugFilterState at address, breakpoint set %x\n", addr42);
477 AddBpt(addr42);
478 SetBptAttr(addr42, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
479 SetBptCnd(addr42, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_DbgSetDebugFilterState: The ntdll DbgSetDebugFilterState() function (or the ntdll NtSetDebugFilterState() function, both introduced in Windows XP) cannot be used to detect the presence of a debugger.\\n\")");
480
481 // Add runtime patching here if necessary
482 }
483
484 if (addr43 != BADADDR){
485 Message("[*] Ntdll DbgBreakPoint at address, breakpoint set %x\n", addr43);
486 AddBpt(addr43);
487 SetBptAttr(addr43, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
488 SetBptCnd(addr43, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_DbgBreakPoint: The ntdll DbgBreakPoint() function is called when a debugger attaches to an already-running process. The function allows the debugger to gain control because an exception is raised that the debugger can intercept.\\n\")");
489
490 // Add runtime patching here if necessary
491 }
492
493 if (addr44 != BADADDR){
494 Message("[*] NTDLL NtSuspendThread at address, breakpoint set %x\n", addr44);
495 AddBpt(addr44);
496 SetBptAttr(addr44, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
497 SetBptCnd(addr44, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtSuspendThread: The ntdll NtSuspendThread() function can be another very effective way to disable user-mode debuggers. This can be achieved by enumerating the threads of a given process, or searching for a named window and opening its owner thread, and then suspending that thread.\\n\")");
498
499 // Add runtime patching here if necessary
500 }
501
502 if (addr45 != BADADDR){
503 Message("[*] NTDLL NtWriteVirtualMemory at address, breakpoint set %x\n", addr45);
504 AddBpt(addr45);
505 SetBptAttr(addr45, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
506 SetBptCnd(addr45, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtWriteVirtualMemory: The ntdll NtWriteVirtualMemory() function can be used to perform self-modification of the code stream, by reading file content to a location after the call to the function.\\n\")");
507
508 // Add runtime patching here if necessary
509 }
510
511 if (addr46 != BADADDR){
512 Message("[*] NTDLL NtClose at address, breakpoint set %x\n", addr46);
513 AddBpt(addr46);
514 SetBptAttr(addr46, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
515 SetBptCnd(addr46, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_NtClose: If an invalid handle is passed to the CloseHandle() function and a debugger is present, then an EXCEPTION_INVALID_HANDLE (0xC0000008) exception will be raised. \\n\")");
516
517 // Add runtime patching here if necessary
518 }
519
520 if (addr47 != BADADDR){
521 Message("[*] NTDLL LdrLoadDll at address, breakpoint set %x\n", addr47);
522 AddBpt(addr47);
523 SetBptAttr(addr47, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
524 SetBptCnd(addr47, "Message(\"[!] ANTI-DBG TRIGGERED - ntdll_LdrLoadDll: The ntdll LdrLoadDll() function is a surprisingly simple and effective way to detect a debugger. When a file is loaded in the presence of a debugger, using the kernel32 LoadLibrary() function, a handle to the file is opened. This allows the debugger to read the debug information from the file (assuming that it is present).\\n\")");
525
526 // Add runtime patching here if necessary
527 }
528}
529
530static user32_brk()
531{
532 // USER32
533 auto addr48 = LocByName("user32_FindWindowA");
534 auto addr49 = LocByName("user32_BlockInput");
535
536 if (addr48 != BADADDR){
537 Message("[*] Kernel32 FindWindowA at address, breakpoint set %x\n", addr48);
538 AddBpt(addr48);
539 SetBptAttr(addr48, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
540 SetBptCnd(addr48, "Message(\"[!] ANTI-DBG TRIGGERED - user32_FindWindowA: The user32 FindWindow() function can be used to search for windows by name or class. This is an easy way to detect the presence of a debugger, if the debugger has a graphical user interface. \\n\")");
541
542 // Add runtime patching here if necessary
543 }
544
545 if (addr49 != BADADDR){
546 Message("[*] Kernel32 BlockInput at address, breakpoint set %x\n", addr49);
547 AddBpt(addr49);
548 SetBptAttr(addr49, BPTATTR_FLAGS, BPT_TRACEON | BPT_TRACE | BPT_ENABLED);
549 SetBptCnd(addr49, "Message(\"[!] ANTI-DBG TRIGGERED - user32_BlockInput: The user32 BlockInput() function can block or unblock all mouse and keyboard events (apart from the ctrl-alt-delete key sequence). The effect remains until either the process exits or the function is called again with the opposite parameter. It is a very effective way to disable debuggers.\\n\")");
550
551 // Add runtime patching here if necessary
552 }
553}