NTSTATUS __stdcall NtCreateProcessEx(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob)
参数说明:
ProcessHandle 是一个输出参数,如果创建成功,则它包含了所创建的进程的句柄。
DesiredAccess 包含了对新进程的访问权限。
ObjectAttributes 是一个可选的指针参数(意指可以为NULL),它指定了进程对象的属性。
ParentProcess 指向父进程的句柄,这是一个必需的参数,不能为NULL,并且调用者必须对该进程具有PROCESS_CREATE_PROCESS 访问权限。Flags 是创建标志,其中有一个标志PROCESS_CREATE_FLAGS_INHERIT_HANDLES 特别值得一提:NtCreateProcess专门有一个布尔参数指定是否该标志为TRUE,表明新进程的对象句柄表是否要复制父进程的句柄表,或者初始设置为空。
SectionHandle 是一个可选的句柄,指向一个内存区对象,代表了该进程的映像文件,调用者对于此内存区对象必须具有SECTION_MAP_EXECUTE 访问权限。
DebugPort 也是一个可选的句柄,指向一个端口对象,如果此句柄参数不为NULL,则此端口被赋为新进程的调试端口,否则,新进程没有调试端口。而且,调用者对于调试端口对象必须具有PORT_WRITE 和PORT_READ 访问权限。
ExceptionPort 也是一个可选的句柄,指向一个端口对象,如果此句柄参数不为NULL,则此端口被赋为新进程的异常端口,否则,新进程没有异常端口。调用者对于异常端口对象必须具有PORT_WRITE 和PORT_READ 访问权限。
JobMemberLevel 指定了要创建的进程在一个Job 集中的级别。
获得路径名:
一般创建进程时ObjectAttributes其实是空的,SectionHandle才是有内容的。因此一般通过这个SectionHandle获取进程文件名。
原理是:
ObReferenceObjectByHandle,通过SectionHandle得到SectionObject,即指向_SECTION_OBJECT结构的指针。
通过_SECTION_OBJECT得到SegmentObject成员,指向一个_SEGMENT_OBJECT结构。
_SEGMENT_OBJECT结构的BaseAddress成员,指向一个_CONTROL_AREA结构。
这个_CONTROL_AREA结构的FilePointer成员,就是指向描述文件的_FILE_OBJECT结构的指针
从_FILE_OBJECT结构的DeviceObject成员中得到所在盘符(调用RtlVolumeDeviceToDosName),加上FileName成员指定的路径,就是这个文件的全路径。
函数如下:
传入的是SectionHandle
NTSTATUS GetFullName(HANDLE KeyHandle,char *fullname)
{
NTSTATUS ns;
PVOID pKey=NULL,pFile=NULL;
UNICODE_STRING fullUniName;
ANSI_STRING akeyname;
ULONG actualLen;
UNICODE_STRING dosName;
fullUniName.Buffer=NULL;
fullUniName.Length=0;
fullname[0]=0x00;
ns= ObReferenceObjectByHandle( KeyHandle, 0, NULL, KernelMode, &pKey, NULL ) ;
if( !NT_SUCCESS(ns)) return ns;
fullUniName.Buffer = ExAllocatePool( PagedPool, MAXPATHLEN*2);//1024*2
fullUniName.MaximumLength = MAXPATHLEN*2;
__try
{
pFile=(PVOID)*(ULONG *)((char *)pKey+20);
pFile=(PVOID)*(ULONG *)((char *)pFile);
pFile=(PVOID)*(ULONG *)((char *)pFile+36);
ObReferenceObjectByPointer(pFile, 0, NULL, KernelMode);
RtlVolumeDeviceToDosName(((PFILE_OBJECT)pFile)->DeviceObject,&dosName);
RtlCopyUnicodeString(&fullUniName, &dosName);
RtlAppendUnicodeStringToString(&fullUniName,&((PFILE_OBJECT)pFile)->FileName);
ObDereferenceObject(pFile);
ObDereferenceObject(pKey );
RtlUnicodeStringToAnsiString( &akeyname, &fullUniName, TRUE );
if(akeyname.Length<MAXPATHLEN)
{
memcpy(fullname,akeyname.Buffer,akeyname.Length);
fullname[akeyname.Length]=0x00;
}
else
{
memcpy(fullname,akeyname.Buffer,MAXPATHLEN);
fullname[MAXPATHLEN-1]=0x00;
}
RtlFreeAnsiString( &akeyname );
ExFreePool(dosName.Buffer);
ExFreePool( fullUniName.Buffer );
return STATUS_SUCCESS;
}
__except(1)
{
if(fullUniName.Buffer) ExFreePool( fullUniName.Buffer );
if(pKey) ObDereferenceObject(pKey );
return STATUS_SUCCESS;
}
}