c++ 反调试器技术:如何使用VB.NET在调试器中隐藏线程?

aiqt4smr  于 2023-08-09  发布在  .NET
关注(0)|答案(2)|浏览(130)

几天来,我一直试图记录自己关于反调试器技术。
所以我找到了很多不同的方法来实现这一点。在这些技术中,我发现了对调试器隐藏线程的可能性,这要归功于NtSetInformationThread方法。我的项目是在VB.NET编写的代码中使用此方法。
以下是我在研究中发现的技术描述,我发现它解释得很好:
在Windows 2000中,出现了一个新的线程信息类- ThreadHideFromDebugger,该类将线程信息传输到NtSetInformationThread函数。这是微软在寻找如何防止逆向工程时,Windows提供的第一个反调试技术之一,它非常强大。如果为线程设置了此标志,则该线程将停止发送有关调试事件的通知
From this website
所以我从这个site找到了一个源来实现这个。下面是他在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; 
}

字符串
所以我试着用我的C++初学者知识来翻译这段代码(老实说,我对这门语言真的不太了解)。以下是它给出的结果:

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


但我觉得我在某个地方错了。例如,我不明白“17”这个参数是什么。你能告诉我我是否走对了路吗?
每个答案对我来说都很有价值:)

puruo6ea

puruo6ea1#

您几乎已经完成了,但是您当前的代码有两个问题:
首先,NtSetInformationThread函数的P/Invoke声明不太正确,我建议您坚持使用DllImport,因为您在互联网上找到的大多数Declare Function声明都是为VB 6编写的,与VB.NET不兼容。
以下是更正后的版本:

<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

字符串
其次,请注意C++代码如何使用函数GetCurrentThread()notGetCurrentThreadId()。这两种方法的不同之处在于,前者为您提供一个句柄,它更像是一个指向线程的指针,而后者只是为您提供一个分配给线程的数字ID。
您需要使用GetCurrentThread函数:

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


我不明白“17”这个论据是甚么。
17ThreadHideFromDebugger的值,实际上没有任何特殊的来源或含义。它只是告诉NtSetInformationThread()要更改有关线程的哪些信息。

wyyhbhjk

wyyhbhjk2#

如果你想要C#版本

[DllImport("Ntdll.dll")]
    public extern static uint NtSetInformationThread(IntPtr hThread, int ThreadInformationClass, IntPtr ThreadInformation, uint ThreadInformationLength);

    [DllImport("Kernel32.dll")]
    public extern static IntPtr GetCurrentThread();

    public static void DisableantiDebug()
    {
        NtSetInformationThread(GetCurrentThread(), 17, IntPtr.Zero, 0);
    }

字符串

相关问题