Jump to content
Nytro

Anti Debugging Tricks #4 – Hidden Threads

Recommended Posts

Posted

Anti Debugging Tricks #4 – Hidden Threads

 

ho-ho-hoANTIDEBUG CRASH HIDE FROM DEBUGGER NTSETINFORMATIONTHREAD THREADS

Has this ever happened to you? You’re playing around with some application and and it crashes the moment you attach a debugger? Ever wondered why or how? I do. These types of questions keep me awake at night.

I first became aware of this technique while cruising around some forums on the internet. People typically asking for a bypass or a method to work around it. But I was more interested in HOW this technique works less interested in how to bypass.

During my research phase I noticed that after the application crashed out it would crash out with:

Unhandled exception code 80000003

But that’s an int 3 exception? How is the Debugger not catching that? What the actual hell. Searching around for information I discovered that NtSetInformationThread has a parameter called THREADINFOCLASS. Which contains this interesting snippet:

ThreadHideFromDebugger = 0x11 

Why Hans?

You may be wondering why this is even a ‘feature’ of Windows? Wouldn’t malware abuse the hell out of this? Yes, probably. But here’s why it exists: When you attach a debugger to a remote process a new thread is created. If this was just a normal thread the debugger would be caught in an endless loop as it attempted to stop it’s own execution.

So behind the scenes when the debugging thread is created Windows calls NtSetInformationThread with the ThreadHideFromDebugger flag set (1). This way the process can be debugged and a deadlock prevented. Allowing code execution to continue as normal.

However, now that this thread is hidden from the debugger any breakpoints or exceptions that are triggered will cause the process to crash. Due to the fact that the debugger cannot see this thread it’s now unable to trap these events.

So as it turned out some devious individual noticed this odd behaviour and thought: “this would make a really cool anti-debug feature”. Now we’re here with this method widespread enough for me to be aware of it.

Das Kode

So what’s it actually look like in code? I wasn’t able find any live examples so I constructed my own based on how I thought it should work:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <windows.h>
 
enum THREADINFOCLASS { ThreadHideFromDebugger = 0x11 };
 
typedef NTSTATUS (WINAPI *NtQueryInformationThread_t)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
typedef NTSTATUS (WINAPI *NtSetInformationThread_t)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
 
NtQueryInformationThread_t fnNtQueryInformationThread = NULL;
NtSetInformationThread_t fnNtSetInformationThread = NULL;
 
DWORD WINAPI ThreadMain(LPVOID p) {
        while(1) {
                // This can be any trigger we're using this demo purposes
                if(IsDebuggerPresent())
                        // For MingW replace with __asm { int 3; } on MSVC
                        asm("int3");
                Sleep(500);
        }
        return 0;
}
 
int main(void)
{
        DWORD dwThreadId = 0;
        HANDLE hThread = CreateThread(NULL, 0, ThreadMain, NULL, 0, &amp;dwThreadId);
 
        HMODULE hDLL = LoadLibrary("ntdll.dll");
        if(!hDLL) return -1;
 
        fnNtQueryInformationThread = (NtQueryInformationThread_t)GetProcAddress(hDLL, "NtQueryInformationThread");
        fnNtSetInformationThread = (NtSetInformationThread_t)GetProcAddress(hDLL, "NtSetInformationThread");
 
        if(!fnNtQueryInformationThread || !fnNtSetInformationThread)
                return -1;
 
        ULONG lHideThread = 1, lRet = 0;
 
        fnNtSetInformationThread(hThread, ThreadHideFromDebugger, &amp;lHideThread, sizeof(lHideThread));
        fnNtQueryInformationThread(hThread, ThreadHideFromDebugger, &amp;lHideThread, sizeof(lHideThread), &amp;lRet);
 
        printf("Thread is hidden: %s\n", val ? "Yes" : "No");
  
        WaitForSingleObject(hThread, INFINITE);
        return 0;
}

Pretty simple yes? Now if you run the program and attempt to attach a debugger you’ll get this interesting crash:

0036:err:seh:raise_exception Unhandled exception code 80000003 flags 0 addr 0x401566

Oh ho ho!

die-hard-ho-ho-ho.jpg?w=1100 Poor Tony

Throwing Hans off Nakatomi

Well now we’ve established how this works we can look at beating it. There’s a number of ways including:

  • Hooking the required Nt Function calls.
  • Replacing the int 3 instruction with a nop.
  • Nopping or hooking the “trigger” function.

I opted for nopping out int 3:

You can use your tool of choice to locate the required int 3 instruction:

2019-01-19-092752_1366x768_scrot.png You’ll have to search around a bit
2019-01-19-092813_1366x768_scrot.png Here’s our thread with the check
2019-01-19-092821_1366x768_scrot.png Now we can nop that sucka out

Attaching a debugger and resuming execution will result in everything working as expected.

giphy.gif Bye Hans
die-hard-smoke-204x300.jpg Ho-ho-ho

One Time Donation:
BTC 1DXcjix3FmcHYezFAjCrpzZA9FkbSC971e
Paypal PayPal.me/timb3r

Monthly Donation:
Patreon

 

Sursa: https://gamephreakers.com/2019/01/anti-debugging-tricks-4-hidden-threads/

  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...