Продолжаю серию своих вопросов . Ну просто что-то никак не получается до конца доделать, только немного продвигаюсь, тут же возникают новые вопросы . На этот раз проблема в следующем: мне нужно получить полный путь создаваемого процесса, я использую NtQueryInformationProcess, через структуру PROCESS_BASIC_INFORMATION получаю указатель на PEB, далее из PEB получаю RTL_USER_PROCESS_PARAMETERS. Насколько я понял, полный путь создаваемого процесса должен лежать в ImagePathName, так вот, я его оттуда извлекаю, а там содержится почему-то путь не создаваемого процесса, а процесса, создавшего его! В чем дело, ума не приложу. Вроде во всех доках написано что это имя создаваемого процесса. Вот мой код (перехват функции ZwCreateThread): Код (Text): NTSTATUS __stdcall xZwCreateThread(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ProcessHandle, PCLIENT_ID ClientId, PCONTEXT ThreadContext, PINITIAL_TEB InitialTeb, BOOLEAN CreateSuspended) { NTSTATUS ns; PROCESS_BASIC_INFORMATION ProcBasicInfo; DWORD RetLen, BytesCount; PEB Peb; PRTL_USER_PROCESS_PARAMETERS pRtlUserProcParams; Set_ZwCreateThread(false); ns=__ZwCreateThread(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, ClientId, ThreadContext, InitialTeb, CreateSuspended); Set_ZwCreateThread(true); ZeroMemory(&ProcBasicInfo, sizeof(PROCESS_BASIC_INFORMATION)); __ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &ProcBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &RetLen); ReadProcessMemory(ProcessHandle, ProcBasicInfo.PebBaseAddress, &Peb, sizeof(PEB), &BytesCount); pRtlUserProcParams=Peb.ProcessParameters; char buf[256]; wsprintf(buf, "%ws", pRtlUserProcParams->ImagePathName.Buffer); /* вот в этом месте вылазит сообшение с полным путем процесса, создающего новый процесс, а мне нужен путь создаваемого процесса */ MessageBox(0, buf, 0, 0); return ns; } Подскажите в чем моя ошибка и как надо было бы сделать правильно.
Сейчас проверил - всегда получаю этот результат. Проблема оказывается еще глубже чем я предполагал: всегда, для какого бы процесса не вызывал приведенный код, всегда возвращается путь того процесса, из которого идет вызов! В чем моя ошибка?
Код (Text): typedef struct _UNICODE_STRING { ULONG Length; ULONG MaximumLength; PWCHAR Buffer; // ---- указатель на имя!!! Читай по этому адресу Length байт } Еще ProcessParameters тоже указатель, значит по его адресу нужно также прочитать структуру RTL_USER_PROCESS_PARAMETERS через ReadProcessMemory(). Естественно, перед тем как читать Buffer
Ну в общем сделал как ты сказал, для других, уже созданных процессов работает, нормально показывает их полный путь, для создаваемых же, то бишь для тех, хэндл которых я перехватывал в ZwCreateThread, - нифига, выдает просто пустую строку . В чем проблема? Может быть надо дождаться сначала вызова ZwResumeThread чтобы проинициализировался главный поток процесса и только тогда получится получить путь? Но мне нельзя ждать инициализации главного потока, ведь это что-то типа системы безопасности и еще ДО запуска процесса (ну или его главного потока) надо в базе проверить, можно ли этому приложению запускаться или нет. Что подскажешь?
В CreateProcessW перед NtCreateThread вызывается функция BasePushProcessParameters, которая и заталкивает PEB в адресное пространство нового процесса. После этого PEB никто больше уже вроде бы и не трогает. Если только csrss... Хотя как проверить это не знаю. По этому поводу можно не заморачиваться. Срубить процесс можно в любой момент, в том числе и в хуке на ZwResumeThread(). Попробуй перехватить ZwResumeThread() и сделать в нем все то же самое, думаю, вопросов не возникнет. Там в случае убиения процесса не вызывая оригинальную функцию, сразу вызывается TerminateThread(). Так как это единственный поток в процессе, то процесс также завалится и не будет даже leak`ов на неосвобожденный стек
Попробовал. Та же самая фигня, возвращается пустая строка . Блин, че ж делать то? Должно же существовать какое-то решение...
CommandLine смотрел, также пустой. Вот мой код: Код (Text): PROCESS_BASIC_INFORMATION ProcBasicInfo; DWORD RetLen, BytesCount; PEB Peb; RTL_USER_PROCESS_PARAMETERS RtlUserProcParams; ZeroMemory(&ProcBasicInfo, sizeof(PROCESS_BASIC_INFORMATION)); __ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &ProcBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &RetLen); ReadProcessMemory(ProcessHandle, ProcBasicInfo.PebBaseAddress, &Peb, sizeof(PEB), &BytesCount); ReadProcessMemory(ProcessHandle, Peb.ProcessParameters, &RtlUserProcParams, sizeof(RTL_USER_PROCESS_PARAMETERS), &BytesCount); WCHAR wszBuffer[256]; ReadProcessMemory(ProcessHandle, RtlUserProcParams.ImagePathName.Buffer, wszBuffer, RtlUserProcParams.ImagePathName.Length, &BytesCount); char buf[256]; wsprintf(buf, "%ws", wszBuffer); MessageBox(0, buf, 0, 0); // просто для тестирования вывожу эту строку сообщением
Код (Text): ReadProcessMemory(ProcessHandle, RtlUserProcParams.ImagePathName.Buffer, wszBuffer, RtlUserProcParams.ImagePathName.Length, &BytesCount); Здесь RtlUserProcParams.ImagePathName.Length не равен нулю? Проверь еще похож ли на правду адрес RtlUserProcParams.ImagePathName.Buffer и статус ReadProcessMemory. Есть подозрение, что с Peb все в порядке, но какой-то косяк с чтением
n0name: Peb.ImageBaseAddress равен 0x100000, то бишь не нулевой. Значение верное (посмотрел, у запускаемого файла действительно это значение базы) gilg: как ни странно, RtlUserProcParams.ImagePathName.Length=58, адрес RtlUserProcParams.ImagePathName.Buffer равен 0x87C, статус у всех трех ReadProcessMemory - true Хм, странно все это однако... Вроде все нормально, а ведь не работает зараза...
gilg угу, чё то я тоже когда прочитал твой пост, подумал что так и есть, только минуты через 3 дошло что в контесте то этого процесса и выполняется перехват. GetLastError?