1、分析Win10 64位CreateRemoteThread
具体流程。
2、分析为什么无法直接在系统进程中创建远程线程。
通过分析整个函数调用流程可以得到这么几个结果:
1、创建远程线程和普通线程没有本质的区别,其调用的函数都是相同的,唯一的区别就是在进程句柄上,进程句柄为-1是创建普通线程。调用的函数根据这个区别就可以对两种线程分别处理了。
2、在用户模式下执行的代码主要还是为了在进入内核模式前准备所需的各种信息参数。在内核模式中的代码最为重要,是完成线程创建的关键代码。
3、在CreateRemoteThead
调用的整个流程中没有对系统进程进行权限的检查,所以可以认为权限检查的关键代码在OpenProcess
中。如果需要在系统进程中创建远程线程就必须在获取进程句柄前进行提权处理。提权方案:
通过WinDbg查看函数CreateRemoteThead
在用户模式下的调用流程,观察这个调用情况可以确定在用户模式下,这个函数涉及到了三个dll模块(KERNEL32、KERNELBASE、ntdll)。而CreateRemoteThead
这个API在KERNEL32模块中真正的函数名是CreateRemoteThreadStub
,通过这个KERNEL32中的CreateRemoteThreadStub
API将参数转发到KERNELBASE模块中的CreateRemoteThreadEx
中,然后在KERNELBASE中调用ntdll模块中的NtCreateThreadEx
API,进入内核。待内核处理结束后获取返回值,进行返回值的处理并返回结果。
用户调用CreateRemoteThread
API后,会进入KERNEL32模块中的CreateRemoteThreadStub
,参数相同,而CreateRemoteThreadStub
则会对CreateRemoteThread
的参数进行一些处理,由原来的7个参数扩展到了8个参数,并且对dwCreationFlags参数进行了一些安全处理,规避了系统规定参数外的无效参数。然后将参数转发到KERNELBASE模块。
这个API主要是为了给内核模式准备所需的参数的,所以这是执行CreateRemoteThread
在用户模式下的最后一个API,然后就会调用ntdll模块中的NtCreateThreadEx
进入内核模式执行内核代码,待内核代码执行完成后,将执行结果返回给用户模式,CreateRemoteThread
就会获取执行结果,并将结果处理完毕后一层一层的返回给调用者。
从以下代码可以看出,在进入内核前需要判断标志位(地址:ds:7FFE0308h
),如果最低位为1则使用syscall
指令进入内核,否则使用int 2Eh
中断进入内核。至于这个地址具体是干什么的待日后分析。从程序的执行流程可以知道,我们进入内核使用的是syscall
。
当程序进入内核模式后,使用三环的调试器就会跑飞,完全不知道程序执行到了哪里,这时就需要使用WinDbg使用内核模式进行调试了。知道程序在内核中一定会进入NT模块下的NtCreateThreadEx
内核函数,所以只需要在这里下进程断点等待调用就行。调用后就会得到该内核函数的调用栈,知道他进入内核都经过了哪些系统调用。盲猜nt!KiSystemServiceCopyEnd
一定就是系统的分发函数了。
以下就是该函数的调用栈:
可以清楚的看出从用户模式到内核模式的全过程:
在nt模块下查找KiSystemServiceCopyEnd
这个内核函数时发现,这根本不是一个函数名,而是一个地址标签,是在一个叫nt!KiSystemCall64
的内核函数中的地址标签。再看这个函数的调用方式是一个call寄存器的方式,也就说明rax寄存器是一个存放NtCreateThreadEx
地址的寄存器,该值需要在KiSystemCall64
中提前计算好才能使用,调用后就会成功进入目标内核函数。
在调用rax之前还有一段代码看起来像是在拷贝函数的栈空间,而且拷贝了14个,盲猜系统内核函数最大的参数数也就是14个参数了,这也就清楚为什么这个地址叫系统服务拷贝了。
这个函数因为内核功底基本没有,所以只能大概分析。首先检查参数判断是否是有效参数,然后判断线程句柄是否在一个正确的区间内,如果不在就修改句柄值。之后就是准备线程的上下文环境,通过句柄和tag获取线程对象。最后就是调用PspCreateThread
开始正式创建线程。待结果返回后释放资源。 总的来说这个函数就是在内核模式为创建进程准备需要用到的参数,没有实际的功能。真正的创建是在PspCreateThread
中,从该函数的前两个字母前缀就可以知道这个内核函数属性进程相关的内核函数。
在内核中进入了创建线程的关键节点,内核代码也越来越费解了,因此只能对这个内核函数进行一些合理的猜想假设。通过函数名获取了一些信息,可以知道操作线程需要上锁进行安全保护,线程中还有临界区保护。线程的存储结构是一个图,在分配线程后需要插入图完成创建。该内核函数调用了一个疑似处理远程线程的内核函数,但分析参数可以确定该参数不是一个变量而是而是一个常量,是通过上层函数传入的0得来的。所以可以暂时确定他没有对远程线程进行有效处理。如果需要确定还得继续学习内核知识。目前可以猜测在内核模式是不区分远程线程的,远程线程只是在用户模式的概念。
如果要验证普通进程和远程在内核中没有区别,就必须知道Kernel32模块是如何处理的,于是将IDA定位到Kernel32模块的CreateThreadStub
API,然而让我震惊的一幕出现了:
我的猜想是这样的:
结果它是这样的:
这么看来前面有些代码的分析就会出现不小的偏差,创建远程线程与创建普通线程最本质的区别是进入KERNEL32!CreateRemoteThreadStub
时的进程句柄有明显的区别,远程线程的进程句柄是正常的,而普通线程的进程句柄是-1。浏览上面的分析发现,不管是在用户模式还是在内核模式都对远程线程与普通线程的创建进行了区别处理。微软取名字的水平真会误导人啊。具体是怎么处理的还需要进一步的学习内核基础知识。
当我们发现创建远程线程与普通线程这一点区别后,是否可以这么做?使用CreateRemoteThread
去创建普通线程,这其实很简单,只需要将进程句柄传为-1即可。说干就干,上代码:
运行结果如下:
果然可以!
本文的分析完全是个人在科锐学习期间的项目,不具有权威性。由于是刚开始接触内核编程不久,对内核的对象、句柄、权限一无所知。大部分分析结果可能与实际情况有着不小的偏差,待以后补充完相关知识再做修改,文中的错误也希望各路内核大佬多多指出,必定会做出改正。
分析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
/
/
{
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
/
/
{
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
.
/
/
begin_rev
/
/
end_rev
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
);
/
/
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直播授课