Ну что, пришло время кое что написать, хочу рассказать о том как нужно “эмулировать” перехваченный ZwTerminateProcess , т.е. нам нужно узнать наш ли процесс собираться замочить :) и так, перехватить. Значит идея такая, у нас будет храниться массив из имён процессов, которые “нельзя убивать”. Что же передаться в процесс , посмотрим описание :
1.NTSTATUS ZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus);
В функцию передается HANDLE открытого для завершения процесса , и статус завершения , нам по этому хэндлу надо получить имя процесса и сравнить с нашим массивом, ну что, я сначала напишу кое какой код, потом всё по полочкам разложу. И так функция сравнивающая имя процесса с нашим массивом.
BOOLEAN ProtectZwTerminateProcess(IN PCWSTR usProcessnameBuff) { BOOLEAN bStat = FALSE; NTSTATUS rc; UNICODE_STRING usUpCase; UNICODE_STRING usFileName; ANSI_STRING szHideFileName; int i = 2,b = 0; char *szHideProcess[] = { "NOTEPAD.EXE", // notepad.exe "EXPLORER.EXE" // explorer.exe }; for (b = 0 ; b < i ; b++) { RtlInitUnicodeString(&usUpCase,usProcessnameBuff); RtlUpcaseUnicodeString(&usFileName,&usUpCase,TRUE); rc = RtlUnicodeStringToAnsiString(&szHideFileName,&usFileName,TRUE); if (NT_SUCCESS(rc)) { if (memcmp(szHideFileName.Buffer,szHideProcess[b],strlen(szHideProcess[b]))==0) { DbgPrint("ProtectProcessName hooked : %s | %s",szHideFileName.Buffer,szHideProcess[b]); RtlFreeAnsiString(&szHideFileName); RtlFreeUnicodeString(&usFileName); return bStat = TRUE; } RtlFreeAnsiString(&szHideFileName); RtlFreeUnicodeString(&usFileName); } } return bStat; }
А вот код самой перехваченной функции :
NTSTATUS NewZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus) { /********************************************************************** * NewZwTerminateProcess **********************************************************************/ NTSTATUS NZTP_STATUS = STATUS_SUCCESS; PROCESS_BASIC_INFORMATION pProcessInformation; // Параметры процесса который нужно завалить PEPROCESS remEprocess = 0; CLIENT_ID remClientId; ANSI_STRING remProcName; UNICODE_STRING usStr1; NZTP_STATUS = ZwQueryInformationProcess(ProcessHandle,ProcessBasicInformation, &pProcessInformation,sizeof( PROCESS_BASIC_INFORMATION),NULL); if (NT_SUCCESS(NZTP_STATUS)) { remClientId.UniqueProcess = (HANDLE)pProcessInformation.UniqueProcessId; remClientId.UniqueThread = 0; NZTP_STATUS = PsLookupProcessByProcessId(remClientId.UniqueProcess,&remEprocess); if (NT_SUCCESS(NZTP_STATUS)) { RtlInitAnsiString(&remProcName,remEprocess->ImageFileName); RtlAnsiStringToUnicodeString(&usStr1,&remProcName,TRUE); if (ProtectZwTerminateProcess(usStr1.Buffer)) { ObDereferenceObject(remEprocess); ZwClose(ProcessHandle); NZTP_STATUS = STATUS_ACCESS_DENIED; return NZTP_STATUS; } RtlFreeUnicodeString(&usStr1); } } NZTP_STATUS = OldZwTerminateProcess(ProcessHandle,ExitStatus); return NZTP_STATUS; }
Значит работает она так, сначала мы по полученному хэндлу вызываем ZwQueryInformationProcess с флагом ProcessBasicInformation , которая нам возвращает память вот с такой структурой :
typedef struct _PROCESS_BASIC_INFORMATION { NTSTATUS ExitStatus; PPEB PebBaseAddress; ULONG_PTR AffinityMask; KPRIORITY BasePriority; ULONG_PTR UniqueProcessId; ULONG_PTR InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION;
Затем мы, по ID процесса получаем EPROCESS процесса с помощью функции PsLookupProcessByProcessId, ну думаю структуру EPROCESS вы знаете, и так же знаете что в ней есть поле ImageFileName в котором храниться имя образа, ну а дальше просто ловкость рук :) и никакого мошенничества :). Дальше мы просто передаём её в функцию ProtectZwTerminateProcess и проверяем результат на True или False.
© ClickF1 28.03.2007


