c++vb.netdebuggingreverse-engineeringtranslate

Anti-debugger technique: How to hide a thread from the debugger using VB.NET?


For several days, I have been trying to document myself about Anti-Debugger techniques.

So I found many different methods to achieve this. In these techniques, I found the possibility to hiding thread from debugger, thanks to the NtSetInformationThread method. My project is to use this method in my code written in VB.NET.

Here is a description of the technique I found in my research, which I find very well explained:

In Windows 2000, a new class of thread information transferred to the NtSetInformationThread function appeared – ThreadHideFromDebugger. This was one of the first anti-debugging techniques provided by Windows in Microsoft's search for how to prevent reverse engineering, and it's very powerful. If this flag is set for a thread, then that thread stops sending notifications about debug events

From this website

So I found a source coming from this site to achieve this. Here is the method he uses in C++:

typedef enum _THREADINFOCLASS {

    ThreadHideFromDebugger=17

} THREADINFOCLASS;

extern "C" ULONG __stdcall NtSetInformationThread(
    __in HANDLE ThreadHandle,
    __in THREADINFOCLASS ThreadInformationClass,
    __in_bcount(ThreadInformationLength) PVOID ThreadInformation,
    __in ULONG ThreadInformationLength
);

ULONG main()
{
    ULONG Status;

    Status=NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);

    if(Status)
        printf("Error with NtSetInformationThread : 0x%xn", Status);

    __asm {int 3}
    return 0; 
}

So I tried with my beginner knowledge in C++ to translate this code (To be honest I do not really know much about this language). Here's what it gave:

Private Declare Function NtSetInformationThread Lib "Ntdll.dll" (ByVal hThread As Long, ByVal ThreadInformationClass As Long, ByVal ThreadInformation As Long, ByVal ThreadInformationLength As Long) As Long
<DllImport("kernel32.dll")>

Public Shared Function GetCurrentThreadId() As UInteger
End Function

Shared Function HideFromDebugger() As UInteger
    Dim Status As UInteger

    Status = NtSetInformationThread(GetCurrentThreadId(), 17, Nothing, 0)

    If Status <> 0 Then

        Console.Write("Error with NtSetInformationThread : 0x{0:x}n", Status)
        Debugger.Break()
        Return 0
    End If
End Function

However, I feel like I'm wrong somewhere. For example, I do not understand what the argument "17" is for. Could you tell me if I'm on the right track?

Each answer items are very valuable to me :)


Solution

  • You're almost there, but your current code has two issues:

    First of all your P/Invoke declaration for the NtSetInformationThread function is not quite correct and I recommend you stick to DllImport as most Declare Function declarations that you find on the internet were written for VB6 and are not compatible with VB.NET.

    Here is the corrected version:

    <DllImport("Ntdll.dll")>
    Public Shared Function NtSetInformationThread(ByVal hThread As IntPtr, ByVal ThreadInformationClass As Integer, ByVal ThreadInformation As IntPtr, ByVal ThreadInformationLength As UInteger) As UInteger
    End Function
    

    Secondly, notice how the C++ code uses the function GetCurrentThread() and not GetCurrentThreadId(). These two are different in that the former gets you a handle which is more like a pointer to the thread, whereas the latter just gets you a numeric ID assigned to the thread.

    You need to use the GetCurrentThread function instead:

    <DllImport("Kernel32.dll")>
    Public Shared Function GetCurrentThread() As IntPtr
    End Function
    

    I do not understand what the argument "17" is for.

    17 is the value of ThreadHideFromDebugger and doesn't really have any special source or meaning. It simply tells NtSetInformationThread() what information to change about the thread.