c ++我如何获得当前的控制台conhost进程

时间:2016-01-30 13:15:43

标签: c++ winapi

我在"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过程...

谢谢! :)

3 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:1)

如果您仍然需要它(阅读评论后),这里有一段代码可以获取 conhost.exe 进程。请注意,我只是出于演示目的而编写它(以检查[MSDN]: Tool Help Functions是否可以用于此场景),所以不要介意其结构或其他编码 NO-NO 。 / p>

code.c

#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.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 = INVALID_HANDLE_VALUE;
    char c = 0;
    if (argc > 1) {
        pid = atoi(argv[1]);
    } else {
        pid = GetCurrentProcessId();
    }
    printf("PID: %d\n", pid);
    snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
    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 ((proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cPid)) == INVALID_HANDLE_VALUE) {
        printf("OpenProcess failed: %d\n", GetLastError());
        return -3;
    }
    printf("Conhost handle: 0x%08X\n", proc);
    CloseHandle(proc);

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

输出(作为 VStudio 2010 控制台应用 Debug - x86 ) 10 ):

e:\Work\Dev\StackOverflow\q035102238>ver

Microsoft Windows [Version 10.0.17134.48]

e:\Work\Dev\StackOverflow\q035102238>"Debug\q035102238.exe"
PID: 22388
    Idx: 00  PID: 19892  PPID: 20164  Name: conhost.exe
    Idx: 01  PID: 21128  PPID: 21120  Name: conhost.exe
    Idx: 02  PID:  1144  PPID: 20572  Name: conhost.exe
    Idx: 03  PID:  8184  PPID: 19572  Name: conhost.exe
    Idx: 04  PID: 10976  PPID: 20608  Name: conhost.exe
    Idx: 05  PID: 21284  PPID:  8792  Name: conhost.exe
    Idx: 06  PID:  8172  PPID: 20444  Name: conhost.exe
    Idx: 07  PID:  4396  PPID: 19484  Name: conhost.exe
    Idx: 08  PID: 12484  PPID:  2580  Name: conhost.exe
    Idx: 09  PID: 18636  PPID: 11552  Name: conhost.exe
    Idx: 10  PID: 21456  PPID: 21016  Name: conhost.exe
    Idx: 11  PID:   960  PPID:  3528  Name: conhost.exe
    Idx: 12  PID: 20616  PPID: 18404  Name: conhost.exe
    Idx: 13  PID: 21548  PPID: 21528  Name: conhost.exe
    Idx: 14  PID: 20192  PPID:  8316  Name: conhost.exe
    Idx: 15  PID:  2496  PPID:  9284  Name: conhost.exe
    Idx: 16  PID:  5820  PPID: 23140  Name: conhost.exe
    Idx: 17  PID:  6032  PPID: 26512  Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...

因此,可以枚举所有正在运行的 conhost.exe 进程,并将PROCESS_ALL_ACCESS提供给与我当前应用程序关联的进程(我必须在此提及我的 Win 用户具有完全管理权限。

<强> @ EDIT0

  • 正如@BladeMight注意到的那样, Win 7 所有 conhost.exe 进程都是 crss.exe 的子进程(因为它也可以在 ProcExp 中看到)

<强>输出

c:\Work\Dev\StackOverflow\q035102238>ver

Microsoft Windows [Version 6.1.7601]

c:\Work\Dev\StackOverflow\q035102238>q035102238.exe
PID: 1548
    Idx: 00  PID:  4960  PPID:  3472  Name: conhost.exe
    Idx: 01  PID:  5024  PPID:  3472  Name: conhost.exe
    Idx: 02  PID:  5076  PPID:  3472  Name: conhost.exe
    Idx: 03  PID:  2676  PPID:  3472  Name: conhost.exe
    Idx: 04  PID:  1888  PPID:  3472  Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...

答案 2 :(得分:0)

这里有一些令人难以置信的复杂答案。使用进程资源管理器获取控制台应用程序的 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 的结构,然后您将知道如何获取参数块,并在它在参数块中的偏移量。您可以在 _PEBhere 中使用 _RTL_USER_PROCESS_PARAMETERSwinternl.h 的类型定义,或者使用 ntkrnlmp.pdb 符号编写自己的类型定义。