Меня интересует получение полного пути к имени исполняемого файла процесса. Мне не надо знать как его получить, мне надо знать какой вариант наиболее оптимальный. Я знаю два варианта получения имени файла процесса 1. Используя функцию PsGetProcessImageFileName() мы получим указатель на ANSI строку 2. Используя ZwQueryInformationProcess(ProcessImageFileName) мы получим UNICODE строку 3. Ещё вариант получить имя через PEB (ZwQueryInformationProcess) но я думаю это не вариант Почитал WDK там нет описания ни одной из этих функций. Именно это меня и смутило Допустим у меня есть EPROCESS, какой наиболее правильный метод получения имени файла? Чтобы работало на XP/Vista/Se7en
Можно так (vista,7,xp проверялось) EPROCESS.SeAuditProcessCreationInfo->Name.Buffer (нужно прописать смещение SeAuditProcessCreationInfo). Там нормализованное имя, по желанию можно преобразовать в другой формат.
Лазить в недокументированных структурах вместо использования недокументированных функций это шило на мыло
Да ну? ZwQueryInformationProcess(). До Vista эта функция возвращает путь только в Native-формате. Начиная с Vista есть ещё класс ProcessImageFileNameWin32, на выходе путь в DOS-формате. Я сам использую другой способ, но думаю тебе хватит и этого, попробуй, если всё таки не - пиши, подскажу.
Но тамже красным цветом написано это меня и смутило функцию ZwQueryInformationProcess я рассматривал как наиболее приемлемый вариант
для повышения собственной образованности а где узнать смещение элемента SeAuditProcessCreationInfo и смещение элемента Name в ней?
Вот мой вариант с PEB-ом, если что Code (Text): #ifdef _X86_ #define PEB_PROCESS_PARAMS_OFFSET 0x10 #define PROCESS_PARAMS_FLAGS_OFFSET 0x08 #define PROCESS_PARAMS_IMAGE_NAME_OFFSET 0x38 #elif _AMD64_ #define PEB_PROCESS_PARAMS_OFFSET 0x20 #define PROCESS_PARAMS_FLAGS_OFFSET 0x08 #define PROCESS_PARAMS_IMAGE_NAME_OFFSET 0x60 #endif #define PROCESS_PARAMETERS_NORMALIZED 1 // pointers are absolute (not self-relative) BOOLEAN GetProcessFullImagePath(PEPROCESS Process, PUNICODE_STRING ImagePath) { BOOLEAN bRet = FALSE; HANDLE hProcess = NULL; // get handle to target process NTSTATUS ns = ObOpenObjectByPointer( Process, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &hProcess ); if (NT_SUCCESS(ns)) { PROCESS_BASIC_INFORMATION ProcessInfo; // get address of PEB ns = ZwQueryInformationProcess( hProcess, ProcessBasicInformation, &ProcessInfo, sizeof(ProcessInfo), NULL ); if (NT_SUCCESS(ns)) { KAPC_STATE ApcState; // change context to target process KeStackAttachProcess(Process, &ApcState); __try { PUCHAR Peb = (PUCHAR)ProcessInfo.PebBaseAddress; if (Peb) { // get pointer to RTL_USER_PROCESS_PARAMETERS PUCHAR ProcessParams = *(PUCHAR *)(Peb + PEB_PROCESS_PARAMS_OFFSET); if (ProcessParams) { // get image path PUNICODE_STRING ImagePathName = (PUNICODE_STRING) (ProcessParams + PROCESS_PARAMS_IMAGE_NAME_OFFSET); if (ImagePathName->Buffer && ImagePathName->Length > 0) { // allocate string if (AllocUnicodeString(ImagePath, ImagePathName->Length)) { PWSTR lpwcName = NULL; ULONG Flags = *(PULONG)(ProcessParams + PROCESS_PARAMS_FLAGS_OFFSET); if (Flags & PROCESS_PARAMETERS_NORMALIZED) { // pointer to buffer is absolute address lpwcName = ImagePathName->Buffer; } else { // pointer to buffer is relative address lpwcName = (PWSTR)(ProcessParams + (ULONGLONG)ImagePathName->Buffer); } if (AppendUnicodeToString(ImagePath, lpwcName, ImagePathName->Length)) { bRet = TRUE; } else { DbgMsg(__FILE__, __LINE__, "AppendUnicodeToString() ERROR\n"); } } else { DbgMsg(__FILE__, __LINE__, "AllocUnicodeString() ERROR\n"); } } } } } __except (EXCEPTION_EXECUTE_HANDLER) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"() EXCEPTION\n"); } KeUnstackDetachProcess(&ApcState); } else { // Can't query information about process, probably 'System' or rootkit activity } ZwClose(hProcess); } else { DbgMsg(__FILE__, __LINE__, "ObOpenObjectByPointer() fails; status: 0x%.8x\n", ns); } return bRet; }
>>а где узнать смещение элемента SeAuditProcessCreationInfo и смещение элемента Name в ней? В windbg dt _EPROCESS. Там и будет смещение. А в структуре SE_AUDIT_PROCESS_CREATION_INFO содержиться только указатель на документированную OBJECT_NAME_INFORMATION, поэтому нужно всего 1 смещение.
В данном случае можно не обращать внимания, вплоть до Windows 7 оно работает. Да, только я ещё раз напоминаю, что эта функция до Vista умеет возвращать только путь в Native-формате, т.е. например, \Device\HarddiskVolume1\Windows\Notepad.exe. Чтобы получить букву диска, придётся приложить некоторые усилия, чтобы распарсить полученную строку. Кроме того, я не гарантирую, что полученный путь не будет содержать символьных ссылок. Это, конечно, маловероятно, но всё таки. Плюс заморочки с сетевыми путями тоже могут иметь место. Но тут смотри сам, если устраивает такой вариант - используй.
Здравствуйте! У меня возникла похожая проблема - никак не могу найти решения... Используя ZwQueryInformationProcess(ProcessImageFileName) мы получим UNICODE строку - выдает "???????"... Пробуя другие варианты, найденные в сети - получаю либо короткое имя (notepad.exe), либо BSOD . Некоторый код не получается скомпилить (правда, может быть, косяк в том, что стоит старая ntddk (многие структуры в найденных кодах есть в ntifs (не знаю откуда скачанном), если подключить этот ntifs, при подключенном ntddk, получаем следующее: driver.c(39) : error C2040: 'KeServiceDescriptorTable' : 'struct sdt ' differs in levels of indirection from 'struct _SERVICE_DESCRIPTOR_TABLE *' Здесь я делаю перехваты функций - не компилится... Если же выдергивать просто объявление структур из ntifs - слишком много ссылок на другие структуры (толком нельзя разобрать все связи) - и опять не компилится... Может это проблема из-за использования старой ntddk? Пока проверить не могу - wdk стоит только дома. Вот такой код работает, но выдает только имя, без пути: Code (Text): void GetCurrentProcessName(CHAR *name) { PEPROCESS proc; char *ptr; if( ProcessNameOffset ) { proc = PsGetCurrentProcess(); ptr = (PCHAR) proc + ProcessNameOffset; strcpy( name, ptr); } else { strcpy(name,"(unknown process)"); } } Кто сможет помочь разобраться - буду очень благодарен.
x64 Многое перепробовал, нашел вроде вариант, который толком собирается , но теперь пишет путь: (null). Код: Code (Text): #define MAX_BUFFER_SZ 1024 NTSYSAPI NTSTATUS NTAPI ZwOpenProcess ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess ( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL ); ... void GetCurrentProcessName ( CHAR *name ) { NTSTATUS Status=STATUS_SUCCESS; ULONG retLen; PVOID buf=NULL; CLIENT_ID clientId; OBJECT_ATTRIBUTES objAttr; HANDLE hProcess = NULL; clientId.UniqueProcess = PsGetCurrentProcessId(); clientId.UniqueThread = NULL; InitializeObjectAttributes( &objAttr, NULL, 0, NULL, NULL); Status = ZwOpenProcess( &hProcess, PROCESS_ALL_ACCESS, &objAttr, &clientId); if( !NT_SUCCESS(Status) ) { DbgPrint(("ZwOpenProcess failed\n")); return Status; } Status = ZwQueryInformationProcess( hProcess, ProcessImageFileName, buf, MAX_BUFFER_SZ * sizeof (WCHAR), &retLen); DbgPrint("Test path: %s", buf); if( !NT_SUCCESS(Status) ) { ZwClose(hProcess); return 0; } ZwClose(hProcess); return 0; } Что я сделал не так? Заранее благодарен.
В buf у тебя будет записана UNICODE_STRING, следовательно, выводить через DbgPrint() надо так: Code (Text): DbgPrint ("Process Image Name = %wZ\r\n", buf);
Спасибо за такой быстрый ответ. Теперь выдает вот что: Process Image Name = (null) Видимо, что-то не так при определении пути (ZwQuery...)
Ты память под буфер не выделяешь вообще, он у тебя NULL как был так и остался. Системные сервисы память, как правило, не выделяют вообще под такие буфера. Правильно сначала вызвать ZwQueryInformationProcess() с 4-ым параметром = 0, тогда в 5-ом параметре получишь необходимый размер буфера. Дальше уже выделяешь буфер этого размера и вызываешь ZwQueryInformationProcess() снова, но теперь уже передаёшь указатель на буфер и его размер.
rpy3uH Внедрить DLL в процесс, получить штатным образом и отправить обратно любым стандартным способом IPC. Недокументятину и прочее хэккерство - ф газенваген.
Внедрение .dll для данной задачи есть ещё больший хак, нежели ZwQueryInformationProcess(). К счастью, некоторые недокументированные вещи весьма стабильны и в умелых руках опасности не представляют.
CyberManiac Зачем чтото внедрять, если можно просто прочитать из UPP или LDR, изменить там инфу тоже можно. Кстате MemorySectionName тоже юзать можно.