深扒QProcess

临近年关,春节前的一周时间都没什么事,每天上班光明正大的摸鱼。但一周都没事做也不免有些无聊。为了打发无聊的时间,翻出我珍藏多年的移动硬盘,在硬盘的某个快被遗忘的角落,翻出了一个我多年以前刚开始学C语言时在网上淘到的一个双管道后门程序。这个后门程序当时我是看不懂的,随手丢在了角落吃灰,这么多年过去了,我觉得我应该能看得懂了,就翻出来研究一下。
其大致原理是这样的:先在本地起一个监听socket,然后开启两个管道,运行cmd程序,并将管道1的读端绑定到cmd的标准输入,管道2的写端绑定到cmd的标准输出和错误输出。然后远程想要用后门了,需要连接这个socket,连接成功后,发送一条命令,比如是dir。后门程序通过socket读到了这条命令,然后把socket读到的命令写入到管道1的写端。还记得管道1的读端在哪不?就是绑定在cmd的标准输入。cmd进程发现管道有数据了,就会读取这条数据,然后执行相应的命令,并将结果写入到管道2的写端。然后后门程序发现管道2的写端有数据了,就读出来。最后通过socket将cmd的返回结果发送给远程。
看到这里,突然联想到,QProcess读取进程的输出是不是也用管道实现的呢?写段代码跟踪一下

QProcess proc;
proc.start("C:/WINDOWS/system32/cmd.exe", QStringList("/c") << "dir\r\n");

if (proc.state() == QProcess::NotRunning)
{
   
	LOG_ERROR("failed to start %s: %s", exe.toLocal8Bit().data(), QMetaEnum::fromType<QProcess::ProcessError>().valueToKey(proc.error()));
	return false;
}

proc.waitForFinished(-1);

QByteArray message = proc.readAllStandardOutput().trimmed();

这段代码很简单,是QProcess的一个常见用法,先执行某个进程,然后等待进程结束,最后读取该进程的输出内容。
接下来要做的是跟进去每个函数,看这些函数都做了什么。

启动进程

首先是构造函数,构造函数没什么可说的,就是一些变量的初始化。
start函数进去后,跳过那些不重要的代码,直接来到QProcessPrivate::startProcess函数内,这才是启动进程的关键位置。QProcessPrivate是不对用户开放的类,但却是QProcess的真正核心,QProcess的很多功能都在QProcessPrivate中实现的。先来看一下QProcessPrivate::startProcess的实现,下面代码删除了该函数内不太重要的内容,只保留真正核心功能,后面的所有Qt的代码段都是这么处理的,完整实现请自行参阅Qt源码

void QProcessPrivate::startProcess()
{
   
    pid = new PROCESS_INFORMATION;
    memset(pid, 0, sizeof(PROCESS_INFORMATION));

    if (!openChannel(stdinChannel) ||
        !openChannel(stdoutChannel) ||
        !openChannel(stderrChannel))
        return;
        
    DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW);
    dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
    STARTUPINFOW startupInfo = {
    sizeof( STARTUPINFO ), 0, 0, 0,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
                                 0, 0, 0,
                                 STARTF_USESTDHANDLES,
                                 0, 0, 0,
                                 stdinChannel.pipe[0], stdoutChannel.
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木千

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值