首页
社区
课程
招聘
[原创]CreateRemoteThread和CreateThread 流程逆向分析从R3到R0
发表于: 2022-2-3 22:15 18395

[原创]CreateRemoteThread和CreateThread 流程逆向分析从R3到R0

2022-2-3 22:15
18395

  1、分析Win10 64位CreateRemoteThread具体流程。
  2、分析为什么无法直接在系统进程中创建远程线程。

通过分析整个函数调用流程可以得到这么几个结果:
  1、创建远程线程和普通线程没有本质的区别,其调用的函数都是相同的,唯一的区别就是在进程句柄上,进程句柄为-1是创建普通线程。调用的函数根据这个区别就可以对两种线程分别处理了。
  2、在用户模式下执行的代码主要还是为了在进入内核模式前准备所需的各种信息参数。在内核模式中的代码最为重要,是完成线程创建的关键代码。
  3、在CreateRemoteThead调用的整个流程中没有对系统进程进行权限的检查,所以可以认为权限检查的关键代码在OpenProcess中。如果需要在系统进程中创建远程线程就必须在获取进程句柄前进行提权处理。提权方案:

  通过WinDbg查看函数CreateRemoteThead在用户模式下的调用流程,观察这个调用情况可以确定在用户模式下,这个函数涉及到了三个dll模块(KERNEL32、KERNELBASE、ntdll)。而CreateRemoteThead这个API在KERNEL32模块中真正的函数名是CreateRemoteThreadStub,通过这个KERNEL32中的CreateRemoteThreadStubAPI将参数转发到KERNELBASE模块中的CreateRemoteThreadEx中,然后在KERNELBASE中调用ntdll模块中的NtCreateThreadExAPI,进入内核。待内核处理结束后获取返回值,进行返回值的处理并返回结果。

流程图1

  用户调用CreateRemoteThreadAPI后,会进入KERNEL32模块中的CreateRemoteThreadStub,参数相同,而CreateRemoteThreadStub则会对CreateRemoteThread的参数进行一些处理,由原来的7个参数扩展到了8个参数,并且对dwCreationFlags参数进行了一些安全处理,规避了系统规定参数外的无效参数。然后将参数转发到KERNELBASE模块。

  这个API主要是为了给内核模式准备所需的参数的,所以这是执行CreateRemoteThread在用户模式下的最后一个API,然后就会调用ntdll模块中的NtCreateThreadEx进入内核模式执行内核代码,待内核代码执行完成后,将执行结果返回给用户模式,CreateRemoteThread就会获取执行结果,并将结果处理完毕后一层一层的返回给调用者。

流程图3

  从以下代码可以看出,在进入内核前需要判断标志位(地址:ds:7FFE0308h),如果最低位为1则使用syscall指令进入内核,否则使用int 2Eh中断进入内核。至于这个地址具体是干什么的待日后分析。从程序的执行流程可以知道,我们进入内核使用的是syscall

  当程序进入内核模式后,使用三环的调试器就会跑飞,完全不知道程序执行到了哪里,这时就需要使用WinDbg使用内核模式进行调试了。知道程序在内核中一定会进入NT模块下的NtCreateThreadEx内核函数,所以只需要在这里下进程断点等待调用就行。调用后就会得到该内核函数的调用栈,知道他进入内核都经过了哪些系统调用。盲猜nt!KiSystemServiceCopyEnd一定就是系统的分发函数了。
  以下就是该函数的调用栈:

流程图4

   可以清楚的看出从用户模式到内核模式的全过程:
流程图2
  在nt模块下查找KiSystemServiceCopyEnd这个内核函数时发现,这根本不是一个函数名,而是一个地址标签,是在一个叫nt!KiSystemCall64的内核函数中的地址标签。再看这个函数的调用方式是一个call寄存器的方式,也就说明rax寄存器是一个存放NtCreateThreadEx地址的寄存器,该值需要在KiSystemCall64中提前计算好才能使用,调用后就会成功进入目标内核函数。
流程图3
   在调用rax之前还有一段代码看起来像是在拷贝函数的栈空间,而且拷贝了14个,盲猜系统内核函数最大的参数数也就是14个参数了,这也就清楚为什么这个地址叫系统服务拷贝了。

流程图6

  这个函数因为内核功底基本没有,所以只能大概分析。首先检查参数判断是否是有效参数,然后判断线程句柄是否在一个正确的区间内,如果不在就修改句柄值。之后就是准备线程的上下文环境,通过句柄和tag获取线程对象。最后就是调用PspCreateThread开始正式创建线程。待结果返回后释放资源。 总的来说这个函数就是在内核模式为创建进程准备需要用到的参数,没有实际的功能。真正的创建是在PspCreateThread中,从该函数的前两个字母前缀就可以知道这个内核函数属性进程相关的内核函数。

  在内核中进入了创建线程的关键节点,内核代码也越来越费解了,因此只能对这个内核函数进行一些合理的猜想假设。通过函数名获取了一些信息,可以知道操作线程需要上锁进行安全保护,线程中还有临界区保护。线程的存储结构是一个图,在分配线程后需要插入图完成创建。该内核函数调用了一个疑似处理远程线程的内核函数,但分析参数可以确定该参数不是一个变量而是而是一个常量,是通过上层函数传入的0得来的。所以可以暂时确定他没有对远程线程进行有效处理。如果需要确定还得继续学习内核知识。目前可以猜测在内核模式是不区分远程线程的,远程线程只是在用户模式的概念。

  如果要验证普通进程和远程在内核中没有区别,就必须知道Kernel32模块是如何处理的,于是将IDA定位到Kernel32模块的CreateThreadStubAPI,然而让我震惊的一幕出现了:

流程图7
我的猜想是这样的:
流程图8
结果它是这样的:
流程图9
  这么看来前面有些代码的分析就会出现不小的偏差,创建远程线程与创建普通线程最本质的区别是进入KERNEL32!CreateRemoteThreadStub时的进程句柄有明显的区别,远程线程的进程句柄是正常的,而普通线程的进程句柄是-1。浏览上面的分析发现,不管是在用户模式还是在内核模式都对远程线程与普通线程的创建进行了区别处理。微软取名字的水平真会误导人啊。具体是怎么处理的还需要进一步的学习内核基础知识。

  当我们发现创建远程线程与普通线程这一点区别后,是否可以这么做?使用CreateRemoteThread去创建普通线程,这其实很简单,只需要将进程句柄传为-1即可。说干就干,上代码:

运行结果如下:
流程图10
果然可以!

  本文的分析完全是个人在科锐学习期间的项目,不具有权威性。由于是刚开始接触内核编程不久,对内核的对象、句柄、权限一无所知。大部分分析结果可能与实际情况有着不小的偏差,待以后补充完相关知识再做修改,文中的错误也希望各路内核大佬多多指出,必定会做出改正。
  分析Windows内核实在是没有足够的资料进行学习,这里也希望大佬们指点下学习方法。

//在OpenProcess前调用即可
BOOL KtSetDebugPrivilege(HANDLE ProcessHandle, BOOL IsEnable)
{
    DWORD  LastError = 0;
    HANDLE TokenHandle = 0;
 
    if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
    {
        LastError = GetLastError();
        if (TokenHandle)
        {
            CloseHandle(TokenHandle);
        }
        return LastError;
    }
    TOKEN_PRIVILEGES TokenPrivileges;
    memset(&TokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES));
    LUID v1;//权限类型,本地独有标识
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &v1))
    {
        LastError = GetLastError();
        CloseHandle(TokenHandle);
        return LastError;
    }
    TokenPrivileges.PrivilegeCount = 1;
    TokenPrivileges.Privileges[0].Luid = v1;
    if (IsEnable)
    {
        TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    }
    else
    {
        TokenPrivileges.Privileges[0].Attributes = 0;
    }
    AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
    LastError = GetLastError();
    CloseHandle(TokenHandle);
    return LastError;
}
//在OpenProcess前调用即可
BOOL KtSetDebugPrivilege(HANDLE ProcessHandle, BOOL IsEnable)
{
    DWORD  LastError = 0;
    HANDLE TokenHandle = 0;
 
    if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
    {
        LastError = GetLastError();
        if (TokenHandle)
        {
            CloseHandle(TokenHandle);
        }
        return LastError;
    }
    TOKEN_PRIVILEGES TokenPrivileges;
    memset(&TokenPrivileges, 0, sizeof(TOKEN_PRIVILEGES));
    LUID v1;//权限类型,本地独有标识
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &v1))
    {
        LastError = GetLastError();
        CloseHandle(TokenHandle);
        return LastError;
    }
    TokenPrivileges.PrivilegeCount = 1;
    TokenPrivileges.Privileges[0].Luid = v1;
    if (IsEnable)
    {
        TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    }
    else
    {
        TokenPrivileges.Privileges[0].Attributes = 0;
    }
    AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
    LastError = GetLastError();
    CloseHandle(TokenHandle);
    return LastError;
}
 
 
0:000> wt
Tracing KERNEL32!CreateRemoteThreadStub to return address 00007ff7`3f741220
   11     0 0] KERNEL32!CreateRemoteThreadStub
   32     0 1]   KERNELBASE!CreateRemoteThreadEx
   25     0 2]     KERNELBASE!BaseFormatObjectAttributes
   67    25 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtDuplicateObject
>> More than one level popped 1 -> 1
   77    31 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtQueryInformationProcess
>> More than one level popped 1 -> 1
   94    37 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtQueryInformationProcess
>> More than one level popped 1 -> 1
  139    43 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtCreateThreadEx
>> More than one level popped 1 -> 1
  158    49 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtClose
>> More than one level popped 1 -> 1
  167    55 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     KERNELBASE!_security_check_cookie
  174    61 1]   KERNELBASE!CreateRemoteThreadEx
   14   235 0] KERNEL32!CreateRemoteThreadStub
 
249 instructions were executed in 248 events (0 from other threads)
 
Function Name                               Invocations MinInst MaxInst AvgInst
KERNEL32!CreateRemoteThreadStub                       1      14      14      14
KERNELBASE!BaseFormatObjectAttributes                 1      25      25      25
KERNELBASE!CreateRemoteThreadEx                       1     174     174     174
KERNELBASE!_security_check_cookie                     1       6       6       6
ntdll!NtClose                                         1       6       6       6
ntdll!NtCreateThreadEx                                1       6       6       6
ntdll!NtDuplicateObject                               1       6       6       6
ntdll!NtQueryInformationProcess                       2       6       6       6
 
5 system calls were executed
 
Calls  System Call
    1  ntdll!NtClose
    1  ntdll!NtCreateThreadEx
    1  ntdll!NtDuplicateObject
    2  ntdll!NtQueryInformationProcess
0:000> wt
Tracing KERNEL32!CreateRemoteThreadStub to return address 00007ff7`3f741220
   11     0 0] KERNEL32!CreateRemoteThreadStub
   32     0 1]   KERNELBASE!CreateRemoteThreadEx
   25     0 2]     KERNELBASE!BaseFormatObjectAttributes
   67    25 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtDuplicateObject
>> More than one level popped 1 -> 1
   77    31 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtQueryInformationProcess
>> More than one level popped 1 -> 1
   94    37 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtQueryInformationProcess
>> More than one level popped 1 -> 1
  139    43 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtCreateThreadEx
>> More than one level popped 1 -> 1
  158    49 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     ntdll!NtClose
>> More than one level popped 1 -> 1
  167    55 1]   KERNELBASE!CreateRemoteThreadEx
    6     0 2]     KERNELBASE!_security_check_cookie
  174    61 1]   KERNELBASE!CreateRemoteThreadEx
   14   235 0] KERNEL32!CreateRemoteThreadStub
 
249 instructions were executed in 248 events (0 from other threads)
 
Function Name                               Invocations MinInst MaxInst AvgInst
KERNEL32!CreateRemoteThreadStub                       1      14      14      14
KERNELBASE!BaseFormatObjectAttributes                 1      25      25      25
KERNELBASE!CreateRemoteThreadEx                       1     174     174     174
KERNELBASE!_security_check_cookie                     1       6       6       6
ntdll!NtClose                                         1       6       6       6
ntdll!NtCreateThreadEx                                1       6       6       6
ntdll!NtDuplicateObject                               1       6       6       6
ntdll!NtQueryInformationProcess                       2       6       6       6
 
5 system calls were executed
 
Calls  System Call
    1  ntdll!NtClose
    1  ntdll!NtCreateThreadEx
    1  ntdll!NtDuplicateObject
    2  ntdll!NtQueryInformationProcess
.text:000000018003AB20 ; HANDLE __stdcall CreateRemoteThreadStub(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
.text:000000018003AB20                 public CreateRemoteThreadStub
.text:000000018003AB20 CreateRemoteThreadStub proc near        ; DATA XREF: .rdata:0000000180085477↓o
.text:000000018003AB20                                         ; .rdata:off_18009A208↓o ...
.text:000000018003AB20
.text:000000018003AB20 lpParameter     = qword ptr  28h
.text:000000018003AB20 dwCreationFlags = dword ptr  30h
.text:000000018003AB20 lpThreadId      = qword ptr  38h
.text:000000018003AB20
.text:000000018003AB20                 mov     r11, rsp            ; r11存储原来的rsp用来传参
.text:000000018003AB23                 sub     rsp, 48h            ; 栈抬高,用来存储参数
.text:000000018003AB27                 mov     r10d, [rsp+48h+dwCreationFlags]   
.text:000000018003AB2C                 mov     rax, [rsp+48h+lpThreadId]
.text:000000018003AB34                 and     r10d, 10004h   
.text:000000018003AB3B                 mov     [r11-10h], rax            ;    参数8 = lpThreadId
.text:000000018003AB3F                 and     qword ptr [r11-18h], 0    ;    参数7(扩展参数) = 0
.text:000000018003AB44                 mov     rax, [rsp+48h+lpParameter]
.text:000000018003AB49                 mov     [r11-20h], r10d            ;    参数6 = dwCreationFlags & 0x10004h
.text:000000018003AB4D                 mov     [r11-28h], rax            ;    参数5 = lpParameter
.text:000000018003AB51                 call    cs:__imp_CreateRemoteThreadEx
.text:000000018003AB58                 nop     dword ptr [rax+rax+00h]
.text:000000018003AB5D                 add     rsp, 48h
.text:000000018003AB61                 retn
.text:000000018003AB61 ; ---------------------------------------------------------------------------
.text:000000018003AB62                 db 0CCh
.text:000000018003AB62 CreateRemoteThreadStub endp
.text:000000018003AB20 ; HANDLE __stdcall CreateRemoteThreadStub(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
.text:000000018003AB20                 public CreateRemoteThreadStub
.text:000000018003AB20 CreateRemoteThreadStub proc near        ; DATA XREF: .rdata:0000000180085477↓o
.text:000000018003AB20                                         ; .rdata:off_18009A208↓o ...
.text:000000018003AB20
.text:000000018003AB20 lpParameter     = qword ptr  28h
.text:000000018003AB20 dwCreationFlags = dword ptr  30h
.text:000000018003AB20 lpThreadId      = qword ptr  38h
.text:000000018003AB20
.text:000000018003AB20                 mov     r11, rsp            ; r11存储原来的rsp用来传参
.text:000000018003AB23                 sub     rsp, 48h            ; 栈抬高,用来存储参数
.text:000000018003AB27                 mov     r10d, [rsp+48h+dwCreationFlags]   
.text:000000018003AB2C                 mov     rax, [rsp+48h+lpThreadId]
.text:000000018003AB34                 and     r10d, 10004h   
.text:000000018003AB3B                 mov     [r11-10h], rax            ;    参数8 = lpThreadId
.text:000000018003AB3F                 and     qword ptr [r11-18h], 0    ;    参数7(扩展参数) = 0
.text:000000018003AB44                 mov     rax, [rsp+48h+lpParameter]
.text:000000018003AB49                 mov     [r11-20h], r10d            ;    参数6 = dwCreationFlags & 0x10004h
.text:000000018003AB4D                 mov     [r11-28h], rax            ;    参数5 = lpParameter
.text:000000018003AB51                 call    cs:__imp_CreateRemoteThreadEx
.text:000000018003AB58                 nop     dword ptr [rax+rax+00h]
.text:000000018003AB5D                 add     rsp, 48h
.text:000000018003AB61                 retn
.text:000000018003AB61 ; ---------------------------------------------------------------------------
.text:000000018003AB62                 db 0CCh
.text:000000018003AB62 CreateRemoteThreadStub endp
HANDLE __stdcall CreateRemoteThreadEx(HANDLE a_hProcess, LPSECURITY_ATTRIBUTES a_lpThreadAttributes, SIZE_T a_dwStackSize, LPTHREAD_START_ROUTINE a_lpStartAddress, LPVOID a_lpParameter, DWORD a_dwCreationFlags, LPPROC_THREAD_ATTRIBUTE_LIST a_lpAttributeList, LPDWORD a_lpThreadId)
{
  int nRet; // eax
  DWORD v_nFlag; // er15
  char bFlag; // si
  NTSTATUS NtRet6; // eax
  NTSTATUS NtRet5; // ebx
  int v_bIsSuspendThread2; // edx
  SIZE_T v_dwStackSize1; // rax
  HMODULE v_hModule_csrsrv; // rax
  __int64 (__fastcall *v_lpfuncCsrCreateRemoteThread)(HANDLE, CLIENT_ID *); // rax
  NTSTATUS NtRet2; // eax
  NTSTATUS NtRet4; // eax
  NTSTATUS NtRet3; // ecx
  NTSTATUS NtRet1; // ebx
  int v23; // [rsp+A0h] [rbp-548h]
  char v_bIsSuspendThread1; // [rsp+B0h] [rbp-538h]
  char v_bflag; // [rsp+B1h] [rbp-537h]
  HANDLE v_ThreadHandle; // [rsp+B8h] [rbp-530h] BYREF
  __int64 v27; // [rsp+C0h] [rbp-528h] BYREF
  HANDLE v_hProcessHandle; // [rsp+C8h] [rbp-520h] BYREF
  PVOID Context[2]; // [rsp+D0h] [rbp-518h] BYREF
  PACTIVATION_CONTEXT_STACK Stack; // [rsp+E0h] [rbp-508h] BYREF
  int v31; // [rsp+E8h] [rbp-500h] BYREF
  PTEB Teb; // [rsp+F0h] [rbp-4F8h] BYREF
  ULONG SuspendCount; // [rsp+F8h] [rbp-4F0h] BYREF
  SIZE_T v_dwStackSize; // [rsp+100h] [rbp-4E8h]
  LPVOID v_lpParameter; // [rsp+108h] [rbp-4E0h]
  LPTHREAD_START_ROUTINE v_lpStartAddress; // [rsp+110h] [rbp-4D8h]
  __int64 v_ThreadAttributes; // [rsp+118h] [rbp-4D0h] BYREF
  CLIENT_ID v_tagClientID; // [rsp+120h] [rbp-4C8h] BYREF
  unsigned __int64 Cookie; // [rsp+130h] [rbp-4B8h] BYREF
  PROCESS_BASIC_INFORMATION v_tagProcessInformation; // [rsp+138h] [rbp-4B0h] BYREF
  SECTION_IMAGE_INFORMATION v_tagSectionImageinformation; // [rsp+170h] [rbp-478h] BYREF
  __int64 v42; // [rsp+1B0h] [rbp-438h] BYREF
  __int64 v_aryAttributeList[122]; // [rsp+1E0h] [rbp-408h] BYREF
  void *retaddr; // [rsp+5E8h] [rbp+0h]
 
//=========================================================================================
 
  v_lpStartAddress = a_lpStartAddress;
  v_dwStackSize = a_dwStackSize;
  v_lpParameter = a_lpParameter;
  v_bflag = 0;
  *(_OWORD *)Context = 0i64;
  Stack = 0i64;
  v_tagClientID = 0i64;
  v_bIsSuspendThread1 = 0;
  v_ThreadHandle = 0i64;
  if ( (a_dwCreationFlags & 0xFFFEFFFB) != 0 // 检查a_dwCreationFlags是否被传入了无效参数,如果参数无效返回错误 0xC000000D(STATUS_INVALID_PARAMETER)
  {
    NtRet3 = -1073741811;
FUNC_END_ERROR:
    BaseSetLastNTError(NtRet3);
    return 0i64;
  }
  nRet = BaseFormatObjectAttributes(&v42, a_lpThreadAttributes, 0i64, &v_ThreadAttributes);// 通过lpThreadAttributes参数格式化v_ThreadAttributes参数,为三环进0环做准备
  if ( nRet < 0 )                               // 检查返回值是否有效,小于0返回错误
    goto LABEL_49;
  v_aryAttributeList[1] = 65539i64;
  v_aryAttributeList[2] = 16i64;
  v_aryAttributeList[4] = 0i64;
  v_aryAttributeList[3] = (__int64)&v_tagClientID;
  v_aryAttributeList[5] = 65540i64;
  v_aryAttributeList[6] = 8i64;
  v_aryAttributeList[8] = 0i64;
  v_aryAttributeList[7] = (__int64)&Teb;
  LODWORD(v27) = 2;
  if ( a_lpAttributeList )                      // 判断是否有扩展参数列表,如果有扩展参数列表就使用BasepConvertWin32AttributeList进行转换
  {
    v23 = 30;
    nRet = BasepConvertWin32AttributeList(
             (int *)a_lpAttributeList,
             1,
             (__int64)&v31,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             (__int64)v_aryAttributeList,
             (__int64)&v27,
             v23);
    if ( nRet < 0 )                             // 检查是否转换成功,如果nRet<0返回失败
    {
LABEL_49:
      NtRet3 = nRet;
      goto FUNC_END_ERROR;
    }
  }
  v_aryAttributeList[0] = 32i64 * (unsigned int)v27 + 8;// 给index=0的位置赋值, 如果没有扩展参数该值为: 2*32 + 8 = 72
  v_nFlag = a_dwCreationFlags & 0x10000;        // 给标志赋值: INHERIT_PARENT_AFFINITY(继承)=1
                                                //            其他 = 0
  v_hProcessHandle = 0i64;
  bFlag = 1;
  if ( a_hProcess != (HANDLE)-1i64 )            // 判断句柄是否是-1
                                                // #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  {
    if ( NtDuplicateObject(                     // 将进程句柄复制一份,为内核准备参数,并将句柄的引用数+1
           (HANDLE)0xFFFFFFFFFFFFFFFFi64,
           a_hProcess,
           (HANDLE)0xFFFFFFFFFFFFFFFFi64,
           &v_hProcessHandle,
           0x402u,
           0,
           0) >= 0 )
      a_hProcess = v_hProcessHandle;            // 如果句柄复制成功,传入内核
    NtRet1 = NtQueryInformationProcess(a_hProcess, ProcessBasicInformation, &v_tagProcessInformation, 0x30u, 0i64);// 检索指向可用于确定指定进程是否正在调试的 PEB 结构的指针,以及系统用于标识指定进程的唯一值。
    if ( NtRet1 >= 0 && (HANDLE)v_tagProcessInformation.UniqueProcessId != NtCurrentTeb()->ClientId.UniqueProcess )// 判断句柄是否属于当前的进程(用来区分是否是远程线程创建)
    {
      bFlag = 0;
      NtRet1 = NtQueryInformationProcess(
                 a_hProcess,
                 ProcessImageInformation,
                 &v_tagSectionImageinformation,
                 0x40u,
                 0i64);                         // 调用函数获取hProcess的SECTION_IMAGE_INFORMATION结构
      if ( NtRet1 >= 0 && v_tagSectionImageinformation.SubSystemType - 2 > 1 )
        NtRet1 = -1073741823;                   // 如果返回值正确,但是SubSystemType类型错误,返回0xC0000001‬(STATUS_UNSUCCESSFUL)
    }
    if ( NtRet1 < 0 )                           // 如果返回错误,关闭句柄,返回错误信息
    {
      if ( v_hProcessHandle )
        NtClose(v_hProcessHandle);
      NtRet3 = NtRet1;
      goto FUNC_END_ERROR;
    }
  }
  if ( bFlag )
  {
    NtRet6 = RtlQueryInformationActivationContext(1u, 0i64, 0i64, 1u, Context, 0x10ui64, 0i64);
    NtRet5 = NtRet6;
    if ( NtRet6 < 0 )
    {                                           // 函数返回值错误,释放资源并返回
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlQueryInformationActivationContext() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet6);
      goto RELEASE_RET;
    }
    if ( !g_bFlag && !NtCurrentTeb()->SubProcessTag && (!Context[0] || ((__int64)Context[1] & 1) != 0) )
    {
      v_bIsSuspendThread1 = 0;
      goto LABEL_11;
    }
    v_bIsSuspendThread1 = 1;
  }
  if ( !v_bIsSuspendThread1 )
  {
LABEL_11:
    v_bIsSuspendThread2 = 0;
    if ( (a_dwCreationFlags & 4) == 0 )
      goto LABEL_17;
  }
  v_bIsSuspendThread2 = 1;
LABEL_17:
  v31 = v_bIsSuspendThread2;
  v_dwStackSize1 = v_dwStackSize;
  if ( v_nFlag )
    v_dwStackSize1 = 0i64;
  NtRet5 = NtCreateThreadEx(                    // 进入内核创建线程
             &v_ThreadHandle,                   // _Out_ PHANDLE ThreadHandle,
             0x1FFFFFi64,                       // _In_ ACCESS_MASK DesiredAccess,  STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL
             v_ThreadAttributes,                // _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
             a_hProcess,                        // _In_ HANDLE ProcessHandle,
             v_lpStartAddress,                  // _In_ PVOID StartRoutine,
             v_lpParameter,                     // _In_opt_ PVOID Argument,
             v_bIsSuspendThread2,               // _In_ ULONG CreateFlags,   挂起线程或者正常 THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
             0i64,                              // _In_opt_ ULONG_PTR ZeroBits,
             v_dwStackSize1,                    // _In_opt_ SIZE_T StackSize,
             v_dwStackSize & -(__int64)(v_nFlag != 0),// _In_opt_ SIZE_T MaximumStackSize,  如果是通过父进程创建最大栈大小不变,否则为0
             v_aryAttributeList);               // _In_opt_ PVOID AttributeList
  if ( NtRet5 < 0 )
    goto RELEASE_RET;
  if ( !v_bIsSuspendThread1 )
    goto LABEL_21;
  if ( NtCurrentTeb()->SubProcessTag )
    Teb->SubProcessTag = NtCurrentTeb()->SubProcessTag;
  if ( Context[0] && ((__int64)Context[1] & 1) == 0 )
  {
    NtRet2 = RtlAllocateActivationContextStack(&Stack);// 分配可激活的线程上下文栈
    NtRet5 = NtRet2;
    if ( NtRet2 < 0 )
    {
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlAllocateActivationContextStack() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet2);
      goto RELEASE_RET;
    }
    Teb->ActivationContextStackPointer = Stack;
    NtRet4 = RtlActivateActivationContextEx(1u, Teb, Context[0], &Cookie);// 激活线程上下文
    NtRet5 = NtRet4;
    if ( NtRet4 < 0 )
    {
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlActivateActivationContextEx() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet4);
      goto RELEASE_RET;
    }
    v_bflag = 1;
  }
  if ( !g_bFlag
    || (v_hModule_csrsrv = GetModuleHandleA("csrsrv"),// 获取模块句柄
        (v_lpfuncCsrCreateRemoteThread = (__int64 (__fastcall *)(HANDLE, CLIENT_ID *))GetProcAddressForCaller(// 获取函数地址
                                                                                        v_hModule_csrsrv,
                                                                                        "CsrCreateRemoteThread",
                                                                                        retaddr)) == 0i64)
    || (NtRet5 = v_lpfuncCsrCreateRemoteThread(v_ThreadHandle, &v_tagClientID), NtRet5 >= 0) )// 调用函数,将线程句柄传入获取ClientID
                                                // CsrCreateRemoteThread例程为不属于当前NT进程的NT线程创建CSR线程对象
  {
LABEL_21:
    if ( a_lpThreadId )
      *a_lpThreadId = (DWORD)v_tagClientID.UniqueThread;// 获取线程ID
    if ( v_bIsSuspendThread1 && (a_dwCreationFlags & 4) == 0 )// CREATE_SUSPENDED 0x00000004
                                                // 创建线程时,挂起标志为1,并且标志参数表示不挂起,恢复线程状态,修改线程挂起数量
      NtResumeThread(v_ThreadHandle, &SuspendCount);
  }
RELEASE_RET:
  if ( Context[0] )
    RtlReleaseActivationContext(Context[0]);    // 释放线程上下文
  if ( v_hProcessHandle )                       // 关闭进程句柄
    NtClose(v_hProcessHandle);
  if ( NtRet5 < 0 )
  {
    if ( v_bflag && Context[0] )
      RtlReleaseActivationContext(Context[0]);
    if ( Stack )
      RtlFreeActivationContextStack(Stack);     // 释放栈空间
    if ( v_ThreadHandle )
    {
      NtTerminateThread(v_ThreadHandle, NtRet5);// 终止线程
      NtClose(v_ThreadHandle);
    }
    BaseSetLastNTError(NtRet5);                 // 设置NT错误信息
    v_ThreadHandle = 0i64;
  }
  return v_ThreadHandle;                        // 返回线程句柄
}
HANDLE __stdcall CreateRemoteThreadEx(HANDLE a_hProcess, LPSECURITY_ATTRIBUTES a_lpThreadAttributes, SIZE_T a_dwStackSize, LPTHREAD_START_ROUTINE a_lpStartAddress, LPVOID a_lpParameter, DWORD a_dwCreationFlags, LPPROC_THREAD_ATTRIBUTE_LIST a_lpAttributeList, LPDWORD a_lpThreadId)
{
  int nRet; // eax
  DWORD v_nFlag; // er15
  char bFlag; // si
  NTSTATUS NtRet6; // eax
  NTSTATUS NtRet5; // ebx
  int v_bIsSuspendThread2; // edx
  SIZE_T v_dwStackSize1; // rax
  HMODULE v_hModule_csrsrv; // rax
  __int64 (__fastcall *v_lpfuncCsrCreateRemoteThread)(HANDLE, CLIENT_ID *); // rax
  NTSTATUS NtRet2; // eax
  NTSTATUS NtRet4; // eax
  NTSTATUS NtRet3; // ecx
  NTSTATUS NtRet1; // ebx
  int v23; // [rsp+A0h] [rbp-548h]
  char v_bIsSuspendThread1; // [rsp+B0h] [rbp-538h]
  char v_bflag; // [rsp+B1h] [rbp-537h]
  HANDLE v_ThreadHandle; // [rsp+B8h] [rbp-530h] BYREF
  __int64 v27; // [rsp+C0h] [rbp-528h] BYREF
  HANDLE v_hProcessHandle; // [rsp+C8h] [rbp-520h] BYREF
  PVOID Context[2]; // [rsp+D0h] [rbp-518h] BYREF
  PACTIVATION_CONTEXT_STACK Stack; // [rsp+E0h] [rbp-508h] BYREF
  int v31; // [rsp+E8h] [rbp-500h] BYREF
  PTEB Teb; // [rsp+F0h] [rbp-4F8h] BYREF
  ULONG SuspendCount; // [rsp+F8h] [rbp-4F0h] BYREF
  SIZE_T v_dwStackSize; // [rsp+100h] [rbp-4E8h]
  LPVOID v_lpParameter; // [rsp+108h] [rbp-4E0h]
  LPTHREAD_START_ROUTINE v_lpStartAddress; // [rsp+110h] [rbp-4D8h]
  __int64 v_ThreadAttributes; // [rsp+118h] [rbp-4D0h] BYREF
  CLIENT_ID v_tagClientID; // [rsp+120h] [rbp-4C8h] BYREF
  unsigned __int64 Cookie; // [rsp+130h] [rbp-4B8h] BYREF
  PROCESS_BASIC_INFORMATION v_tagProcessInformation; // [rsp+138h] [rbp-4B0h] BYREF
  SECTION_IMAGE_INFORMATION v_tagSectionImageinformation; // [rsp+170h] [rbp-478h] BYREF
  __int64 v42; // [rsp+1B0h] [rbp-438h] BYREF
  __int64 v_aryAttributeList[122]; // [rsp+1E0h] [rbp-408h] BYREF
  void *retaddr; // [rsp+5E8h] [rbp+0h]
 
//=========================================================================================
 
  v_lpStartAddress = a_lpStartAddress;
  v_dwStackSize = a_dwStackSize;
  v_lpParameter = a_lpParameter;
  v_bflag = 0;
  *(_OWORD *)Context = 0i64;
  Stack = 0i64;
  v_tagClientID = 0i64;
  v_bIsSuspendThread1 = 0;
  v_ThreadHandle = 0i64;
  if ( (a_dwCreationFlags & 0xFFFEFFFB) != 0 // 检查a_dwCreationFlags是否被传入了无效参数,如果参数无效返回错误 0xC000000D(STATUS_INVALID_PARAMETER)
  {
    NtRet3 = -1073741811;
FUNC_END_ERROR:
    BaseSetLastNTError(NtRet3);
    return 0i64;
  }
  nRet = BaseFormatObjectAttributes(&v42, a_lpThreadAttributes, 0i64, &v_ThreadAttributes);// 通过lpThreadAttributes参数格式化v_ThreadAttributes参数,为三环进0环做准备
  if ( nRet < 0 )                               // 检查返回值是否有效,小于0返回错误
    goto LABEL_49;
  v_aryAttributeList[1] = 65539i64;
  v_aryAttributeList[2] = 16i64;
  v_aryAttributeList[4] = 0i64;
  v_aryAttributeList[3] = (__int64)&v_tagClientID;
  v_aryAttributeList[5] = 65540i64;
  v_aryAttributeList[6] = 8i64;
  v_aryAttributeList[8] = 0i64;
  v_aryAttributeList[7] = (__int64)&Teb;
  LODWORD(v27) = 2;
  if ( a_lpAttributeList )                      // 判断是否有扩展参数列表,如果有扩展参数列表就使用BasepConvertWin32AttributeList进行转换
  {
    v23 = 30;
    nRet = BasepConvertWin32AttributeList(
             (int *)a_lpAttributeList,
             1,
             (__int64)&v31,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             0i64,
             (__int64)v_aryAttributeList,
             (__int64)&v27,
             v23);
    if ( nRet < 0 )                             // 检查是否转换成功,如果nRet<0返回失败
    {
LABEL_49:
      NtRet3 = nRet;
      goto FUNC_END_ERROR;
    }
  }
  v_aryAttributeList[0] = 32i64 * (unsigned int)v27 + 8;// 给index=0的位置赋值, 如果没有扩展参数该值为: 2*32 + 8 = 72
  v_nFlag = a_dwCreationFlags & 0x10000;        // 给标志赋值: INHERIT_PARENT_AFFINITY(继承)=1
                                                //            其他 = 0
  v_hProcessHandle = 0i64;
  bFlag = 1;
  if ( a_hProcess != (HANDLE)-1i64 )            // 判断句柄是否是-1
                                                // #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  {
    if ( NtDuplicateObject(                     // 将进程句柄复制一份,为内核准备参数,并将句柄的引用数+1
           (HANDLE)0xFFFFFFFFFFFFFFFFi64,
           a_hProcess,
           (HANDLE)0xFFFFFFFFFFFFFFFFi64,
           &v_hProcessHandle,
           0x402u,
           0,
           0) >= 0 )
      a_hProcess = v_hProcessHandle;            // 如果句柄复制成功,传入内核
    NtRet1 = NtQueryInformationProcess(a_hProcess, ProcessBasicInformation, &v_tagProcessInformation, 0x30u, 0i64);// 检索指向可用于确定指定进程是否正在调试的 PEB 结构的指针,以及系统用于标识指定进程的唯一值。
    if ( NtRet1 >= 0 && (HANDLE)v_tagProcessInformation.UniqueProcessId != NtCurrentTeb()->ClientId.UniqueProcess )// 判断句柄是否属于当前的进程(用来区分是否是远程线程创建)
    {
      bFlag = 0;
      NtRet1 = NtQueryInformationProcess(
                 a_hProcess,
                 ProcessImageInformation,
                 &v_tagSectionImageinformation,
                 0x40u,
                 0i64);                         // 调用函数获取hProcess的SECTION_IMAGE_INFORMATION结构
      if ( NtRet1 >= 0 && v_tagSectionImageinformation.SubSystemType - 2 > 1 )
        NtRet1 = -1073741823;                   // 如果返回值正确,但是SubSystemType类型错误,返回0xC0000001‬(STATUS_UNSUCCESSFUL)
    }
    if ( NtRet1 < 0 )                           // 如果返回错误,关闭句柄,返回错误信息
    {
      if ( v_hProcessHandle )
        NtClose(v_hProcessHandle);
      NtRet3 = NtRet1;
      goto FUNC_END_ERROR;
    }
  }
  if ( bFlag )
  {
    NtRet6 = RtlQueryInformationActivationContext(1u, 0i64, 0i64, 1u, Context, 0x10ui64, 0i64);
    NtRet5 = NtRet6;
    if ( NtRet6 < 0 )
    {                                           // 函数返回值错误,释放资源并返回
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlQueryInformationActivationContext() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet6);
      goto RELEASE_RET;
    }
    if ( !g_bFlag && !NtCurrentTeb()->SubProcessTag && (!Context[0] || ((__int64)Context[1] & 1) != 0) )
    {
      v_bIsSuspendThread1 = 0;
      goto LABEL_11;
    }
    v_bIsSuspendThread1 = 1;
  }
  if ( !v_bIsSuspendThread1 )
  {
LABEL_11:
    v_bIsSuspendThread2 = 0;
    if ( (a_dwCreationFlags & 4) == 0 )
      goto LABEL_17;
  }
  v_bIsSuspendThread2 = 1;
LABEL_17:
  v31 = v_bIsSuspendThread2;
  v_dwStackSize1 = v_dwStackSize;
  if ( v_nFlag )
    v_dwStackSize1 = 0i64;
  NtRet5 = NtCreateThreadEx(                    // 进入内核创建线程
             &v_ThreadHandle,                   // _Out_ PHANDLE ThreadHandle,
             0x1FFFFFi64,                       // _In_ ACCESS_MASK DesiredAccess,  STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL
             v_ThreadAttributes,                // _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
             a_hProcess,                        // _In_ HANDLE ProcessHandle,
             v_lpStartAddress,                  // _In_ PVOID StartRoutine,
             v_lpParameter,                     // _In_opt_ PVOID Argument,
             v_bIsSuspendThread2,               // _In_ ULONG CreateFlags,   挂起线程或者正常 THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
             0i64,                              // _In_opt_ ULONG_PTR ZeroBits,
             v_dwStackSize1,                    // _In_opt_ SIZE_T StackSize,
             v_dwStackSize & -(__int64)(v_nFlag != 0),// _In_opt_ SIZE_T MaximumStackSize,  如果是通过父进程创建最大栈大小不变,否则为0
             v_aryAttributeList);               // _In_opt_ PVOID AttributeList
  if ( NtRet5 < 0 )
    goto RELEASE_RET;
  if ( !v_bIsSuspendThread1 )
    goto LABEL_21;
  if ( NtCurrentTeb()->SubProcessTag )
    Teb->SubProcessTag = NtCurrentTeb()->SubProcessTag;
  if ( Context[0] && ((__int64)Context[1] & 1) == 0 )
  {
    NtRet2 = RtlAllocateActivationContextStack(&Stack);// 分配可激活的线程上下文栈
    NtRet5 = NtRet2;
    if ( NtRet2 < 0 )
    {
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlAllocateActivationContextStack() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet2);
      goto RELEASE_RET;
    }
    Teb->ActivationContextStackPointer = Stack;
    NtRet4 = RtlActivateActivationContextEx(1u, Teb, Context[0], &Cookie);// 激活线程上下文
    NtRet5 = NtRet4;
    if ( NtRet4 < 0 )
    {
      DbgPrint_0(
        "SXS: %s - Failing thread create because RtlActivateActivationContextEx() failed with status %08lx\n",
        "CreateRemoteThreadEx",
        (unsigned int)NtRet4);
      goto RELEASE_RET;
    }
    v_bflag = 1;
  }
  if ( !g_bFlag
    || (v_hModule_csrsrv = GetModuleHandleA("csrsrv"),// 获取模块句柄
        (v_lpfuncCsrCreateRemoteThread = (__int64 (__fastcall *)(HANDLE, CLIENT_ID *))GetProcAddressForCaller(// 获取函数地址
                                                                                        v_hModule_csrsrv,
                                                                                        "CsrCreateRemoteThread",
                                                                                        retaddr)) == 0i64)
    || (NtRet5 = v_lpfuncCsrCreateRemoteThread(v_ThreadHandle, &v_tagClientID), NtRet5 >= 0) )// 调用函数,将线程句柄传入获取ClientID
                                                // CsrCreateRemoteThread例程为不属于当前NT进程的NT线程创建CSR线程对象
  {
LABEL_21:
    if ( a_lpThreadId )
      *a_lpThreadId = (DWORD)v_tagClientID.UniqueThread;// 获取线程ID
    if ( v_bIsSuspendThread1 && (a_dwCreationFlags & 4) == 0 )// CREATE_SUSPENDED 0x00000004
                                                // 创建线程时,挂起标志为1,并且标志参数表示不挂起,恢复线程状态,修改线程挂起数量
      NtResumeThread(v_ThreadHandle, &SuspendCount);
  }
RELEASE_RET:
  if ( Context[0] )
    RtlReleaseActivationContext(Context[0]);    // 释放线程上下文
  if ( v_hProcessHandle )                       // 关闭进程句柄
    NtClose(v_hProcessHandle);
  if ( NtRet5 < 0 )
  {
    if ( v_bflag && Context[0] )
      RtlReleaseActivationContext(Context[0]);
    if ( Stack )
      RtlFreeActivationContextStack(Stack);     // 释放栈空间
    if ( v_ThreadHandle )
    {
      NtTerminateThread(v_ThreadHandle, NtRet5);// 终止线程
      NtClose(v_ThreadHandle);
    }
    BaseSetLastNTError(NtRet5);                 // 设置NT错误信息
    v_ThreadHandle = 0i64;
  }
  return v_ThreadHandle;                        // 返回线程句柄
}
//0x40 bytes (sizeof)  未公共 https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1909%2019H2%20(November%202019%20Update)/_SECTION_IMAGE_INFORMATION
typedef struct _SECTION_IMAGE_INFORMATION
{
    VOID* TransferAddress;                                                  //0x0
    ULONG ZeroBits;                                                         //0x8
    ULONGLONG MaximumStackSize;                                             //0x10
    ULONGLONG CommittedStackSize;                                           //0x18
    ULONG SubSystemType;                                                    //0x20
    union
    {
        struct
        {
            USHORT SubSystemMinorVersion;                                   //0x24
            USHORT SubSystemMajorVersion;                                   //0x26
        };
        ULONG SubSystemVersion;                                             //0x24
    };
    union
    {
        struct
        {
            USHORT MajorOperatingSystemVersion;                             //0x28
            USHORT MinorOperatingSystemVersion;                             //0x2a
        };
        ULONG OperatingSystemVersion;                                       //0x28
    };
    USHORT ImageCharacteristics;                                            //0x2c
    USHORT DllCharacteristics;                                              //0x2e
    USHORT Machine;                                                         //0x30
    UCHAR ImageContainsCode;                                                //0x32
    union
    {
        UCHAR ImageFlags;                                                   //0x33
        struct
        {
            UCHAR ComPlusNativeReady:1;                                     //0x33
            UCHAR ComPlusILOnly:1;                                          //0x33
            UCHAR ImageDynamicallyRelocated:1;                              //0x33
            UCHAR ImageMappedFlat:1;                                        //0x33
            UCHAR BaseBelow4gb:1;                                           //0x33
            UCHAR ComPlusPrefer32bit:1;                                     //0x33
            UCHAR Reserved:2;                                               //0x33
        };
    };
    ULONG LoaderFlags;                                                      //0x34
    ULONG ImageFileSize;                                                    //0x38
    ULONG CheckSum;                                                         //0x3c
}SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
 
//公开
typedef struct _PROCESS_BASIC_INFORMATION {
    NTSTATUS ExitStatus;
    PPEB PebBaseAddress;
    ULONG_PTR AffinityMask;
    KPRIORITY BasePriority;
    ULONG_PTR UniqueProcessId;
    ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION;
 
 
// Subsystem Values in Microsoft SDK and avaiable in <winnt.h> header file.
 
#define IMAGE_SUBSYSTEM_UNKNOWN              0   // Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE               1   // Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI          2   // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI          3   // Image runs in the Windows character subsystem.
#define IMAGE_SUBSYSTEM_OS2_CUI              5   // image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI            7   // image runs in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS       8   // image is a native Win9x driver.
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI       9   // Image runs in the Windows CE subsystem.
#define IMAGE_SUBSYSTEM_EFI_APPLICATION      10  //
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER  11   //
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER   12  //
#define IMAGE_SUBSYSTEM_EFI_ROM              13
#define IMAGE_SUBSYSTEM_XBOX                 14
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16
 
 
 
 
// begin_rev
#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 // ?
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004
#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010 // ?
#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020 // ?
#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080
// end_rev
#if (PHNT_VERSION >= PHNT_VISTA)
NTSYSCALLAPI
NTSTATUS
NTAPI
NtCreateThreadEx(
    _Out_ PHANDLE ThreadHandle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
    _In_ HANDLE ProcessHandle,
    _In_ PVOID StartRoutine, // PUSER_THREAD_START_ROUTINE
    _In_opt_ PVOID Argument,
    _In_ ULONG CreateFlags, // THREAD_CREATE_FLAGS_*
    _In_ SIZE_T ZeroBits,
    _In_ SIZE_T StackSize,
    _In_ SIZE_T MaximumStackSize,
    _In_opt_ PPS_ATTRIBUTE_LIST AttributeList
    );
#endif
//0x40 bytes (sizeof)  未公共 https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1909%2019H2%20(November%202019%20Update)/_SECTION_IMAGE_INFORMATION
typedef struct _SECTION_IMAGE_INFORMATION
{
    VOID* TransferAddress;                                                  //0x0
    ULONG ZeroBits;                                                         //0x8
    ULONGLONG MaximumStackSize;                                             //0x10
    ULONGLONG CommittedStackSize;                                           //0x18
    ULONG SubSystemType;                                                    //0x20
    union
    {
        struct
        {
            USHORT SubSystemMinorVersion;                                   //0x24
            USHORT SubSystemMajorVersion;                                   //0x26
        };
        ULONG SubSystemVersion;                                             //0x24
    };
    union
    {
        struct
        {
            USHORT MajorOperatingSystemVersion;                             //0x28
            USHORT MinorOperatingSystemVersion;                             //0x2a
        };
        ULONG OperatingSystemVersion;                                       //0x28
    };
    USHORT ImageCharacteristics;                                            //0x2c
    USHORT DllCharacteristics;                                              //0x2e
    USHORT Machine;                                                         //0x30
    UCHAR ImageContainsCode;                                                //0x32
    union
    {
        UCHAR ImageFlags;                                                   //0x33
        struct
        {
            UCHAR ComPlusNativeReady:1;                                     //0x33
            UCHAR ComPlusILOnly:1;                                          //0x33
            UCHAR ImageDynamicallyRelocated:1;                              //0x33
            UCHAR ImageMappedFlat:1;                                        //0x33

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 11
支持
分享
最新回复 (8)
雪    币: 2058
活跃值: (1651)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

虽然搞有些小游戏的辅助的时候经常createremoteThread(-1,xxxxxx)不过还真没细究过内部的实现。涨知识了。感谢分享

最后于 2022-2-4 18:05 被youxiaxy编辑 ,原因:
2022-2-4 18:04
1
雪    币: 4154
活跃值: (1535)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
-1是一个预定义的伪句柄,代表当前进程的句柄,常用宏函数NtCurrentProcess()和win32 api函数GetCurrentProcess()来引用它。类似的还有GetCurrentThread()等
2022-2-6 02:09
1
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
问一下,是科锐的线下班吗?
2022-2-25 10:27
0
雪    币: 129
活跃值: (333)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xed
5
不错,。标记一下~~~
2022-3-22 20:17
0
雪    币: 1810
活跃值: (4020)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好,mark
2022-3-22 21:00
0
雪    币: 2141
活跃值: (5173)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
感谢po主,不过有些错误,有少量误导人的注释
2022-9-5 15:06
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
可以关注下 CR3 的变化 线程在哪使用主要取决于CR3 看看 线程创建的时候用的是 当前进程的CR3 还是 目标进程的CR3 
2022-10-8 13:44
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
创建线程的精髓就在PspCreateThread里面,你却一笔带过了
2022-11-28 16:17
0
游客
登录 | 注册 方可回帖
返回
//