NT5/NT6上的获取进程全路径
前面说过使用一大堆函数获取全路径PID->eprocess->KeStackAttachProcess->ZwQueryInformationProcess->ProcessImageFileName->ZwCreateFile
->ObReferenceObjectByHandle->RtlVolumeDeviceToDosName
->ZwQueryInformationFile
code:
NTKERNELAPI NTSTATUS
PsLookupProcessByProcessId(
IN HANDLE ProcessId,
OUT PEPROCESS *Process
);
/*NTSTATUS
IoQueryFileDosDeviceName(
IN PFILE_OBJECT FileObject,
OUT POBJECT_NAME_INFORMATION *ObjectNameInformation
); */
NTSTATUS
NTAPI
ZwQueryInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);
NTSTATUSGetProcessFullNameByPid(HANDLE nPid, PUNICODE_STRINGFullPath)
{
HANDLE hFile = NULL;
ULONG nNeedSize = 0;
NTSTATUS nStatus = STATUS_SUCCESS;
NTSTATUS nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
PEPROCESS Process = NULL;
KAPC_STATE ApcState = {0};
PVOID lpBuffer = NULL;
OBJECT_ATTRIBUTES ObjectAttributes = {0};
IO_STATUS_BLOCK IoStatus = {0};
PFILE_OBJECT FileObject = NULL;
PFILE_NAME_INFORMATION FileName = NULL;
WCHAR FileBuffer = {0};
DECLARE_UNICODE_STRING_SIZE(ProcessPath,MAX_PATH);
DECLARE_UNICODE_STRING_SIZE(DosDeviceName,MAX_PATH);
PAGED_CODE();
nStatus = PsLookupProcessByProcessId(nPid, &Process);
if(NT_ERROR(nStatus))
{
KdPrint(("%s error PsLookupProcessByProcessId.\n",__FUNCTION__));
return nStatus;
}
__try
{
KeStackAttachProcess(Process, &ApcState);
nStatus = ZwQueryInformationProcess(
NtCurrentProcess(),
ProcessImageFileName,
NULL,
NULL,
&nNeedSize
);
if (STATUS_INFO_LENGTH_MISMATCH != nStatus)
{
KdPrint(("%s NtQueryInformationProcess error.\n",__FUNCTION__));
nStatus = STATUS_MEMORY_NOT_ALLOCATED;
__leave;
}
lpBuffer = ExAllocatePoolWithTag(NonPagedPool, nNeedSize,'GetP');
if (lpBuffer == NULL)
{
KdPrint(("%s ExAllocatePoolWithTag error.\n",__FUNCTION__));
nStatus = STATUS_MEMORY_NOT_ALLOCATED;
__leave;
}
nStatus =ZwQueryInformationProcess(
NtCurrentProcess(),
ProcessImageFileName,
lpBuffer,
nNeedSize,
&nNeedSize
);
if (NT_ERROR(nStatus))
{
KdPrint(("%s NtQueryInformationProcess error2.\n",__FUNCTION__));
__leave;
}
RtlCopyUnicodeString(&ProcessPath,(PUNICODE_STRING)lpBuffer);
InitializeObjectAttributes(
&ObjectAttributes,
&ProcessPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
nStatus = ZwCreateFile(
&hFile,
FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
NULL,
0
);
if (NT_ERROR(nStatus))
{
hFile = NULL;
__leave;
}
nStatus = ObReferenceObjectByHandle(
hFile,
NULL,
*IoFileObjectType,
KernelMode,
(PVOID*)&FileObject,
NULL
);
if (NT_ERROR(nStatus))
{
FileObject = NULL;
__leave;
}
FileName = (PFILE_NAME_INFORMATION)FileBuffer;
nStatus = ZwQueryInformationFile(
hFile,
&IoStatus,
FileName,
sizeof(WCHAR)*MAX_PATH,
FileNameInformation
);
if (NT_ERROR(nStatus))
{
__leave;
}
if (FileObject->DeviceObject == NULL)
{
nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
__leave;
}
nDeviceStatus = RtlVolumeDeviceToDosName(FileObject->DeviceObject,&DosDeviceName);
}
__finally
{
if (NULL != FileObject)
{
ObDereferenceObject(FileObject);
}
if (NULL != hFile)
{
ZwClose(hFile);
}
if (NULL != lpBuffer)
{
ExFreePool(lpBuffer);
}
KeUnstackDetachProcess(&ApcState);
}
if (NT_SUCCESS(nStatus))
{
RtlInitUnicodeString(&ProcessPath,FileName->FileName);
if (NT_SUCCESS(nDeviceStatus))
{
RtlCopyUnicodeString(FullPath,&DosDeviceName);
RtlUnicodeStringCat(FullPath,&ProcessPath);
}
else
{
RtlCopyUnicodeString(FullPath,&ProcessPath);
}
}
return nStatus;
}
这实在是太麻烦了
其实要获得全路径 就是要获得FIleObject 而FIleObject就在EPROCESS结构下 详细继续读下去
在NT5上PsReferenceProcessFilePointer没有导出,需要自己实现
在WRK中:
NTSTATUS NTAPI PsReferenceProcessFilePointer
(
IN PEPROCESS Process,
OUT PFILE_OBJECT * FileObject
)
{
PSECTION Section;
PAGED_CODE();
/* Lock the process */
ExAcquireRundownProtection(&Process->RundownProtect);
/* Get the section */
Section = Process->SectionObject;
if (Section)
{
/* Get the file object and reference it */
*FileObject = MmGetFileObjectForSection((PVOID)Section);
ObReferenceObject(*FileObject);
}
/* Release the protection */
ExReleaseRundownProtection(&Process->RundownProtect);
/* Return status */
return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
PFILE_OBJECT NTAPI MmGetFileObjectForSection
(
IN PVOID Section
)
{
PSECTION_OBJECT Section;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(SectionObject != NULL);
/* Check if it's an ARM3, or ReactOS section */
if (MiIsRosSectionObject(SectionObject) == FALSE)
{
/* Return the file pointer stored in the control area */
Section = SectionObject;
return Section->Segment->ControlArea->FilePointer;
}
/* Return the file object */
return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
}
FileObject要这么获得:Process->SectionObject->Segment->ControlArea->FilePointer
大概需要4个硬编码
XP:
code:
//Process->SectionObject->Segment->ControlArea->FilePointer
PFILE_OBJECT __declspec(naked) __stdcall _MmGetFileObjectForSection(PVOID Section)
{
__asm
{
push ebp;
movebp, esp;
moveax, dword ptr ss:;
moveax, dword ptr ds:;
moveax, dword ptr ds:;
moveax, dword ptr ds:;
movesp, ebp;
popebp;
ret0x04;
}
/*
kd> dt _section_object 0xe109e640
nt!_SECTION_OBJECT
+0x000 StartingVa : (null)
+0x004 EndingVa : (null)
+0x008 Parent : (null)
+0x00c LeftChild : (null)
+0x010 RightChild : (null)
+0x014 Segment : 0xe10c14c0 _SEGMENT_OBJECT
kd> dt _SEGMENT_OBJECT 0xe10c14c0
nt!_SEGMENT_OBJECT
+0x000 BaseAddress : 0x861f2348 Void
+0x004 TotalNumberOfPtes : 0xb1
+0x008 SizeOfSegment : _LARGE_INTEGER 0xb1
+0x010 NonExtendedPtes: 0xb1000
+0x014 ImageCommitment: 0
+0x018 ControlArea : 0xcbf13c3e _CONTROL_AREA
+0x01c Subsection : (null)
+0x020 LargeControlArea : (null)
+0x024 MmSectionFlags : (null)
+0x028 MmSubSectionFlags : 0x00400000 _MMSUBSECTION_FLAGS
kd> dt _CONTROL_AREA 0x861f2348
nt!_CONTROL_AREA
+0x000 Segment : 0xe10c14c0 _SEGMENT
+0x004 DereferenceList: _LIST_ENTRY [ 0x0 - 0x0 ]
+0x00c NumberOfSectionReferences : 1
+0x010 NumberOfPfnReferences : 0xa1
+0x014 NumberOfMappedViews : 1
+0x018 NumberOfSubsections : 5
+0x01a FlushInProgressCount : 0
+0x01c NumberOfUserReferences : 2
+0x020 u : __unnamed
+0x024 FilePointer : 0x8602caf8 _FILE_OBJECT
+0x028 WaitingForDeletion : (null)
+0x02c ModifiedWriteCount : 0
+0x02e NumberOfSystemCacheViews : 0
kd> dt _FILE_OBJECT 0x8602caf8
nt!_FILE_OBJECT
+0x000 Type : 0n5
+0x002 Size : 0n112
+0x004 DeviceObject : 0x8632c030 _DEVICE_OBJECT
+0x008 Vpb : 0x862443c8 _VPB
+0x00c FsContext : 0xe1059aa0 Void
+0x010 FsContext2 : 0xe105b648 Void
+0x014 SectionObjectPointer : 0x85e16fa0 _SECTION_OBJECT_POINTERS
+0x018 PrivateCacheMap: (null)
+0x01c FinalStatus : 0n0
+0x020 RelatedFileObject : (null)
+0x024 LockOperation : 0 ''
+0x025 DeletePending : 0 ''
+0x026 ReadAccess : 0x1 ''
+0x027 WriteAccess : 0 ''
+0x028 DeleteAccess : 0 ''
+0x029 SharedRead : 0x1 ''
+0x02a SharedWrite : 0 ''
+0x02b SharedDelete : 0x1 ''
+0x02c Flags : 0xc4042
+0x030 FileName : _UNICODE_STRING "\Program Files\VMware\VMware Tools\TPAutoConnect.exe"
+0x038 CurrentByteOffset : _LARGE_INTEGER 0x0
+0x040 Waiters : 0
+0x044 Busy : 0
+0x048 LastLock : (null)
+0x04c Lock : _KEVENT
+0x05c Event : _KEVENT
+0x06c CompletionContext : (null)
*/
}
NTSTATUS PsReferenceProcessFilePointer(IN PEPROCESS Process, OUT PVOID *OutFileObject)
{
PVOID SectionObject;
//xp:
// +0x134 Job : Ptr32 _EJOB
// +0x138 SectionObject : Ptr32 Void
if (SectionObject = *(PVOID*)((PCHAR)Process + 0x138))
{
PFILE_OBJECT FileObject;
FileObject = _MmGetFileObjectForSection(SectionObject);
*OutFileObject = FileObject;
ObReferenceObject (FileObject);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
PUNICODE_STRING PsGetProcessFullNameByHardCodeOfXP(PEPROCESS pTargetProcess)
{
PFILE_OBJECT pFileObject=NULL;
POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
return NULL;
if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
return NULL;
return &(pObjectNameInfo->Name);//尚未释放内存
}
除了这个以外:还有一个
Process->SeAuditProcessCreationInfo.ImageFileName->Name
在WRK中可以看到
这说明从这个路径可能是不存在的
NTSTATUS
SeLocateProcessImageName(
__in PEPROCESS Process,
__deref_out PUNICODE_STRING *pImageFileName
)
/*++
Routine Description
This routine returns the ImageFileName information from the process, if available.This is a "lazy evaluation" wrapper
around SeInitializeProcessAuditName.If the image file name information has already been computed, then this call simply
allocates and returns a UNICODE_STRING with this information.Otherwise, the function determines the name, stores the name in the
EPROCESS structure, and then allocates and returns a UNICODE_STRING.Caller must free the memory returned in pImageFileName.
Arguments
Process - process for which to acquire the name
pImageFileName - output parameter to return name to caller
Return Value
NTSTATUS.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID FilePointer = NULL;
PVOID PreviousValue = NULL;
POBJECT_NAME_INFORMATION pProcessImageName = NULL;
PUNICODE_STRING pTempUS = NULL;
ULONG NameLength = 0;
PAGED_CODE();
*pImageFileName = NULL;
if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
//
// The name has not been predetermined.We must determine the process name. First, reference the
// PFILE_OBJECT and lookup the name.Then again check the process image name pointer against NULL.
// Finally, set the name.
//
Status = PsReferenceProcessFilePointer( Process, &FilePointer );
if (NT_SUCCESS(Status)) {
//
// Get the process name information.
//
Status = SeInitializeProcessAuditName(
FilePointer,
TRUE, // skip audit policy
&pProcessImageName // to be allocated in nonpaged pool
);
if (NT_SUCCESS(Status)) {
//
// Only use the pProcessImageName if the field in the process is currently NULL.
//
PreviousValue = InterlockedCompareExchangePointer(
(PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
(PVOID) pProcessImageName,
(PVOID) NULL
);
if (NULL != PreviousValue) {
ExFreePool(pProcessImageName); // free what we caused to be allocated.
}
}
ObDereferenceObject( FilePointer );
}
}
if (NT_SUCCESS(Status)) {
//
// Allocate space for a buffer to contain the name for returning to the caller.
//
NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
if (NULL != pTempUS) {
RtlCopyMemory(
pTempUS,
&Process->SeAuditProcessCreationInfo.ImageFileName->Name,
NameLength
);
pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
*pImageFileName = pTempUS;
} else {
Status = STATUS_NO_MEMORY;
}
}
return Status;
}
我自己实现了下 在win7 x86下效果还是可以的 不过使用了硬编码,推荐还是在NT5上使用(NT6很简单)
PUNICODE_STRING GetSeLocateProcessImageName(PEPROCESS Process,PUNICODE_STRING *pImageFileName)
{
POBJECT_NAME_INFORMATION pProcessImageName = NULL;
PUNICODE_STRING pTempUS = NULL;
ULONG NameLength = 0;
//Process->SeAuditProcessCreationInfo.ImageFileName->Name
//win7 x86 offset = 0x1ec
//if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName)
pProcessImageName = (POBJECT_NAME_INFORMATION)(*(ULONG*)((ULONG)Process + 0x1ec));
if(pProcessImageName == NULL)
{
DbgPrint("Process->SeAuditProcessCreationInfo.ImageFileName == NULL \n");
return NULL;
}
else
{
NameLength = sizeof(UNICODE_STRING) + pProcessImageName->Name.MaximumLength;
pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
if (NULL != pTempUS) {
RtlCopyMemory(
pTempUS,
&pProcessImageName->Name,
NameLength
);
pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
*pImageFileName = pTempUS;
DbgPrint("Path:%wZ\n",&pProcessImageName->Name);
return *pImageFileName;
}
return NULL;
}
}
而NT6就很简单了
PsReferenceProcessFilePointe已经被导出了
那么直接使用
PsReferenceProcessFilePointe +IoQueryFileDosDeviceName就可以了
PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
{
PFILE_OBJECT pFileObject=NULL;
POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
return NULL;
if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
return NULL;
return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
}
除了这些以前还有一些路径存在PEB里 如果在x64的系统中 还得看是PEB32还是PEB64 虽然可以使用PsGetProcessWow64Process来判断是不是64进程
但这些数据在r3就可以直接被修改了 所以不太建议使用
PEB->ProcessParameters->ImagePathName
PEB->ProcessParameters->CommandLine
PEB->ProcessParameters->WindowTitle
PEB->Ldr->InLoadOrderLinks->FullDllName
PEB->Ldr->InMemoryOrderLinks->FullDllName
大家看看黑客防线里面的《伪造进程初探》和获取进程完整路径方法小结.pdf
另外一个博主写的也是不错的
42969803 //EPROCESS取进程全路径
43638651 //EPROCESS取进程全路径(xp)
页:
[1]