c++ 如何获取当前控制台 conhost 进程

问题描述 投票:0回答:3

我在

"how i get the conhost process"
之后搜索了很多网站,但没有什么是我真正要找的。

我已经搜索过。

我找不到任何关于

"how to get the conhost process"
的信息。

我有一些适用于当前

"cmd.exe / program.exe"
的代码,这给了我
"PID, NAME, PATH, READ/WRITE ADDRESS"

我可以获得

parent
流程,但这不是
conhost.exe

代码

"need to link library 'psapi' first"

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
#include <tlhelp32.h>

int PrintModules(DWORD processID) {
    HMODULE hMods[1024];
    HANDLE hProcess;
    DWORD cbNeeded;
    unsigned int i;

    printf( "\nProcess ID: %u\n", processID);

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
    if(NULL == hProcess) return 1;

    if(EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
        for(i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            TCHAR szModName[MAX_PATH];

            if(GetModuleFileNameEx(hProcess, hMods[i], szModName,sizeof(szModName) / sizeof(TCHAR))) {
                _tprintf( TEXT("  %s (0x%08X)\n"), szModName, hMods[i]);
            }
        }
    }

    CloseHandle(hProcess);

    return 0;
}

int main(void) {
    DWORD cpid = GetCurrentProcessId();
    PrintModules(cpid);

    int ppid = -1;
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { 0 };
    pe.dwSize = sizeof(PROCESSENTRY32);
    if(Process32First(h, &pe)) {
        do {
            if(pe.th32ProcessID == cpid) {
                printf("PID: %i; PPID: %i\n", cpid, pe.th32ParentProcessID);
                ppid = pe.th32ParentProcessID;
            }
        } while(Process32Next(h, &pe));
    }
    PrintModules(ppid);
    CloseHandle(h);
    std::cin.get();
    return 0;
}

我无法找到获取当前

conhost
进程的方法。

当您打开使用控制台的

program
时,会创建一个
conhost.exe
进程。 我的问题是我如何获得该
conhost.exe
过程...

谢谢! :)

c++ windows winapi console-application
3个回答
2
投票

如果您仍然需要它(阅读评论后),这里有一段获取 ConHost (conhost.exe) 进程的代码。请注意,我编写它只是为了演示目的(检查[MS.Learn]:工具帮助函数是否可以用于此场景),所以不要介意它的结构或其他编码NO-NO

代码00.c

#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <winternl.h>


int main(int argc, char **argv)
{
    DWORD pid = 0, i = 0, cPid = 0;
    PROCESSENTRY32 pe32;
    BOOL res = FALSE;
    HANDLE snap = INVALID_HANDLE_VALUE, proc = NULL;
    char c = 0;
    if (argc > 1) {
        pid = atoi(argv[1]);
    } else {
        pid = GetCurrentProcessId();
    }
    printf("PID: %d\n", pid);
    snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snap == INVALID_HANDLE_VALUE) {
        printf("CreateToolhelp32Snapshot failed: %d\n", GetLastError());
        return -1;
    }
    pe32.dwSize = sizeof(PROCESSENTRY32);
    res = Process32First(snap, &pe32);
    if (res == FALSE) {
        printf("Process32First failed: %d\n", GetLastError());
        CloseHandle(snap);
        return -2;
    }
    do {
        if (_tcscmp(pe32.szExeFile, TEXT("conhost.exe")) == 0) {
            _tprintf(TEXT("    Idx: %02d,  PId: %5d,  PPId: %5d,  Name: %s\n"), i++, pe32.th32ProcessID, pe32.th32ParentProcessID, pe32.szExeFile);
            if (pe32.th32ParentProcessID == pid) {
                cPid = pe32.th32ProcessID;
            }
        }
    } while ((res = Process32Next(snap, &pe32)));
    CloseHandle(snap);

    if (cPid) {
        if ((proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cPid)) == NULL) {
            printf("OpenProcess failed: %d\n", GetLastError());
            //return -3;
        } else {
            printf("ConHost handle: 0x%08X\n", proc);
            CloseHandle(proc);
        }
    }

    printf("Press a key to exit...\n");
    c = _getch();
    return 0;
}

因此,可以枚举所有正在运行的 conhost.exe 进程,并且还可以获得与我当前应用程序关联的进程 PROCESS_ALL_ACCESS(我必须在这里提到,我的 Win 用户拥有完全管理权限)

  • 正如 @BladeMight 注意到的,在 Win 7 all ConHost 进程是 crss.exe 的子进程(也可以在 ProcExp 中看到)

输出

  • 1st运行:

    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> ver
    
    Microsoft Windows [Version 10.0.19045.4355]
    
    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> Debug\q35102238.exe
    PID: 21460
        Idx: 00,  PId: 15004,  PPId:  6636,  Name: conhost.exe
        Idx: 01,  PId:  1996,  PPId: 14992,  Name: conhost.exe
        Idx: 02,  PId:  6964,  PPId:  7908,  Name: conhost.exe
        Idx: 03,  PId:  9620,  PPId:  3168,  Name: conhost.exe
        Idx: 04,  PId: 11828,  PPId:  3040,  Name: conhost.exe
        Idx: 05,  PId: 15832,  PPId: 15732,  Name: conhost.exe
        Idx: 06,  PId:  3276,  PPId: 11808,  Name: conhost.exe
        Idx: 07,  PId: 17336,  PPId: 17316,  Name: conhost.exe
        Idx: 08,  PId: 16284,  PPId: 15020,  Name: conhost.exe
        Idx: 09,  PId: 16908,  PPId: 16760,  Name: conhost.exe
        Idx: 10,  PId: 11220,  PPId:  5224,  Name: conhost.exe
        Idx: 11,  PId: 11832,  PPId: 15764,  Name: conhost.exe
        Idx: 12,  PId: 17460,  PPId: 17440,  Name: conhost.exe
        Idx: 13,  PId: 17808,  PPId: 17788,  Name: conhost.exe
        Idx: 14,  PId: 18216,  PPId: 18196,  Name: conhost.exe
        Idx: 15,  PId: 15736,  PPId:  3724,  Name: conhost.exe
        Idx: 16,  PId: 17852,  PPId: 17900,  Name: conhost.exe
        Idx: 17,  PId: 13068,  PPId:  6908,  Name: conhost.exe
        Idx: 18,  PId: 14116,  PPId: 12172,  Name: conhost.exe
        Idx: 19,  PId:  1564,  PPId: 10668,  Name: conhost.exe
        Idx: 20,  PId:  9592,  PPId:  9612,  Name: conhost.exe
        Idx: 21,  PId:  1364,  PPId:  9848,  Name: conhost.exe
        Idx: 22,  PId:  7040,  PPId: 16308,  Name: conhost.exe
        Idx: 23,  PId: 15484,  PPId: 22092,  Name: conhost.exe
        Idx: 24,  PId: 18996,  PPId:  2668,  Name: conhost.exe
        Idx: 25,  PId: 11108,  PPId: 19440,  Name: conhost.exe
        Idx: 26,  PId:  4792,  PPId: 25404,  Name: conhost.exe
        Idx: 27,  PId: 14948,  PPId: 20596,  Name: conhost.exe
    Press a key to exit...
    
  • 流程布局:

    Img00

  • 2nd运行 - 通过2668(父级CmdPId):

    [cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q035102238]> Debug\q35102238.exe 2668
    PID: 2668
        Idx: 00,  PId: 15004,  PPId:  6636,  Name: conhost.exe
        Idx: 01,  PId:  1996,  PPId: 14992,  Name: conhost.exe
        Idx: 02,  PId:  6964,  PPId:  7908,  Name: conhost.exe
        Idx: 03,  PId:  9620,  PPId:  3168,  Name: conhost.exe
        Idx: 04,  PId: 11828,  PPId:  3040,  Name: conhost.exe
        Idx: 05,  PId: 15832,  PPId: 15732,  Name: conhost.exe
        Idx: 06,  PId:  3276,  PPId: 11808,  Name: conhost.exe
        Idx: 07,  PId: 17336,  PPId: 17316,  Name: conhost.exe
        Idx: 08,  PId: 16284,  PPId: 15020,  Name: conhost.exe
        Idx: 09,  PId: 16908,  PPId: 16760,  Name: conhost.exe
        Idx: 10,  PId: 11220,  PPId:  5224,  Name: conhost.exe
        Idx: 11,  PId: 11832,  PPId: 15764,  Name: conhost.exe
        Idx: 12,  PId: 17460,  PPId: 17440,  Name: conhost.exe
        Idx: 13,  PId: 17808,  PPId: 17788,  Name: conhost.exe
        Idx: 14,  PId: 18216,  PPId: 18196,  Name: conhost.exe
        Idx: 15,  PId: 15736,  PPId:  3724,  Name: conhost.exe
        Idx: 16,  PId: 17852,  PPId: 17900,  Name: conhost.exe
        Idx: 17,  PId: 13068,  PPId:  6908,  Name: conhost.exe
        Idx: 18,  PId: 14116,  PPId: 12172,  Name: conhost.exe
        Idx: 19,  PId:  1564,  PPId: 10668,  Name: conhost.exe
        Idx: 20,  PId:  9592,  PPId:  9612,  Name: conhost.exe
        Idx: 21,  PId:  1364,  PPId:  9848,  Name: conhost.exe
        Idx: 22,  PId:  7040,  PPId: 16308,  Name: conhost.exe
        Idx: 23,  PId: 15484,  PPId: 22092,  Name: conhost.exe
        Idx: 24,  PId: 18996,  PPId:  2668,  Name: conhost.exe
        Idx: 25,  PId: 11108,  PPId: 19440,  Name: conhost.exe
        Idx: 26,  PId:  4792,  PPId: 25404,  Name: conhost.exe
        Idx: 27,  PId: 14948,  PPId: 20596,  Name: conhost.exe
        Idx: 28,  PId: 23172,  PPId: 15672,  Name: conhost.exe
        Idx: 29,  PId: 23516,  PPId: 13352,  Name: conhost.exe
    ConHost handle: 0x000000DC
    Press a key to exit...
    

2
投票

想到的一种方法是获取 CMD.EXE 进程的启动时间。然后遍历所有 CONHOST 进程寻找相同(或非常接近)的启动时间。

作为概念证明,下载并安装 Process Explorer。在 ProcExp 中找到 CMD.EXE 进程,然后查看“属性”、“图像”选项卡。注意开始时间。然后查看每个 CONHOST 进程,寻找同时启动的进程。

请注意,ProcExp 显示 1 秒分辨率,但 ProcExp 使用的任何底层 API 可能具有更好的分辨率。

您可能需要谷歌一些来了解 ProcExp 使用哪些 API 来收集进程启动时间。此外,您还可以使用多种工具来查看可执行文件(本例中为 ProcExp)导入了哪些 API。您也许可以从 ProcExp 导入的 API 名称推断出哪个(哪些)将提供进程的启动时间。


-1
投票

这里有一些令人难以置信的复杂答案。使用进程资源管理器获取控制台应用程序的pid,然后在

kd -kl

中执行以下操作
lkd> !process 0n16592 0
Searching for Process with Cid == 40d0
Cid handle table at fffff8a001db8000 with 4368 entries in use

PROCESS fffffa8042eb9590
.
.
.
lkd> .process /P fffffa8042eb9590                         
Implicit process is now fffffa80`42eb9590
lkd> !peb                                
PEB at 000007fffffd3000 
.
.
.                                       
    ProcessParameters: 0000000000202880
.
.
.
lkd> dt nt!_RTL_USER_PROCESS_PARAMETERS 0000000000202880
.
.
.
   +0x010 ConsoleHandle    : 0x00000000`00003d98 Void
   +0x018 ConsoleFlags     : 0
   +0x020 StandardInput    : 0x00000000`00000003 Void
   +0x028 StandardOutput   : 0x00000000`00000007 Void
   +0x030 StandardError    : 0x00000000`0000000b Void
.
.
.
.
lkd> ? 0x3d98
Evaluate expression: 15768 = 00000000`00003d98

这是它所附加的 conhost 进程的 pid。在 C++ 中,您必须获取当前的 PEB,看看如何以编程方式完成此操作here,研究 PEB 和 ParameterBlock 的结构,然后您就会知道如何获取参数块以及偏移量是多少它位于参数块中。您可以使用

_PEB
here
_RTL_USER_PROCESS_PARAMETERS
winternl.h 的类型定义,或者使用 ntkrnlmp.pdb 符号编写自己的类型定义。

© www.soinside.com 2019 - 2024. All rights reserved.