当我调用
GetStdHandle()
(或其他对我的进程执行某些操作的函数)时,例如:
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetStdHandle()
将返回我的进程的STDOUT
句柄,但是这个函数如何知道我的进程是什么,我的意思是我没有给它进程id作为参数。
好吧,让我们假设您需要传递进程 ID。你会怎样做呢?
DWORD my_id = GetCurrentProcessId();
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE, my_id);
显然,如果我们要多次调用它,我们可以通过将其放入辅助函数中来节省一些重复的工作:
HANDLE MyGetStdHandle(DWORD nStdHandle)
{
DWORD my_id = GetCurrentProcessId();
return GetStdHandle(STD_OUTPUT_HANDLE, my_id);
}
但是,很多人都需要这个功能。也许我们应该把它放入一个库......或者一个API......事实上,我们只需将它添加到Windows API并调用它GetStdHandle()即可。
他们做到了。
(好吧,它实际上并不是这样工作的,但我认为它说明了这一点。Windows API has 知道您从哪个进程调用它,否则它无法执行任何事情。 )
嗯,在 Windows 中,每个线程都有一个线程环境块,存储在 CPU 段中,例如 x86 上的
fs
和 x64 上的 gs
。 https://learn.microsoft.com/en-us/windows/win32/debug/thread-environment-block--debugging-notes-
在线程环境块内有进程环境块,https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm存储了
RTL_USER_PROCESS_PARAMETER
。
这是他们存储标准句柄的地方,https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/rtl_user_process_parameters.htm?ts=0,159.
所以
GetStdHandle(STD_OUTPUT_HANDLE)
返回NtCurrentPeb()->ProcessParameter->StandardOutput
等等。
在 x64 上组装
%define NtCurrentPeb gs:[0x60]
%define ProcessParameter 32
%define StandardOutput 40
mov rax, NtCurrentPeb()
mov rax, ProcessParameter[rax]
mov rax, StandardOutput[rax]