- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 566
- Реакции
- 14
Траблы с PsGetContextThread:
Пытаюсь реализовать классический Thread Hijacking из драйвера для инжекта в юзермод процесс. Логика стандартная: находим поток, вешаем саспенд, но на этапе получения контекста через PsGetContextThread ловлю стабильный STATUS_UNSUCCESSFUL.
Самое забавное, что KeSuspendThread и KeResumeThread отрабатывают без нареканий. По логам и анализу ядра ошибка вылетает, когда KeInsertQueueApc внутри функции дает осечку. Обычно это происходит, если у потока сброшен флаг ApcQueueable или в очереди уже висит аналогичный APC.
Что может быть не так:
Кто сталкивался с таким поведением системы при разработке своего софта? Можно, конечно, лезть в оффсеты KTHREAD и парсить стек вручную, но хотелось бы понять, почему штатный метод из состава ядра шлет меня лесом.
Есть идеи, как это пофиксить или обойти без лишних костылей?
Пытаюсь реализовать классический Thread Hijacking из драйвера для инжекта в юзермод процесс. Логика стандартная: находим поток, вешаем саспенд, но на этапе получения контекста через PsGetContextThread ловлю стабильный STATUS_UNSUCCESSFUL.
Самое забавное, что KeSuspendThread и KeResumeThread отрабатывают без нареканий. По логам и анализу ядра ошибка вылетает, когда KeInsertQueueApc внутри функции дает осечку. Обычно это происходит, если у потока сброшен флаг ApcQueueable или в очереди уже висит аналогичный APC.
Код:
NTSTATUS DbgRegisters(HANDLE ThreadId)
{
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
PETHREAD pThread;
NTSTATUS status = PsLookupThreadByThreadId(ThreadId, &pThread);
if (NT_SUCCESS(status))
{
KeSuspendThread(pThread);
// Тут стабильно прилетает 0xC0000001
status = PsGetContextThread(pThread, &ctx, KernelMode);
if (NT_SUCCESS(status))
{
DbgPrint("RIP = %I64X\n", ctx.Rip);
DbgPrint("RAX = %I64X\n", ctx.Rax);
}
KeResumeThread(pThread);
}
if (pThread)
ObDereferenceObject(pThread);
return status;
}
Что может быть не так:
- Поток находится в специфическом состоянии, когда доставка APC невозможна (например, он уже в процессе терминации).
- Потоки некоторых системных процессов или под защитой античитов могут иметь свои нюансы с доставкой APC.
- Пробовал играться с флагами ContextFlags, но результат тот же.
- IRQL на уровне PASSIVE_LEVEL, так что тут проблем быть не должно.
Кто сталкивался с таким поведением системы при разработке своего софта? Можно, конечно, лезть в оффсеты KTHREAD и парсить стек вручную, но хотелось бы понять, почему штатный метод из состава ядра шлет меня лесом.
Есть идеи, как это пофиксить или обойти без лишних костылей?