zoukankan      html  css  js  c++  java
  • Windows核心编程笔记之内核对象

    0x01 子进程继承父进程内核对象句柄

    • 父进程
    #include <Windows.h>
    #include <iostream>
    #include <strsafe.h>
    using namespace std;
    
    /*
    	父进程用于模拟子进程通讯,向子进程传递内核对象
    */
    
    int main(int argc, char *argv[])
    {
    	/*
    		创建一个内核对象
    	*/
    
    	SECURITY_ATTRIBUTES KerObjSec = { 0 };
    	KerObjSec.bInheritHandle = TRUE;												// 设置内核对象句柄为可继承
    	KerObjSec.nLength = sizeof(KerObjSec); KerObjSec.lpSecurityDescriptor = NULL;	// 安全属性为默认
    	HANDLE KernelObj = CreateMutex(&KerObjSec, TRUE, TEXT("KernelObj"));			// 创建一个内核对象为 KernelObj
    
    	/*
    		创建进程
    	*/
    
    	WCHAR Program[] = L"D:\test.exe"; WCHAR CmdLine[20] = { 0 };										// 设置可执行模块的名称,并且初始化命令行参数
    	STARTUPINFO StartUpInfo = { 0 }; PROCESS_INFORMATION ProcessInformation;
    	StringCchPrintf((STRSAFE_LPWSTR)CmdLine, sizeof(CmdLine) / 2, TEXT("D:\test.exe %x"), KernelObj);	// 格式化命令行字符串
    
    	SECURITY_ATTRIBUTES ProcessSec = { 0 }; SECURITY_ATTRIBUTES ThreadSec = { 0 };		// 初始化子线程和子线程的 SECURITY_ATTRIBUTES 结构体
    	ProcessSec.lpSecurityDescriptor = NULL; ProcessSec.nLength = sizeof(ProcessSec);
    	ProcessSec.bInheritHandle = TRUE;													// 设置子进程可继承父进程句柄表									
    
    	ThreadSec.lpSecurityDescriptor = NULL; ThreadSec.nLength = sizeof(ThreadSec);
    	ThreadSec.bInheritHandle = FALSE;
    
    	cout << "
    开始创建子进程
    " << endl;
    	// 当内核对象和子进程都设置为可继承时,子进程才可以操作内核对象
    	BOOL Process = CreateProcess((LPCWSTR)&Program, (LPWSTR)&CmdLine, &ProcessSec,
    		&ThreadSec, TRUE, NULL, NULL, NULL, &StartUpInfo, &ProcessInformation			// 设置子进程可以继承句柄
    	);
    
    	if (Process == 0) cout << "CreateProcess 错误代码: " << GetLastError() << endl;		// 如果调用失败打印错误代码
    	return 0;
    }
    
    • 子进程
    #include <Windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	if (argc == 2)
    	{
    		cout << "Now In child process!" << endl;				
    		char Buffer[20] = { 0 }; DWORD FatherHandle = NULL;		// 创建转换的内存缓冲区区域
    		memcpy(Buffer, argv[1], 4);								// 接收父进程传来的内核对象句柄
    		sscanf_s(Buffer, "%x", &FatherHandle);					// 将字符串转换为 HANDLE 句柄
    		HANDLE res = (HANDLE)FatherHandle;						
    		if (CloseHandle(res))									// 若父进程内核对象句柄不可继承,则转入 else 语句
    			cout << "对象句柄已经删除" << endl;
    		else
    			cout << "对象句柄不可删除" << endl;
    	}
    	return 0;
    }
    
    • 当内核对象和子进程都设置为可继承时,子进程才可以操作内核对象
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 反之则不可以
      在这里插入图片描述
      在这里插入图片描述

    0x02 创建进程间共享内核对象

    • 父进程
    #include <Windows.h>
    #include <iostream>
    #include <strsafe.h>
    using namespace std;
    
    /*
    	父进程用于模拟子进程通讯,向子进程传递内核对象
    */
    
    int main(int argc, char *argv[])
    {
    	/*
    		创建一个了可继承的内核对象
    	*/
    
    	SECURITY_ATTRIBUTES KerObjSec = { 0 };
    	KerObjSec.bInheritHandle = FALSE; 
    	KerObjSec.nLength = sizeof(KerObjSec); 
    	KerObjSec.lpSecurityDescriptor = NULL;
    
    	HANDLE KernelObj = CreateMutex(&KerObjSec, TRUE, TEXT("KernelObj-kb5j-bs36-55kv"));			
    
    	/*
    		创建进程
    	*/
    								
    	STARTUPINFO StartUpInfo = { 0 }; PROCESS_INFORMATION ProcessInformation;
    
    	SECURITY_ATTRIBUTES ProcessSec = { 0 };		// 初始化子线程和子线程的 SECURITY_ATTRIBUTES 结构体
    	SECURITY_ATTRIBUTES ThreadSec = { 0 };
    	ProcessSec.lpSecurityDescriptor = NULL; 
    	ProcessSec.nLength = sizeof(ProcessSec);
    	ProcessSec.bInheritHandle = TRUE;			// 设置子进程可继承父进程句柄表									
    
    	ThreadSec.lpSecurityDescriptor = NULL; 
    	ThreadSec.nLength = sizeof(ThreadSec);
    	ThreadSec.bInheritHandle = FALSE;
    	WCHAR Program[] = L"D:\test.exe";
    
    	cout << "
    开始创建子进程
    " << endl;
    	BOOL Process = CreateProcess((LPCWSTR)&Program, NULL , &ProcessSec, &ThreadSec,
    		TRUE, NULL, NULL, NULL, &StartUpInfo, &ProcessInformation						// 设置子进程可以继承句柄
    	);
    
    	if (Process == 0) cout << "CreateProcess 错误代码: " << GetLastError() << endl;		// 如果调用失败打印错误代码
    	return 0;
    }
    
    • 子进程
    #include <Windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	if (OpenMutex(MUTEX_ALL_ACCESS, TRUE, TEXT("KernelObj-kb5j-bs36-55kv")))
    		cout << "内核对象已经被创建没有与之对应的内核对象" << endl;
    	else
    		cout << "没有与之对应的内核对象" << endl;
    	return 0;
    }
    

    0x03 获取进程 SessionId 和检测进程是否有副本

    #include <Windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	DWORD ProcessId = GetCurrentProcessId();
    	DWORD SessionId = NULL;
    	if (ProcessIdToSessionId(ProcessId, &SessionId))
    		cout << " ProcessId: " << ProcessId << " - SessionId: " << SessionId << endl;
    	else
    		cout << "调用失败,错误代码: " << GetLastError() << endl;
    	return 0;
    }
    
    #include <Windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	HANDLE KernelObj = CreateMutex(NULL, FALSE,	TEXT("KernelObj"));
    	if (GetLastError() == ERROR_ALREADY_EXISTS) {
    		cout << "进程已存在,新生成进程 ID: " << GetCurrentProcessId() << endl;
    		CloseHandle(KernelObj);
    	}
    	while (true)
    		Sleep(20);
    	return(0);
    }
    
    • 借助 Process Explore 工具也可以看出其创建过程
      在这里插入图片描述

    0x04 DuplicateHandle 获取当前进程的真实句柄

    #include <Windows.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	HANDLE DupProcessHandle = NULL;
    	BOOL res = DuplicateHandle(
    		GetCurrentProcess(),	// 复制句柄的进程,这里是当前进程
    		GetCurrentProcess(),	// 复制的句柄,这里复制当前进程伪句柄
    		GetCurrentProcess(),	// 复制到哪一个进程,这里复制到当前进程
    		&DupProcessHandle,		// 将复制的句柄传递给一个 HANDLE 变量,如果第二个参数传递的是伪句柄,那么这个函数会把它转换成真实的句柄
    		0, FALSE, DUPLICATE_SAME_ACCESS
    	);
    	// 由于只是把当前进程的伪句柄复制到当前进程,所以只是使用了 DupProcessHandle 函数转换伪句柄的功能,并没有用进程间复制句柄的功能
    	if (res)
    	{
    		cout << "[*] 当前进程的真实句柄为: " << DupProcessHandle    << endl;
    		cout << "[*] 当前进程的伪造句柄为: " << GetCurrentProcess() << endl;
    	}
    	return(0);
    }
    
    
    • DuplicateHandle 在进行进程间复制时,若子进程需要使用复制的内核对象,仍然需要通过命令行或者 IPC 等将内核句柄值传递给子进程
  • 相关阅读:
    面向对象之三个基本特征(javaScript)
    webpack初探
    浅谈Promise
    Vue Mixin 与微信小程序 Mixins 应用
    C#入门基础语法知识点总结(变量、运算符、类型转换)
    C#入门基础语法知识点总结(.NET开发环境及代码编写规范)
    触发器练习三
    触发器练习二
    触发器练习一
    存储过程练习二
  • 原文地址:https://www.cnblogs.com/csnd/p/11800526.html
Copyright © 2011-2022 走看看