티스토리 뷰

보안/분석

NTSTATUS PspCreateProcess(...)

NineKY 2008. 3. 25. 15:00

/*++

Routine Description:

This routine creates and initializes a process object. It implements the

foundation for NtCreateProcess and for system initialization process

creation.

Arguments:

ProcessHandle - Returns the handle for the new process.

DesiredAccess - Supplies the desired access modes to the new process.

ObjectAttributes - Supplies the object attributes of the new process.

ParentProcess - Supplies a handle to the process' parent process. If this parameter is not specified, then the process has no parent and is created using the system address space.

SectionHandle - Supplies a handle to a section object to be used to create the process' address space. If this parameter is not specified, then the address space is simply a clone of the parent process' address space.

DebugPort - Supplies a handle to a port object that will be used as the process' debug port.

ExceptionPort - Supplies a handle to a port object that will be used as the

process' exception port.

Return Value:

TBD

--*/

 

NTSTATUS

PspCreateProcess(

           OUT PHANDLE ProcessHandle,

           IN ACCESS_MASK DesiredAccess,

           IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

           IN HANDLE ParentProcess OPTIONAL,

           IN BOOLEAN InheritObjectTable,

           IN HANDLE SectionHandle OPTIONAL,

           IN HANDLE DebugPort OPTIONAL,

           IN HANDLE ExceptionPort OPTIONAL) {

           NTSTATUS st;

           PEPROCESS Process;

           PEPROCESS Parent;

           KAFFINITY Affinity;

           KPRIORITY BasePriority;

           PVOID SectionToMap;

           PVOID ExceptionPortObject;

           PVOID DebugPortObject;

           ULONG WorkingSetMinimum, WorkingSetMaximum;

           HANDLE LocalProcessHandle;

           KPROCESSOR_MODE PreviousMode;

           HANDLE NewSection;

           NTSTATUS DuplicateStatus;

           INITIAL_PEB InitialPeb;

           BOOLEAN CreatePeb;

           ULONG_PTR DirectoryTableBase[2];

           BOOLEAN AccessCheck;

           BOOLEAN MemoryAllocated;

           PSECURITY_DESCRIPTOR SecurityDescriptor;

           SECURITY_SUBJECT_CONTEXT SubjectContext;

           NTSTATUS accesst;

           NTSTATUS savedst;

           BOOLEAN BreakAwayRequested;

           PUNICODE_STRING AuditName = NULL ;

          

           PAGED_CODE();

          

           BreakAwayRequested = FALSE;

           CreatePeb = FALSE;

           DirectoryTableBase[0] = 0;

           DirectoryTableBase[1] = 0;

           PreviousMode = KeGetPreviousMode();

          

           //

           // Parent

           //

          

           if (ARGUMENT_PRESENT(ParentProcess) ) {

                     st = ObReferenceObjectByHandle(

                                ParentProcess,

                                PROCESS_CREATE_PROCESS,

                                PsProcessType,

                                PreviousMode,

                                (PVOID *)&Parent,

                                NULL

                                );

                     if ( !NT_SUCCESS(st) ) {

                                return st;

                     }

                    

                      //

                     // Until CSR understands priority class, don't

                     // inherit base priority. This just makes things

                     // worse !

                     //

                    

                     BasePriority = (KPRIORITY) NORMAL_BASE_PRIORITY;

                    

                     //

                     //BasePriority = Parent->Pcb.BasePriority;

                     //

                    

                     Affinity = Parent->Pcb.Affinity;

                    

                     WorkingSetMinimum = PsMinimumWorkingSet; // FIXFIX

                     WorkingSetMaximum = PsMaximumWorkingSet;

                    

                    

           } else {

                    

                     Parent = NULL;

                     Affinity = KeActiveProcessors;

                     BasePriority = (KPRIORITY) NORMAL_BASE_PRIORITY;

                    

                     WorkingSetMinimum = PsMinimumWorkingSet; // FIXFIX

                     WorkingSetMaximum = PsMaximumWorkingSet;

           }

          

           //

           // Section

           //

          

           if (ARGUMENT_PRESENT(SectionHandle) ) {

                    

                     //

                     // Use Object manager tag bits to indicate that breakaway is

                     // desired

                     //

                    

                     if ( (UINT_PTR)SectionHandle & 1 ) {

                                BreakAwayRequested = TRUE;

                     }

                    

                     st = ObReferenceObjectByHandle(

                                SectionHandle,

                                SECTION_MAP_EXECUTE,

                                MmSectionObjectType,

                                PreviousMode,

                                (PVOID *)&SectionToMap,

                                NULL

                                );

                     if ( !NT_SUCCESS(st) ) {

                                if (Parent) {

                                          ObDereferenceObject(Parent);

                                }

                                return st;

                     }

           } else {

                     SectionToMap = NULL;

           }

          

           //

           // DebugPort

           //

          

           if (ARGUMENT_PRESENT(DebugPort) ) {

                     st = ObReferenceObjectByHandle (

                                DebugPort,

                                0,

                                LpcPortObjectType,

                                KeGetPreviousMode(),

                                (PVOID *)&DebugPortObject,

                                NULL

                                );

                     if ( !NT_SUCCESS(st) ) {

                                if (Parent) {

                                          ObDereferenceObject(Parent);

                                }

                                if (SectionToMap) {

                                          ObDereferenceObject(SectionToMap);

                                }

                                return st;

                     }

           } else {

                     DebugPortObject = NULL;

           }

          

           //

           // ExceptionPort

           //

          

           if (ARGUMENT_PRESENT(ExceptionPort) ) {

                     st = ObReferenceObjectByHandle (

                                ExceptionPort,

                                0,

                                LpcPortObjectType,

                                KeGetPreviousMode(),

                                (PVOID *)&ExceptionPortObject,

                                NULL

                                );

                     if ( !NT_SUCCESS(st) ) {

                                if (Parent) {

                                          ObDereferenceObject(Parent);

                                }

                                if (SectionToMap) {

                                          ObDereferenceObject(SectionToMap);

                                }

                                if (DebugPortObject) {

                                          ObDereferenceObject(DebugPortObject);

                                }

                               

                                return st;

                     }

           } else {

                     ExceptionPortObject = NULL;

           }

          

           st = ObCreateObject(

                     KeGetPreviousMode(),

                     PsProcessType,

                     ObjectAttributes,

                     KeGetPreviousMode(),

                     NULL,

                     (ULONG) sizeof(EPROCESS),

                     0,

                     0,

                     (PVOID *)&Process

                     );

           if ( !NT_SUCCESS( st ) ) {

                     if (Parent) {

                                ObDereferenceObject(Parent);

                     }

                     if (SectionToMap) {

                                ObDereferenceObject(SectionToMap);

                     }

                     if (DebugPortObject) {

                                ObDereferenceObject(DebugPortObject);

                     }

                     if (ExceptionPortObject) {

                                ObDereferenceObject(ExceptionPortObject);

                     }

                     return st;

           }

          

           //

           // The process object is created set to NULL. Errors

           // That occur after this step cause the process delete

           // routine to be entered.

           //

           // Teardown actions that occur in the process delete routine

           // do not need to be performed inline.

           //

          

           RtlZeroMemory(Process,sizeof(EPROCESS));

          

           InitializeListHead(&Process->ThreadListHead);

           Process->CreateProcessReported = FALSE;

           Process->DebugPort = DebugPortObject;

           Process->ExceptionPort = ExceptionPortObject;

          

          

           PspInheritQuota(Process,Parent);

           ObInheritDeviceMap(Process,Parent);

          

           if ( Parent ) {

                     Process->DefaultHardErrorProcessing = Parent->DefaultHardErrorProcessing;

                     Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId;

                     Process->SessionId = Parent->SessionId;

                    

           } else {

                     Process->DefaultHardErrorProcessing = 1;

                     Process->InheritedFromUniqueProcessId = NULL;

           }

          

           Process->ExitStatus = STATUS_PENDING;

           Process->LockCount = 1;

           Process->LockOwner = NULL;

           KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);

          

           //

           // Initialize the security fields of the process

           // The parent may be null exactly once (during system init).

           // Thereafter, a parent is always required so that we have a

           // security context to duplicate for the new process.

           //

          

           st = PspInitializeProcessSecurity( Parent, Process );

          

           if (!NT_SUCCESS(st)) {

                    

                    

                     if ( Parent ) {

                                ObDereferenceObject(Parent);

                     }

                    

                     if (SectionToMap) {

                                ObDereferenceObject(SectionToMap);

                     }

                    

                     ObDereferenceObject(Process);

                     return st;

           }

          

           //

           // Clone parent's object table.

           // If no parent (booting) then use the current object table created in

           // ObInitSystem.

           //

          

           if (Parent) {                 

                     //

                     // Calculate address space

                     //

                     // If Parent == PspInitialSystem

                     //

                    

                     if (!MmCreateProcessAddressSpace(WorkingSetMinimum,

                                Process,

                                &DirectoryTableBase[0])) {

                               

                                ObDereferenceObject(Parent);

                                if (SectionToMap) {

                                          ObDereferenceObject(SectionToMap);

                                }

                               

                                PspDeleteProcessSecurity( Process );

                               

                                ObDereferenceObject(Process);

                                return STATUS_INSUFFICIENT_RESOURCES;

                     }

                    

           } else {

                    

                     Process->ObjectTable = PsGetCurrentProcess()->ObjectTable;

                    

                     DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0];

                     DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1];

                    

                     //

                     // Initialize the Working Set Mutex and address creation mutex

                     // for this "hand built" process.

                     // Normally, the call the MmInitializeAddressSpace initializes the

                     // working set mutex, however, in this case, we have already initialized

                     // the address space and we are now creating a second process using

                     // the address space of the idle thread.

                     //

                    

                     //KeInitializeMutant(&Process->WorkingSetLock, FALSE);

                     ExInitializeFastMutex(&Process->WorkingSetLock);

                    

                     ExInitializeFastMutex(&Process->AddressCreationLock);

                    

                     KeInitializeSpinLock (&Process->HyperSpaceLock);

                    

                     //

                     // Initialize virtual address descriptor root.

                     //

                    

                     ASSERT (Process->VadRoot == NULL);

                     Process->Vm.WorkingSetSize = PsGetCurrentProcess()->Vm.WorkingSetSize;

                     KeQuerySystemTime(&Process->Vm.LastTrimTime);

                     Process->Vm.VmWorkingSetList = MmWorkingSetList;

           }

          

           Process->Vm.MaximumWorkingSetSize = WorkingSetMaximum;

          

           KeInitializeProcess(

                     &Process->Pcb,

                     BasePriority,

                     Affinity,

                     &DirectoryTableBase[0],

                     (BOOLEAN)(Process->DefaultHardErrorProcessing & PROCESS_HARDERROR_ALIGNMENT_BIT)

                     );

           Process->Pcb.ThreadQuantum = PspForegroundQuantum[0];

           Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;

          

           if (Parent) {

                    

                     //

                     // this used to happen in basesrv\srvtask.c

                     //

                     if ( Parent->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE ||

                                Parent->PriorityClass == PROCESS_PRIORITY_CLASS_BELOW_NORMAL ) {

                                Process->PriorityClass = Parent->PriorityClass;

                     }

                     //

                     // if address space creation worked, then when going through

                     // delete, we will attach. Of course, attaching means that the kprocess

                     // must be initialized, so we delay the object stuff till here.            

                     //

                     st = ObInitProcess(InheritObjectTable ? Parent : (PEPROCESS)NULL,Process);

                    

                     if (!NT_SUCCESS(st)) {

                               

                                ObDereferenceObject(Parent);

                                if (SectionToMap) {

                                          ObDereferenceObject(SectionToMap);

                                }

                               

                                PspDeleteProcessSecurity( Process );

                                ObDereferenceObject(Process);

                                return st;

                     }

           }

          

           st = STATUS_SUCCESS;

           savedst = STATUS_SUCCESS;

          

           //

           // Initialize the process address space

           // The address space has four possibilities

           //

           // 1 - Boot Process. Address space is initialized during

           // MmInit. Parent is not specified.

           //

           // 2 - System Process. Address space is a virgin address

           // space that only maps system space. Process is same

           // as PspInitialSystemProcess.

           //

           // 3 - User Process (Cloned Address Space). Address space

           // is cloned from the specified process.

           //

           // 4 - User Process (New Image Address Space). Address space

           // is initialized so that it maps the specified section.

           //

          

           if ( SectionToMap ) {

                     //

                     // User Process (New Image Address Space). Don't specify Process to

                     // clone, just SectionToMap.

                     //

                    

                     st = MmInitializeProcessAddressSpace(

                                Process,

                                NULL,

                                SectionToMap,

                                &AuditName

                                );

                    

                     ObDereferenceObject(SectionToMap);

                     ObInitProcess2(Process);

                    

                     if ( NT_SUCCESS(st) ) {

                               

                                //

                                // In order to support relocating executables, the proper status

                                // (STATUS_IMAGE_NOT_AT_BASE) must be returned, so save it here.

                                //

                               

                                savedst = st;

                               

                                st = PspMapSystemDll(Process,NULL);

                     }

                    

                     CreatePeb = TRUE;

                    

                     goto insert_process;

           }

          

           if ( Parent ) {

                    

                     if ( Parent != PsInitialSystemProcess ) {

                               

                                Process->SectionBaseAddress = Parent->SectionBaseAddress;

                               

                                //

                                // User Process ( Cloned Address Space ). Don't specify section to

                                // map, just Process to clone.

                                //

                               

                                st = MmInitializeProcessAddressSpace(

                                          Process,

                                          Parent,

                                          NULL,

                                          NULL

                                          );

                               

                                CreatePeb = TRUE;

                               

                     } else {

                               

                                //

                                // System Process. Don't specify Process to clone or section to map

                                //

                               

                                st = MmInitializeProcessAddressSpace(

                                          Process,

                                          NULL,

                                          NULL,

                                          NULL

                                          );

                     }

           }

          

insert_process:

          

           //

           // If MmInitializeProcessAddressSpace was NOT successful, then

           // dereference and exit.

           //

          

           if ( !NT_SUCCESS(st) ) {

                    

                     if (Parent) {

                                ObDereferenceObject(Parent);

                     }

                    

                     KeAttachProcess(&Process->Pcb);

                     ObKillProcess(FALSE, Process);

                     KeDetachProcess();

                    

                     PspDeleteProcessSecurity( Process );

                     ObDereferenceObject(Process);

                     return st;

           }

          

           //

           // Reference count of process is not biased here. Each thread in the

           // process bias the reference count when they are created.

           //

          

           st = ObInsertObject(

                     Process,

                     NULL,

                     DesiredAccess,

                     0,

                     (PVOID *)NULL,

                     &LocalProcessHandle

                     );

          

          

           if ( !NT_SUCCESS(st) ) {

                     if (Parent) {

                                ObDereferenceObject(Parent);

                     }

                     return st;

           }

          

           //

           // See if the parent has a job. If so reference the job

           // and add the process in.

           //

          

           if ( Parent && Parent->Job && !(Parent->Job->LimitFlags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK) ) {

                    

                     if ( BreakAwayRequested ) {

                                if ( !(Parent->Job->LimitFlags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) ) {

                                          st = STATUS_ACCESS_DENIED;

                                          if (Parent) {

                                                     ObDereferenceObject(Parent);

                                          }

                                          ZwClose(LocalProcessHandle);

                                          return st;

                                }

                     }

                     else {

                                ObReferenceObject(Parent->Job);

                                Process->Job = Parent->Job;

                                st = PspAddProcessToJob(Process->Job,Process);

                                if ( !NT_SUCCESS(st) ) {

                                          if (Parent) {

                                                     ObDereferenceObject(Parent);

                                          }

                                          ZwClose(LocalProcessHandle);

                                          return st;

                                }

                     }

           }

          

           PsSetProcessPriorityByClass(Process,PsProcessPriorityBackground);

          

           ExAcquireFastMutex(&PspActiveProcessMutex);

           InsertTailList(&PsActiveProcessHead,&Process->ActiveProcessLinks);

           ExReleaseFastMutex(&PspActiveProcessMutex);

          

           if (Parent && CreatePeb ) {

                    

                      //

                     // For processes created w/ a section,

                     // a new "virgin" PEB is created. Otherwise,

                     // for forked processes, uses inherited PEB

                     // with an updated mutant.

                    

                     RtlZeroMemory(&InitialPeb, FIELD_OFFSET(INITIAL_PEB, Mutant));

                     InitialPeb.Mutant = (HANDLE)(-1);

                     if ( SectionToMap ) {

                               

                                try {

                                          Process->Peb = MmCreatePeb(Process,&InitialPeb);

                                } except(EXCEPTION_EXECUTE_HANDLER) {

                                          ObDereferenceObject(Parent);

                                          ZwClose(LocalProcessHandle);

                                          return GetExceptionCode();

                                }

                               

                     } else {

                               

                                InitialPeb.InheritedAddressSpace = TRUE;

                               

                                Process->Peb = Parent->Peb;

                               

                                ZwWriteVirtualMemory(

                                          LocalProcessHandle,

                                          Process->Peb,

                                          &InitialPeb,

                                          sizeof(INITIAL_PEB),

                                          NULL

                                          );

                     }

                    

                     //

                     // The new process should have a handle to its

                     // section. The section is either from the specified

                     // section, or the section of its parent.

                     //

                    

                     if ( ARGUMENT_PRESENT(SectionHandle) ) {

                                DuplicateStatus = ZwDuplicateObject(

                                          NtCurrentProcess(),

                                          SectionHandle,

                                          LocalProcessHandle,

                                          &NewSection,

                                          0L,

                                          0L,

                                          DUPLICATE_SAME_ACCESS

                                          );

                     } else {

                               

                                DuplicateStatus = ZwDuplicateObject(

                                          ParentProcess,

                                          Parent->SectionHandle,

                                          LocalProcessHandle,

                                          &NewSection,

                                          0L,

                                          0L,

                                          DUPLICATE_SAME_ACCESS

                                          );

                     }

                    

                     if ( NT_SUCCESS(DuplicateStatus) ) {

                                Process->SectionHandle = NewSection;

                     }

                    

                     ObDereferenceObject(Parent);

           }

          

           if ( Parent && ParentProcess != PspInitialSystemProcessHandle ) {

                    

                     st = ObGetObjectSecurity(

                                Process,

                                &SecurityDescriptor,

                                &MemoryAllocated

                                );

                     if ( !NT_SUCCESS(st) ) {

                                ZwClose(LocalProcessHandle);

                                return st;

                     }

                    

                     //

                     // Compute the subject security context

                     //

                    

                     SubjectContext.ProcessAuditId = Process;

                     SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);

                     SubjectContext.ClientToken = NULL;

                     AccessCheck = SeAccessCheck(

                                SecurityDescriptor,

                                &SubjectContext,

                                FALSE,

                                MAXIMUM_ALLOWED,

                                0,

                                NULL,

                                &PsProcessType->TypeInfo.GenericMapping,

                                PreviousMode,

                                &Process->GrantedAccess,

                                &accesst

                                );

                     PsDereferencePrimaryToken(SubjectContext.PrimaryToken);

                     ObReleaseObjectSecurity(

                                SecurityDescriptor,

                                MemoryAllocated

                                );

                    

                     if ( !AccessCheck ) {

                                Process->GrantedAccess = 0;

                     }

                    

                     //

                     // It does not make any sense to create a process that can not

                     // do anything to itself

                     //

                    

                     Process->GrantedAccess |= (PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_SET_INFORMATION);

                    

           } else {

                     Process->GrantedAccess = PROCESS_ALL_ACCESS;

           }

          

           if ( SeDetailedAuditing ) {

                    

                     SeAuditProcessCreation( Process, Parent, AuditName );

           }

          

           KeQuerySystemTime(&Process->CreateTime);

          

           try {

                     *ProcessHandle = LocalProcessHandle;

           } except(EXCEPTION_EXECUTE_HANDLER) {

                     return st;

           }

          

           if (savedst != STATUS_SUCCESS) {

                     st = savedst;

           }

          

           return st;

}

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함