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 << "\n开始创建子进程\n" << 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 << "\n开始创建子进程\n" << 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 等将内核句柄值传递给子进程
Windows核心编程笔记之内核对象的更多相关文章
- Windows核心编程笔记之作业
创建作业,并加以限制 HANDLE WINAPI CreateJob() { BOOL IsInJob = FALSE; DWORD ErrorCode = NULL; // 不能将已经在作业中的进程 ...
- Windows核心编程笔记之处理字符串
0x01 ANSI 和宽字符定义 // ANSI 字符定义 CHAR varChar_1 = 'a'; // #typedef char CHAR CHAR varChar_2[] = "A ...
- Windows核心编程笔记之进程
改变进程基址,获取进程基址 #include <Windows.h> #include <iostream> #include <strsafe.h> #inclu ...
- Windows核心编程笔记之错误处理
0x01 GetLastError() 函数用于获取上一个操作的错误代码 #include <Windows.h> #include <iostream> using name ...
- windows核心编程---第八章 使用内核对象进行线程同步
使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...
- Windows核心编程学习九:利用内核对象进行线程同步
注:源码为学习<Windows核心编程>的一些尝试,非原创.若能有助于一二访客,幸甚. 1.程序框架 #include "Queue.h" #include <t ...
- 《Windows核心编程》读书笔记 上
[C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 【转】《windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
随机推荐
- 读 Kafka 源码写优雅业务代码:配置类
这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一剑! 往期文章 Kafka 探险 ...
- Vue 插槽之插槽内容学习总结
插槽内容使用方法介绍 父组件中引用支持插槽内容的子组件,形如以下(假设子组件为NavigationLink.vue) <navigation-link url="/profile&qu ...
- VSCode 微信小程序扩展开发
写在前面 为什么要开发这个扩展呢,是因为微信开发者工具自身不支持页面引入组件的跳转,人工根据引入组件路径查看对应代码的方式,效率偏低.就形如这样的json文件,引入了多个组件,比如要查看 " ...
- python学习之基础内容
python基础内容① 什么是python? -一种计算机语言,计算机语言分为 -高级语言:python.java.Ruby.C#.C++...... -基础语言:C语言.汇编 -计算机可以直接执行基 ...
- 2019HDU多校第七场 HDU6651 Final Exam
一.题目 Final Exam 二.分析 题目说的比较绕,总之一定要记住,$n$个题目都可以做,至少作对$k$到,但是做题目的人不知道每道题对应的分数. 作为出题人,如果他是田忌,肯定不会去在做题目的 ...
- jqgrid 实现表格随select框内容改变而刷新
要实现的功能如下:当选择框选择数据源由原始数据切换到组合后数据时,界面左侧jqgrid表格随之改变.效果如下: 实现代码: 界面顶部select选择框:要点是用localStory将选择框的选择信息记 ...
- Win 10 下Pipenv源码安装 odoo12
因为,本身电脑已经安装odoo8,9,10等odoo的版本,当时,没有考虑是直接是统一的环境很配置. 现在,在odoo11的环境下,需要Python 3的语言环境可以很好地支持odoo11的功能,所以 ...
- 开源的 Switch 模拟器——GitHub 热点速览 v.21.12
作者:HelloGitHub-小鱼干 脸滚键盘操作选手小鱼干这里要推荐一个超酷 Switch 模拟器,不能埋没你的游戏天赋.Ryujinx 是一个 C# 写的 Switch 模拟器,1700+ 游戏可 ...
- 从谷歌CRE谈起,运维如何培养服务意识?
从谷歌CRE谈起,运维如何培养服务意识? 2016年10月,谷歌云平台博客(Google Cloud Platform Blog)上更新了一篇文章,谷歌宣布了一个新的专业岗位,CRE(Customer ...
- Linux命令的应用
目录 Linux命令 Linux文件管理命令 用户管理 权限管理 vi文本编辑器 find查找命令 磁盘管理命令 压缩及解压 Linux 进程 Linux运行tomcat Linux安装mysql 卸 ...