创建线程的方式打开记事本

2023-09-20 06:53:23

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验


今天操作系统课老师讲到进程,提出了一个有趣的小实验:能否以系统调用的方式利用 Windows 创建进程的系统调用函数来打开一个软件。闲着蛋疼的我立马来了兴趣,姑且写一个玩玩(


头文件


  • <windows.h>:包含了 Windows API 的核心功能。
  • <tchar.h>:提供了一种跨平台的方式来处理 UnicodeANSI 字符集,防止出现一些编码错误。
  • <cstdio>:包含了 C 标准输入输出函数的声明。

CreateThread


CreateThread Windows API 中的一个函数,用于创建一个新的线程。

这就是我们程序的核心函数,其函数的原型如下:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  LPVOID                  lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);

参数说明:

  • lpThreadAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,用于指定新线程的安全性。可以设置为 NULL,表示使用默认的安全性。
  • dwStackSize:指定新线程的堆栈大小。可以设置为 0 0 0,表示使用默认的堆栈大小。
  • lpStartAddress:指向线程函数的指针,表示新线程的入口点。线程函数的原型为DWORD WINAPI ThreadProc(LPVOID lpParameter),其中lpParameter为传递给线程函数的参数。
  • lpParameter:传递给线程函数的参数,可以是任意类型的指针。
  • dwCreationFlags:指定线程的创建标志。可以设置为 0 0 0,表示无特殊标志。
  • lpThreadId:指向DWORD类型变量的指针,用于接收新线程的标识符。

即:CreateThread 函数创建一个新的线程,并返回该线程的句柄。如果创建线程成功,返回值为线程的句柄;否则返回值为 NULL

句柄

  • 有趣的是,在 Windows 里并没有进程层次的概念,所有进程的地位都是相同的。
  • 在创建进程时,父进程会得到一个特别令牌(句柄),用于控制子进程。
  • 该令牌是可以传递的,即父进程有权将该令牌传递给其他进程,以至于不存在了进程层次的概念。

注意

  • 新线程的入口点是通过 lpStartAddress 参数指定的线程函数。线程函数在新线程中执行,可以执行各种任务。
  • 线程函数的返回值是一个 DWORD 类型的值,表示线程的退出码。
  • 通过 CreateThread 函数创建的线程是可执行的,它可以并发地与其他线程执行,但线程的执行顺序和调度由操作系统决定。
  • 在使用CreateThread函数创建线程后,需要使用 CloseHandle 函数关闭线程句柄,以释放资源。

实现代码


#include <windows.h>
#include <tchar.h>
#include <cstdio>

DWORD WINAPI OpenNotepadThread(LPVOID lpParam) {
    // 定义要打开的应用程序的路径
    LPCTSTR appName = _T("notepad.exe");

    // 创建进程信息结构体
    STARTUPINFO startupInfo;
    PROCESS_INFORMATION processInfo;

    // 初始化进程信息结构体
    ZeroMemory(&startupInfo, sizeof(startupInfo));
    startupInfo.cb = sizeof(startupInfo);
    ZeroMemory(&processInfo, sizeof(processInfo));

    // 创建新进程
    if (!CreateProcess(
        NULL,                   // 指向可执行文件名的指针
        (LPTSTR)appName,        // 命令行参数
        NULL,                   // 进程句柄不可继承
        NULL,                   // 线程句柄不可继承
        FALSE,                  // 不继承句柄
        0,                      // 无特殊标志
        NULL,                   // 使用父进程的环境变量
        NULL,                   // 使用父进程的工作目录
        &startupInfo,           // 启动信息
        &processInfo            // 进程信息
    )) {
        _tprintf(_T("WRONGING:%d\n"), GetLastError());
        return 1;
    }

    // 等待新进程结束
    WaitForSingleObject(processInfo.hProcess, INFINITE);

    // 关闭进程和线程句柄
    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);

    return 0;
}

int main() {
    // 创建线程
    HANDLE hThread = CreateThread(NULL, 0, OpenNotepadThread, NULL, 0, NULL);
    
    if (hThread == NULL) {
        _tprintf(_T("WRONGING:%d\n"), GetLastError());
        return 1;
    }

    // 等待线程结束
    WaitForSingleObject(hThread, INFINITE);

    // 关闭线程句柄
    CloseHandle(hThread);

    return 0;
}

在上述代码中,我定义了一个名为 OpenNotepadThread 的函数,它是一个线程函数,用于打开记事本应用程序。该函数的参数类型为LPVOID,表示一个指向任意类型的指针。然后创建进程信息结构体 STARTUPINFOPROCESS_INFORMATION,并对其进行了初始化。

接下来调用 CreateProcess 函数用于创建一个新的进程,返回进程的句柄和线程的句柄。它的参数包括可执行文件名、命令行参数、进程句柄和线程句柄是否可继承等信息。如果创建进程成功,返回值为 0 0 0;否则返回值为 1 1 1

调用 WaitForSingleObject 函数用于等待一个对象的状态变为可信,即等待进程结束。它的参数包括要等待的对象句柄和等待的时间,这里使用 INFINITE 表示无限等待,直到进程结束。

当进程结束后,需要调用 CloseHandle 函数关闭进程和线程的句柄,释放资源。


测试效果


image-20230920011044280

🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗🤗

更多推荐

跨进程数据共享技术

跨进程数据共享技术是指在不同的计算进程之间实现数据共享的方法和技术。这种技术通常用于多任务操作系统或分布式系统中,以便不同的程序或进程能够在运行时共享数据,从而实现协同工作或实现某些特定的功能。以下是一些常见的跨进程数据共享技术:进程间通信(Inter-ProcessCommunication,IPC):IPC是一种广

SpringBoot+Jpa+Thymeleaf实现增删改查

SpringBoot+Jpa+Thymeleaf实现增删改查这篇文章介绍如何使用Jpa和Thymeleaf做一个增删改查的示例。1、pom依赖pom包里面添加Jpa和Thymeleaf的相关包引用<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://mave

Linux 信号集 及其 部分函数

这几个函数都是对自己自定义的信号集操作intsigemptyset(sigset_t*set)功能:清空信号集中的数据,将所有的标志位置为0参数:set需要操作的信号集返回值:成功0失败-1intsigfillset(sigset_t*set)功能:清空信号集中的数据,将所有的标志位置为1参数:set需要操作的信号集返

数据结构---二叉搜索树

二叉搜索树二叉搜索树什么是二叉搜索树?二叉搜索树的操作查找插入删除源代码非递归版二叉搜索树什么是二叉搜索树?二叉搜索树(BinarySearchTree简称BST)又称二叉排序树,是一种二叉树的特殊形式,它在每个节点上存储的键值满足以下性质:若它的左子树不为空,则左子树上的所有节点的值都小于根节点的值若它的右子树不为空

数据结构--7.1散列表(哈希表)查找

散列表查找我们要在a[]中查找key关键字的记录:——顺序表查找:挨个儿查找——有序表查找:二分法查找——散列表查找记录的存储位置=f(关键字)散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。这里我们把这种对应关系f称为散列函数,又成为哈希(Hash

EM算法和VAE的学习笔记

文章目录摘要EM算法流程EM算法对GMM的参数估计EM算法的证明EM算法的另一种理解VAE参考文献摘要这是我学习EM算法(Expectation-MaximizationAlgorithm)和VAE(VariationalAuto-Encoder)的学习笔记,首先总结了EM算法流程,然后举了一个例子,用EM算法对GMM

【karle 笔记】QQ机器人jdk17版本下载和安装

这里写自定义目录标题下载地址安装JDK:安装JRE验证安装成功下载地址https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe下载后,是一个exe文件,傻瓜式安装即可安装JDK:直接用安装包安装,默认安装路径在:C:\ProgramFil

ChatGPT技术原理

目录一、Tokenization二、Transformer模型三、预训练四、微调五、Beamsearch总结自从OpenAI的ChatGPT在2022年底横空出世以来,这款大型语言模型在各种任务中都展现了惊人的性能,包括问答、对话、文本生成等。ChatGPT以其卓越的性能和高效的处理能力,引领了自然语言处理(NLP)领

vue/react/node项目通过eslint检查语法规范

首先我们打开终端全局安装依赖npminstall-geslint然后以管理员身份运行项目终端输入eslint--init然后这里在初始化时会问我们想如何使用它?分别对应仅检查语法检查语法并发现问题检查语法、发现问题并强制执行代码样式这里建议第二种第三种肯定是不行的然后问我们您的项目使用哪种类型的模块?JavaScrip

日主题RiPro主题高端美化/设计素材软件下载站专用子主题/美化包源码(升级版/免拓展)

主题简介日主题RiPro主题高端美化/设计素材软件下载站专用子主题/美化包源码,这个子主题美化包无授权无暗链,不用再修改原主题代码,在用这个本美化包前要先下载最新ripro主题,本子主题有版本要求,仅支持RiPro8.0以上版本,建议使用官方正版主题。更新记录:美化网站整站主色调颜色,优化代码结构,更适合SEO新增菜单

文件包含漏洞

1.文件包含原理程序在开发的时候,未对包含的文件进行严格的过滤,攻击者可以构造自己的图片木马当作php执行2.文件包含分类本地包含不需要条件,只要有程序代码漏洞,默认条件就可以包含漏洞远程包含需要allow_url_include=on(开启远程包含功能)、magic_quotes_gpc=off(魔术符号关闭)htt

热文推荐