DuplicateHandle进程间传递
2023-10-24
15
0
学习USBIP的代码时,学到了新的知识。https://www.usbzh.com/article/detail-320.html
在应用层通过DuplicateHandle传递句柄给子进程,这样可以实现过继句柄。
主进程中:
static int
execute_attacher(HANDLE hdev, SOCKET sockfd, int rhport)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE hRead, hWrite;
HANDLE hdev_attacher, sockfd_attacher;
BOOL res;
int ret = ERR_GENERAL;
if (!create_pipe(&hRead, &hWrite))
return ERR_GENERAL;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.hStdInput = hRead;
si.dwFlags = STARTF_USESTDHANDLES;
ZeroMemory(&pi, sizeof(pi));
res = CreateProcess("attacher.exe", "attacher.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
if (!res) {
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND)
ret = ERR_NOTEXIST;
dbg("failed to create process: 0x%lx", err);
goto out;
}
res = DuplicateHandle(GetCurrentProcess(), hdev, pi.hProcess, &hdev_attacher, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (!res) {
dbg("failed to dup hdev: 0x%lx", GetLastError());
goto out_proc;
}
res = DuplicateHandle(GetCurrentProcess(), (HANDLE)sockfd, pi.hProcess, &sockfd_attacher, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (!res) {
dbg("failed to dup sockfd: 0x%lx", GetLastError());
goto out_proc;
}
if (!write_handle_value(hWrite, hdev_attacher) || !write_handle_value(hWrite, sockfd_attacher))
goto out_proc;
ret = 0;
out_proc:
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
out:
CloseHandle(hRead);
CloseHandle(hWrite);
return ret;
}
创建子进程需要的管道,然后使用DuplicateHandle将主进程的需要dump的两个句柄sockfd和hdev复制出来,并写入管道中去。
在子进程中,通过打开管道读取句柄,实现子进程的功能。
static HANDLE
read_handle_value(HANDLE hStdin)
{
HANDLE handle;
LPBYTE buf = (LPBYTE)&handle;
DWORD buflen = sizeof(HANDLE);
while (buflen > 0) {
DWORD nread;
if (!ReadFile(hStdin, buf + sizeof(HANDLE) - buflen, buflen, &nread, NULL)) {
return INVALID_HANDLE_VALUE;
}
if (nread == 0)
return INVALID_HANDLE_VALUE;
buflen -= nread;
}
return handle;
}
static BOOL
setup_forwarder(void)
{
HANDLE hdev, sockfd;
HANDLE hStdin, hStdout;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hdev = read_handle_value(hStdin);
sockfd = read_handle_value(hStdin);
usbip_forward(hdev, sockfd, FALSE);
CloseHandle(hStdin);
CloseHandle(hStdout);
return TRUE;
}
int APIENTRY
wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
if (!setup_forwarder())
return 1;
return 0;
}
通过usbip_forward实现子进程的业务。