0x00前言
createprocess 创建进程工作是由0环的NtCreateUserProcess函数完成的
这篇文章就来分析NtCreateUserProcess做了什么?
0x01NtCreateUserProcess流程分析
首先是验证从3环传递过来的参数并建立一个内核结构来保存这些信息
句柄检测 不能操作0环地址
接着调用PspBuildCreateProcessContext 初始化所用用到的进程信息
PspBuildCreateProcessContext 进来就是参数判断和初始化
后面篇幅过程直接分析伪代码
__int64 __fastcall NtCreateUserProcess( _QWORD *a1, // 传出新进程句柄 __int64 a2, // 传出新进程主线程句柄 int a3, // 当前进程对新进程操作权限描述 int a4, // 当前进程对新线程的操作权限描述 unsigned __int64 a5, // 进程对象属性 __int64 a6, // 线程对象属性 unsigned int a7, // 新进程创建标志 unsigned int a8, // 新线程创建标志 __int64 a9, // 进程创建相关参数 路径,命令参数 unsigned __int64 a10, // 传出信息 新进程peb unsigned __int64 *a11) // 传入参数 保存了一些信息, 程序路径 父进程pid { struct _KTHREAD *CurrentThread; // rax __int64 Process; // r13 char PreviousMode; // r15 unsigned int v14; // r12d __int64 result; // rax __int64 v16; // rcx __int64 v17; // rcx int v18; // eax int Info; // esi KPROCESSOR_MODE v20; // r14 int v21; // r8d __int64 v22; // r9 unsigned __int8 v23; // bl unsigned int v24; // eax int v25; // ecx int v26; // r9d char v27; // bl int v28; // ebx int v29; // eax int v30; // ecx struct _DMA_ADAPTER *v31; // r8 char v32; // r13 int i; // eax __int64 v34; // rdx unsigned __int8 v35; // bl int v36; // r8d __int64 v37; // r9 __int64 v38; // rdx __int64 v39; // rcx char v40; // bl int v41; // r9d __int64 v42; // rdx __int64 v43; // rcx __int64 v44; // r8 __int64 v45; // r11 __int64 *v46; // r12 char v47; // r11 int v48; // ecx unsigned int v49; // esi unsigned __int64 v50; // rax void *v51; // rsp int v52; // r9d __int64 v53; // rax char *v54; // rbx __int64 v55; // rax __int64 v56; // rcx char *v57; // rbx __int64 v58; // r13 char v59; // al int v60; // r8d int v61; // esi __int64 v62; // rax int inserted; // ebx __int64 ProcessServerSilo; // rax _OWORD *v65; // rax KPROCESSOR_MODE v66; // dl int v67; // [rsp+80h] [rbp+0h] BYREF unsigned __int8 v68; // [rsp+84h] [rbp+4h] BYREF char v69; // [rsp+85h] [rbp+5h] BYREF __int16 v70; // [rsp+86h] [rbp+6h] BYREF char v71; // [rsp+88h] [rbp+8h] BYREF char v72; // [rsp+89h] [rbp+9h] PVOID v73; // [rsp+90h] [rbp+10h] BYREF char v74; // [rsp+98h] [rbp+18h] char v75[8]; // [rsp+9Ch] [rbp+1Ch] BYREF unsigned int v76; // [rsp+A4h] [rbp+24h] BYREF int v77; // [rsp+A8h] [rbp+28h] int v78; // [rsp+ACh] [rbp+2Ch] __int64 v79; // [rsp+B0h] [rbp+30h] BYREF PADAPTER_OBJECT v80; // [rsp+B8h] [rbp+38h] BYREF __int64 v81; // [rsp+C0h] [rbp+40h] struct _KTHREAD *v82; // [rsp+C8h] [rbp+48h] PVOID v83; // [rsp+D0h] [rbp+50h] BYREF __int64 v84; // [rsp+D8h] [rbp+58h] BYREF PADAPTER_OBJECT v85; // [rsp+E0h] [rbp+60h] BYREF volatile signed __int32 *v86; // [rsp+E8h] [rbp+68h] PVOID Object; // [rsp+F0h] [rbp+70h] BYREF PVOID v88; // [rsp+F8h] [rbp+78h] BYREF __int64 v89; // [rsp+100h] [rbp+80h] __int64 v90; // [rsp+108h] [rbp+88h] _QWORD *v91; // [rsp+110h] [rbp+90h] __int64 v92; // [rsp+118h] [rbp+98h] BYREF OBJECT_ATTRIBUTES ObjectAttributes; // [rsp+120h] [rbp+A0h] BYREF __int64 v94[3]; // [rsp+150h] [rbp+D0h] BYREF __int128 v95; // [rsp+168h] [rbp+E8h] struct _IO_STATUS_BLOCK IoStatusBlock; // [rsp+178h] [rbp+F8h] BYREF struct _IO_DRIVER_CREATE_CONTEXT DriverContext; // [rsp+188h] [rbp+108h] BYREF __int64 v98[2]; // [rsp+1B0h] [rbp+130h] BYREF __int64 v99; // [rsp+1C0h] [rbp+140h] char v100[80]; // [rsp+1D0h] [rbp+150h] BYREF __int64 v105[66]; // [rsp+220h] [rbp+1A0h] BYREF _BYTE v102[400]; // [rsp+430h] [rbp+3B0h] BYREF _BYTE AccessState[400]; // [rsp+5C0h] [rbp+540h] BYREF __int64 v104[2]; // [rsp+750h] [rbp+6D0h] BYREF __int128 var60; // [rsp+760h] [rbp+6E0h] v77 = a4; v78 = a3; v90 = a2; // 传出新线程句柄 v91 = a1; // 传出新进程句柄 v86 = (volatile signed __int32 *)a5; v94[1] = a6; v89 = a9; v84 = 0i64; *(_DWORD *)v75 = 0; IoStatusBlock = 0i64; v73 = 0i64; v85 = 0i64; memset(&ObjectAttributes, 0, sizeof(ObjectAttributes)); v79 = 0i64; memset(v102, 0, sizeof(v102)); v95 = 0i64; v70 = 0; v69 = 0; v71 = 0; *(_OWORD *)v104 = 0i64; var60 = 0i64; memset(AccessState, 0, sizeof(AccessState)); v94[0] = 0i64; v76 = 0; v92 = 0i64; *(_OWORD *)v98 = 0i64; v99 = 0i64; CurrentThread = KeGetCurrentThread(); v82 = CurrentThread; Process = (__int64)CurrentThread->ApcState.Process; v81 = Process; v94[2] = Process; PreviousMode = CurrentThread->PreviousMode; v74 = PreviousMode; v83 = 0i64; v80 = 0i64; LOBYTE(CurrentThread) = 0; v67 = (int)CurrentThread; v72 = 0; memset(&DriverContext, 0, sizeof(DriverContext)); memset(v100, 0, 0x48ui64); v14 = a7; if ( (a7 & 0xFFFB6838) != 0 || (a8 & 0xFFFFFFFE) != 0 ) return 0xC000000Di64; if ( (a7 & 0x8400) == 33792 ) return 0xC0000030i64; v102[388] = PreviousMode; if ( PreviousMode ) { v16 = (__int64)v91; if ( (unsigned __int64)v91 >= 0x7FFFFFFF0000i64 ) v16 = 0x7FFFFFFF0000i64; // 进程句柄检查 *(_QWORD *)v16 = *(_QWORD *)v16; v17 = v90; // 线程句柄检查 if ( (unsigned __int64)v90 >= 0x7FFFFFFF0000i64 ) v17 = 0x7FFFFFFF0000i64; *(_QWORD *)v17 = *(_QWORD *)v17; } if ( a5 ) { if ( PreviousMode && (a5 & 3) != 0 ) // 检查是否对齐 ExRaiseDatatypeMisalignment(); if ( PreviousMode ) v18 = *(_DWORD *)(a5 + 24) & 0x1DF2; else v18 = *(_DWORD *)(a5 + 24) & 0x11FF2; *(_DWORD *)&v102[384] = v18; } memset(v105, 0, 0x208ui64); // 解析参数INFORMATION 传入信息复制到局部变量 if ( !a11 || (result = PspBuildCreateProcessContext(a11, PreviousMode, 0, (__int64)v105), (int)result >= 0) ) { if ( (a7 & 0x40) != 0 && (v105[0] & 0x2000000000000i64) != 0 && !LOBYTE(v105[48]) ) { // 进程的属性 v14 = a7 & 0xFFFFFFBF; a7 &= ~0x40u; HIDWORD(v105[0]) &= ~0x20000u; } if ( (v14 & 4) == 0 && (v105[0] & 0x80000000000i64) != 0 || (v105[0] & 0x2000000000000i64) != 0 && (v14 & 0x40) == 0 ) goto LABEL_167; Info = PspCaptureCreateInfo(PreviousMode, a10, (__int64)v105);// 解析参数createinfo 到 CreateProcessContext v105 if ( Info >= 0 ) // 小于0结束 { v20 = 1; if ( (v105[0] & 0x100000000i64) == 0 ) // flag 假会调用ObReferenceObjectByHandle获取获取父进程确保会有父进程 { v79 = Process; LABEL_33: v105[58] = PspEstimateNewProcessServerSilo(Process, v105[50], HIDWORD(v105[51])); if ( (BYTE1(v105[1]) & 0xC) != 4 || Process == v81 && (*(_DWORD *)(v81 + 2172) & 0x1000) == 0 ) { Info = PspReferenceTokenForNewProcess((struct _KPROCESS *)Process, (void *)v105[18], PreviousMode, &v105[19]);// 新进程的令牌引用 if ( Info < 0 ) { v105[19] = 0i64; goto LABEL_168; // 结束 } if ( !v105[18] || (int)SeQueryServerSiloToken(v105[19], (__int64)&v92) < 0 || (unsigned __int8)PspIsSiloInSilo(v92, v105[58]) ) { if ( (v105[0] & 0x2000000000i64) != 0 ) { v23 = (v105[0] & 0x2000000000000i64) != 0 ? LOBYTE(v105[48]) : 0; v68 = v23; if ( (NtGlobalFlag & 0x40000) != 0 ) { v95 = *(_OWORD *)&v105[29]; // 读写内核空间 ZwSystemDebugControl(); } LOBYTE(v22) = v23; Info = SeQuerySigningPolicy( (void *)v105[19], (const UNICODE_STRING *)&v105[29], (v14 >> 6) & 1, v22, &v70, &v69, &v68); if ( Info < 0 ) goto LABEL_168; ObjectAttributes.Length = 48; ObjectAttributes.RootDirectory = 0i64; v24 = 1600; if ( PreviousMode != 1 ) v24 = 576; ObjectAttributes.Attributes = v24; ObjectAttributes.ObjectName = (_UNICODE_STRING *)&v105[29]; *(_OWORD *)&ObjectAttributes.SecurityDescriptor = 0i64; Info = 0; if ( qword_140D2D440 ) Info = qword_140D2D440(v105[19]); if ( Info < 0 ) goto LABEL_168; Info = PspGetMemoryPartitionContext(Process, v14, v105[50], HIDWORD(v105[51]), &v83);// 第3个值 可能写 if ( Info < 0 ) goto LABEL_168; Info = PspCreateUserProcessEcp((__int64)&DriverContext, v105[19]);// 有链表操作 if ( Info < 0 ) // 装载文件到内存中加载 goto LABEL_168; Info = IoCreateFileEx( (PHANDLE)&v105[21], LODWORD(v105[20]) | 0x100020, &ObjectAttributes, &IoStatusBlock, 0i64, 0x80u, 5u, 1u, 0x60u, 0i64, 0, CreateFileTypeNone, 0i64, 0, &DriverContext); if ( Info < 0 && LODWORD(v105[20]) ) Info = IoCreateFileEx( (PHANDLE)&v105[21], 0x100020u, &ObjectAttributes, &IoStatusBlock, 0i64, 0x80u, 5u, 1u, 0x60u, 0i64, 0, CreateFileTypeNone, 0i64, 0, &DriverContext); if ( Info < 0 ) { v105[21] = 0i64; v25 = 1; LABEL_57: PspUpdateCreateInfo(v25, (__int64)v105, 0i64); goto LABEL_168; } Object = 0i64; // 获取句柄对象 Info = ObReferenceObjectByHandle( (HANDLE)v105[21], 0x100020u, (POBJECT_TYPE)IoFileObjectType, 0, &Object, 0i64); v105[22] = (__int64)Object; if ( Info < 0 ) { v105[22] = 0i64; v27 = v67; LABEL_171: if ( v83 ) ObfDereferenceObjectWithTag(v83, 0x624A7350u); PspDeleteCreateProcessContext(v105); if ( DriverContext.ExtraCreateParameter ) FsRtlFreeExtraCreateParameterList(DriverContext.ExtraCreateParameter); if ( v27 ) HalPutDmaAdapter(v80); return (unsigned int)Info; } ObjectAttributes.ObjectName = 0i64; v28 = 1; if ( v105[49] ) v28 = 5; *(_DWORD *)&v75[4] = v28; if ( v105[53] ) { v29 = SeDuplicateTokenAndAddOriginClaim(v105[19], v105[53], v105[54], &v80); v30 = (unsigned __int8)v67; if ( v29 >= 0 ) v30 = 1; v67 = v30; v72 = v30; } else { LOBYTE(v30) = v67; } v31 = v80; if ( !(_BYTE)v30 ) v31 = (struct _DMA_ADAPTER *)v105[19]; v80 = v31; v32 = v70; LOBYTE(v26) = v70; for ( i = MmCreateSpecialImageSection(// 更具文件句柄创建文件映射 对pe格式检查 (int)&v105[23], (int)&ObjectAttributes, (int)v31, v26, v105[21], v28); ; i = MmCreateSpecialImageSection( (int)&v105[23], (int)&ObjectAttributes, (int)v80, v41, v105[21], *(int *)&v75[4]) ) { Info = i; if ( i < 0 ) { v105[23] = 0i64; v25 = 2; goto LABEL_57; } v88 = 0i64; // 获取文件映射对象 Info = ObReferenceObjectByHandle((HANDLE)v105[23], 8u, MmSectionObjectType, 0, &v88, 0i64); v105[25] = (__int64)v88; if ( Info < 0 ) { v105[25] = 0i64; goto LABEL_168; } v35 = v68; LOBYTE(v34) = v68; Info = PspGetProcessProtectionRequirementsFromImage(v88, v34, (char *)&v70 + 1); if ( Info < 0 ) goto LABEL_168; LOBYTE(v37) = HIBYTE(v70); if ( HIBYTE(v70) == v35 ) break; // 安全函数 Info = SeQuerySigningPolicy( (void *)v105[19], (const UNICODE_STRING *)&v105[29], 1i64, v37, &v71, &v69, &v68); if ( Info < 0 ) goto LABEL_168; v40 = v71; if ( v71 == v32 ) { v35 = v68; break; } if ( (v32 & 0x30) != 0 && (v71 & 0x30) != (v32 & 0x30) ) goto LABEL_167; if ( !qword_140C1D8E0 ) goto LABEL_167; LOBYTE(v38) = v32; LOBYTE(v39) = v71; if ( !(unsigned int)qword_140C1D8E0(v39, v38) ) goto LABEL_167; ObCloseHandle((HANDLE)v105[23], 0); HalPutDmaAdapter((PADAPTER_OBJECT)v105[25]); v105[23] = 0i64; v105[25] = 0i64; v32 = v40; LOBYTE(v70) = v40; LOBYTE(v41) = v40; } // for循环结束 LOBYTE(v36) = PreviousMode; Info = PspValidateCreateProcessProtection(v81, (int)v105, v36, v14, v35);// 验证进程创建 if ( Info < 0 ) goto LABEL_168; if ( (v14 & 0x40000) != 0 || (v35 & 7) != 1 && (LOBYTE(v44) = v35, LOBYTE(v43) = PreviousMode, LOBYTE(v42) = *(_BYTE *)(v45 + 2170), (unsigned __int8)PspCheckForInvalidAccessByProtection(v43, v42, v44)) ) { LOBYTE(v105[1]) |= 8u; } PspGetProcessParameterOverrides(v105, v83); Info = PspCaptureProcessParameters(PreviousMode, v89, (__int64)v105);// 保存创建进程信息到v105 if ( Info < 0 ) { LOBYTE(v105[1]) &= ~4u; goto LABEL_168; } v46 = v104; v47 = v69; goto LABEL_104; } if ( Process == v81 && PreviousMode && !v89 && (v105[1] & 0xC00) == 0 && (v105[0] & 0x8000000000i64) == 0 && (v105[0] & 0x2000000000000i64) == 0 && (v105[1] & 0x10) == 0 ) { LOBYTE(v105[1]) &= ~4u; v35 = *(_BYTE *)(Process + 2170); v68 = v35; v69 = *(_BYTE *)(Process + 2169); v32 = *(_BYTE *)(Process + 2168); LOBYTE(v70) = v32; if ( (v14 & 0x40) != 0 && (v35 & 7) == 0 ) { Info = -1073741790; goto LABEL_168; } LOBYTE(v21) = PreviousMode; Info = PspValidateCreateProcessProtection(v81, (int)v105, v21, v14, v35); if ( Info < 0 ) goto LABEL_168; v46 = 0i64; LABEL_104: Info = PspAllocateProcess( // 创建进程 v79, PreviousMode, v86, // 可控制 v35, v32, v47, (void *)v105[25], (void *)v105[19], a7, 0, (__int64)v105, v105[18] != 0, v83, (__int64)&v84, &v73); if ( Info < 0 ) goto LABEL_168; v48 = *((_DWORD *)v73 + 629) & 0x4000; v86 = v48 != 0 ? (volatile signed __int32 *)0x800 : 0i64; v49 = (v105[25] != 0 ? 1048587 : 1048603) | 0x100040; if ( !v48 ) v49 = v105[25] != 0 ? 1048587 : 1048603; RtlGetExtendedContextLength2(v49, &v76, v48 != 0 ? 0x800 : 0); v50 = v76 + 15i64; if ( v50 <= v76 ) v50 = 0xFFFFFFFFFFFFFF0i64; v51 = alloca(v50 & 0xFFFFFFFFFFFFFFF0ui64); memset(&v67, 0, v76); RtlInitializeExtendedContext2((__int64)&v67, v49, v94, (unsigned __int64)v86); if ( v105[25] ) // 创建是否成功 { v53 = HIDWORD(v105[28]); if ( !*((_QWORD *)v73 + 176) ) v53 = *((_QWORD *)v73 + 170); // 创建线程环境 PspCreateUserContext((int)&v67, 1, PspUserThreadStart, v105[6], v53); } else { LOBYTE(v52) = 1; // 获取当前线程环境 Info = PspGetContextThreadInternal((int)v82, (int)&v67, 0, v52, 1); if ( Info < 0 ) { v54 = (char *)v73; if ( (_InterlockedExchangeAdd64((volatile signed __int64 *)v73 + 135, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 ) ExfTryToWakePushLock(v54 + 1080); KeAbPostRelease((ULONG_PTR)(v54 + 1080)); KeLeaveCriticalRegionThread(v82); PspRundownSingleProcess((ULONG_PTR)v73); goto LABEL_168; } v88 = (PVOID)297; } ObfReferenceObjectWithTag(v73, 0x72437350u); if ( v46 ) { *(_BYTE *)v46 = 0; v55 = v105[8]; if ( v105[8] < 0x40000ui64 ) v55 = 0x40000i64; v46[3] = v55; v46[2] = v105[9]; v46[1] = LODWORD(v105[7]); } *(_DWORD *)&v75[4] = 0; PspMapThreadCreationFlags(a8, (int *)v75); if ( (_DWORD)v84 ) { *(_DWORD *)&v75[4] = 2; *(_DWORD *)v75 |= 0x10u; } if ( HIDWORD(v84) ) a7 |= 0x400u; v98[0] = (__int64)v100; *(_DWORD *)v75 |= 0x60u; Info = PspAllocateThread( // 创建,初始化线程 (ULONG_PTR)v73, (__int64)&v67, (__int64)v98, 0i64, 0i64, (__int64)v75, (__int64)&v85, (__int64)v46, (__int64)AccessState); if ( Info < 0 ) // 错误 { v57 = (char *)v73; if ( (_InterlockedExchangeAdd64((volatile signed __int64 *)v73 + 135, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 ) ExfTryToWakePushLock(v57 + 1080); KeAbPostRelease((ULONG_PTR)(v57 + 1080)); KeLeaveCriticalRegionThread(v82); PspRundownSingleProcess((ULONG_PTR)v73); v27 = v67; goto LABEL_166; } v58 = v81; LOBYTE(v56) = PreviousMode; v59 = PsTestProtectedProcessIncompatibility(v56, v81, v73); v60 = v78; if ( v59 ) { if ( (v78 & 0x2000000) != 0 ) { v60 = ~*(_DWORD *)&RtlProtectedAccess[12 * ((unsigned __int64)v35 >> 4) + 4] & 0x1FFFFF | v78 & 0xFDFFFFFF; if ( !v105[16] || v58 == v105[16] ) v60 |= 1u; } v61 = v77; if ( (v77 & 0x2000000) != 0 ) { v61 = ~*(_DWORD *)&RtlProtectedAccess[12 * ((unsigned __int64)v35 >> 4) + 8] & 0x1FFFFF | v77 & 0xFDFFFFFF; if ( !v105[16] || v58 == v105[16] ) v61 |= 1u; } } else { v61 = v77; } if ( v105[26] ) v62 = v105[26] + 112; else v62 = 0i64; // 安装进程地址 环境 inserted = PspInsertProcess( (char *)v73, (struct _KPROCESS *)v79, v60, a7, (HANDLE)v105[17], v75[4], v62, (PACCESS_STATE)v102); Info = PspInsertThread( // 安装线程进链表中 v85, (PEPROCESS)v73, v61, (__int64)v46, (__int64)v105, 0i64, (PACCESS_STATE)AccessState, v90, v105[2]); KeLeaveCriticalRegionThread(v82); if ( inserted < 0 ) { PspRundownSingleProcess((ULONG_PTR)v73); Info = inserted; v27 = v67; LABEL_165: HalPutDmaAdapter(v85); LABEL_166: ObfDereferenceObjectWithTag(v73, 0x72437350u);// 释放句柄 goto LABEL_169; } if ( Info < 0 ) { v27 = v67; LABEL_163: if ( Info >= 0 ) goto LABEL_165; LABEL_164: PsTerminateProcess(v73, (unsigned int)Info); goto LABEL_165; } ProcessServerSilo = PsGetProcessServerSilo(v73); if ( ProcessServerSilo != v105[58] ) { Info = -1073741267; v27 = v67; goto LABEL_164; } Info = PspCreateObjectHandle(v73, (__int64)v102, (struct _OBJECT_TYPE *)PsProcessType); if ( Info < 0 ) { v27 = v67; } else { v65 = (_OWORD *)v105[4]; if ( v105[4] ) { *(_OWORD *)v105[4] = *(_OWORD *)&v105[6]; v65[1] = *(_OWORD *)&v105[8]; v65[2] = *(_OWORD *)&v105[10]; v65[3] = *(_OWORD *)&v105[12]; } *v91 = *(_QWORD *)&v102[392]; // a1 取地址 v27 = v67; Info = PspUpdateCreateInfo(6, (__int64)v105, (__int64)v73); if ( Info >= 0 ) goto LABEL_161; if ( (*(_WORD *)&v102[384] & 0x200) != 0 || (v66 = 1, (*(_DWORD *)(v58 + 2172) & 0x1000) != 0) ) v66 = 0; ObCloseHandle(*(HANDLE *)&v102[392], v66); } if ( (*(_WORD *)&AccessState[384] & 0x200) != 0 || (*(_DWORD *)(v58 + 2172) & 0x1000) != 0 ) v20 = 0; ObCloseHandle(*(HANDLE *)&AccessState[392], v20); LABEL_161: SepDeleteAccessState(v102); // 失败会调用 清除新进程 SeReleaseSubjectContext((PSECURITY_SUBJECT_CONTEXT)&v102[32]); goto LABEL_163; } } } LABEL_167: Info = -1073741811; goto LABEL_168; } Info = ObpReferenceObjectByHandleWithTag( v105[15], 128, (__int64)PsProcessType, PreviousMode, 0x72437350u, &v79, 0i64, 0i64); if ( Info >= 0 ) { Process = v79; v105[16] = v79; goto LABEL_33; } } LABEL_168: v27 = v67; LABEL_169: if ( v105[22] ) SeDeleteCodeIntegrityOriginClaimForFileObject(); goto LABEL_171; } return result; } /* Orphan comments: 创建进程 */