本日の内容は耐解析性を高めるスレッドのステルス化についてです。
ステルス化とは該当のスレッドをデバッガから解析できないようにすることです。
耐解析性を高める手法として有効です。
(ソフトウェアの動的解析回避として)
「ntdll」の「NtSetInformationThread」という関数を使います。
該当のスレッドに対して「0x11 = 17」を渡すことでステルス化が成功します。
(このスレッドのステルス化はMicrosoftの公式ページにはあまり詳細が載っていない内容です。)
ソースコード
Mainスレッドをステルス化し、ブレークポイントを貼れないようにします。
「NtSetInformationThread」以降の処理はブレーク不可で、
タイマー処理もブレークポイントを貼っても停止しません。
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace StealthThreadPrj
{
public partial class Form1 : Form
{
enum NTSTATUS
{
STATUS_SUCCESS = 0,
STATUS_INFO_LENGTH_MISMATCH = 4,
}
enum THREADINFOCLASS
{
ThreadHideFromDebugger = 0x11,
}
[DllImport("ntdll.dll")]
public static extern ulong NtSetInformationThread(
IntPtr ThreadHandle, int ThreadInformationClass,
IntPtr ThreadInformation, ulong ThreadInformationLength);
[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentThread();
public Form1()
{
InitializeComponent();
ulong status;
// 現在のスレッドを取得する
IntPtr curThread = GetCurrentThread();
// ステルス化の実施
status = NtSetInformationThread(curThread, (int)THREADINFOCLASS.ThreadHideFromDebugger, IntPtr.Zero, 0);
// 以降はブレークポイントを貼っても止まらない
if(status == (int)NTSTATUS.STATUS_SUCCESS)
{
Console.WriteLine("Stealth Thread Success : 0x{0:x}", status);
}
else
{
Console.WriteLine("Stealth Thread Fail : 0x{0:x}", status);
}
// Break貼っても止まらない
for(int i=0; i < 3; i++)
{
Console.WriteLine(i);
}
timer1.Interval = 1000;
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
// ここにもBreak貼っても止まらない
Console.WriteLine("Hello");
}
}
}
参考
更新履歴
- 2021/11/06 初版