Скажите, пожалуйста, возможло ли из режима ядра получить имя исполняемого файла по его PID-у, или для этого придется возвращаться в режим пользователя? Самостоятельно по ядру накопал только об имени процесса в EPROCESS, но даже не понял, зачем оно вообще там нужно, так как с ограничением имени символов в 16 (точно не считал) далеко не уедешь...
0. Получить EPROCESS по PID - PsLookupProcessByProcessId 1. Получить объект секции. для хр и далее - SectionObject присутствует в EPROCESS, отличаются только смещения(0x138 для xpsp2 например) (для w2k чуть сложнее) 3. дальше - (для всех кроме висты) - sectionObject->Segment->ControlAreal->FilePointer
Win2k SectionObjectOffset=1ACh Win2k3 SP0 SectionObjectOffset=114h Win2k3 SP1 SectionObjectOffset=124h WinVista SectionObjectOffset=110h WinVista sectionObject->Segment->ControlAreal->FilePointer - 8 P.S. RKU
не, для w2k там его нет вообще. там есть SectionHandle. но он иногда невалидный, (иногда просто равен 4 - очень часто, а иногда - 0x3e8)
Не верно. 0x3F8. Код (Text): typedef struct _CONTROL_AREA { PVOID Segment; // 0x00 LIST_ENTRY DereferenceList; // 0x04 DWORD NumberOfSectionReferences; // 0x0c DWORD NumberOfPfnReferences; // 0x10 DWORD NumberOfMappedViews; // 0x14 WORD NumberOfSubsections; // 0x18 WORD FlushInProgressCount; // 0x1a DWORD NumberOfUserReferences; // 0x1c DWORD Flags; // MMSECTION_FLAGS // 0x20 PFILE_OBJECT FilePointer; // 0x24 PVOID WaitingForDeletion; // PEVENT_COUNTER // 0x28 WORD ModifiedWriteCount; // 0x2c WORD NumberOfSystemCacheViews; // 0x2e DWORD PagedPoolUsage; // 0x30 DWORD NonPagedPoolUsage; // 0x34 } CONTROL_AREA, * PCONTROL_AREA; typedef struct _SEGMENT { PCONTROL_AREA ControlArea; // 0x00 PVOID SegmentBaseAddress; // 0x04 DWORD TotalNumberOfPtes; // 0x08 DWORD NonExtendedPtes; // 0x0c LARGE_INTEGER SizeOfSegment; // 0x10 DWORD ImageCommitment; // 0x18 PVOID ImageInformation; // 0x1c PSECTION_IMAGE_INFORMATION PVOID SystemImageBase; // 0x20 DWORD NumberOfCommittedPages; // 0x24 DWORD SegmentPteTemplate; // 0x28 PVOID BaseAddress; // 0x2c PVOID/*PMMEXTEND_INFO*/ BaseAddrPae; // 0x30 if PAE enabled PDWORD PrototypePte; // 0x34 DWORD ThePtes[1]; // 0x38 } SEGMENT, * PSEGMENT; typedef struct _MMADDRESS_NODE { DWORD StartingVpn; // 0x00 ULONG_PTR DWORD EndingVpn; // 0x04 ULONG_PTR PVOID Parent; // 0x08 PTR MMADDRESS_NODE PVOID LeftChild; // 0x0C PTR MMADDRESS_NODE PVOID RightChild; // 0x10 PTR MMADDRESS_NODE } MMADDRESS_NODE, * PMMADDRESS_NODE; typedef struct _SECTION_OBJECT { MMADDRESS_NODE Address; // 0x00 PSEGMENT Segment; // 0x14 PTR _SEGMENT LARGE_INTEGER SizeOfSection; // 0x18 DWORD Flags; // 0x20 MMSECTION_FLAGS DWORD InitialPageProtection; // 0x24 } SECTION_OBJECT, * PSECTION_OBJECT; PVOID GetProcessSectionObject( IN PEPROCESS peproc) { PVOID result = NULL; BOOL bCurrentProcess; KAPC_STATE ApcState; NTSTATUS status; if (*NtBuildNumber == 2195) { bCurrentProcess = PsGetCurrentProcess() == peproc; if (!bCurrentProcess) { KeStackAttachProcess(peproc, &ApcState); } // Первая попытка с хэндлом 0x0004 status = ObReferenceObjectByHandle((HANDLE)0x0004, SECTION_QUERY, *MmSectionObjectType, KernelMode, &result, NULL); if (!NT_SUCCESS(status)) { // Вторая попытка с хэндлом 0x03F8 status = ObReferenceObjectByHandle((HANDLE)0x03F8, SECTION_QUERY, *MmSectionObjectType, KernelMode, &result, NULL); if (!NT_SUCCESS(status)) { // Третья попытка с хэндлом из EPROCESS->SectionHandle status = ObReferenceObjectByHandle(*(HANDLE*)((ULONG)peproc + 0x01AC), SECTION_QUERY, *MmSectionObjectType, KernelMode, &result, NULL); } } if (NT_SUCCESS(status)) { ObDereferenceObject(result); } if (!bCurrentProcess) { KeUnstackDetachProcess(&ApcState); } } else { /* * SectionObject offset: * xp 0x138 * 2k3 sp0 - 0x114, other - 0x124 * vista 0x110 */ result = *(PVOID*)((ULONG)peproc + offsSectionObject); } return result; } VOID GetProcessEXEName( IN ULONG pid, OUT PCHAR ExeName) { NTSTATUS status; PSECTION_OBJECT section_obj; PFILE_OBJECT file_obj; ULONG len; PEPROCESS peproc; UNICODE_STRING usDosName; WCHAR textbuf[MAX_PATH]; __try { status = PsLookupProcessByProcessId((HANDLE)pid, &peproc); if (NT_SUCCESS(status)) { section_obj = (PSECTION_OBJECT)GetProcessSectionObject(peproc); if (MmIsAddressValid(section_obj)) { if (MmIsAddressValid(section_obj->Segment)) { if (MmIsAddressValid(((PSEGMENT)section_obj->Segment)->ControlArea)) { file_obj = ((PSEGMENT)section_obj->Segment)->ControlArea->FilePointer; file_obj = (PFILE_OBJECT)((ULONG)file_obj & 0xfffffff8); if (MmIsAddressValid(file_obj)) { status = RtlVolumeDeviceToDosName(file_obj->DeviceObject, &usDosName); if (NT_SUCCESS(status)) { RtlZeroMemory(&textbuf, MAX_PATH * sizeof(WCHAR)); wcsncpy(textbuf, usDosName.Buffer, usDosName.Length / sizeof(WCHAR)); ExFreePool(usDosName.Buffer); wcsncat(textbuf, file_obj->FileName.Buffer, file_obj->FileName.Length / sizeof(WCHAR)); wcstombs(ExeName, textbuf, wcslen(textbuf) + 1); } } } } } } } __except(EXCEPTION_EXECUTE_HANDLER) { } } Если GetProcessEXEName() вернула пустую строку, имя следует считать из EPROCESS, тут это не реализовано. Но думаю самому сделать это труда не составит. GetProcessEXEName() универсальна и работает везде, начиная от w2k вплоть до vista sp1 и w2k8 sp1. Enjoy
круто! особенно насчет NtBuildNumber == 2195 ))) мы это делаем для всех w2k - тоже как то работает. насчет 0x3e8 - пасип, обязательно проверю...