//функция создает поток и возвращает адрес DeallocationStack NTSTATUS NTAPI NewThread(OUT PHANDLE phThread, IN HANDLE hProcess, IN PVOID StartRoutine, IN PVOID Argument OPTIONAL, OUT PVOID *pDeallocationStack OPTIONAL, OUT PCLIENT_ID ClientID OPTIONAL) { NTSTATUS ns = RtlCreateUserThread(hProcess, 0, 0, 0, 0, 0, StartRoutine, Argument, phThread, ClientID); if ((ns == STATUS_SUCCESS) && (pDeallocationStack)) { THREAD_BASIC_INFORMATION tbi;
if (ZwQueryInformationThread(*phThread, ThreadBasicInformation, &tbi, sizeof(THREAD_BASIC_INFORMATION), 0) == STATUS_SUCCESS) if (tbi.TebBaseAddress) { if (hProcess == 0xFFFFFFFF) { *pDeallocationStack = ((PTEB)(tbi.TebBaseAddress))->DeallocationStack; } else { ULONG Dummy = 0;
if (ZwReadVirtualMemory(hProcess, (PVOID)((ULONG)(tbi.TebBaseAddress) + 0xE0C), pDeallocationStack, 4, &Dummy) != STATUS_SUCCESS) *pDeallocationStack = NULL; } } else { *pDeallocationStack = NULL; } } return ns; }
//Функция уничтожает поток и освобождает его DeallocationStack NTSTATUS NTAPI KillThread(IN HANDLE hProcess, IN HANDLE hThread, IN PVOID DeallocationStack OPTIONAL) { NTSTATUS ns = ZwTerminateThread(hThread, 0);
if (DeallocationStack) { ULONG FreeSize = 0; ZwFreeVirtualMemory(hProcess, &DeallocationStack, &FreeSize, MEM_RELEASE); }
return ns; }
//Функция потока ULONG __stdcall ThreadRoutine(IN PVOID Argument) { //Работа потока return ZwTerminateThread(0xFFFFFFFE,0); }
//А вот тривиальный пример вызова всего этого безобразия NTSTATUS NTAPI ExecuteThreadRoutine(IN PVOID Argument OPTIONAL, IN PLARGE_INTEGER Timeout OPTIONAL) { PVOID DeallocationStack; HANDLE hThread; CLIENT_ID CliID;
NTSTATUS ns = NewThread(&hThread, 0xFFFFFFFF, (PVOID)ThreadRoutine, Argument, &DeallocationStack, &CliID); if (ns == STATUS_SUCCESS) { ZwWaitForSingleObject(hThread, FALSE, Timeout); KillThread(0xFFFFFFFF, hThread, DeallocationStack); ZwClose(hThread); } return ns; } |