4

i have searched on so many websites after "how i get the conhost process", and nothing is really what i'm looking for.

i have searched on.

and i can't find anything about "how to get the conhost process".

i have some code that works for the current "cmd.exe / program.exe" and that gives me the "PID, NAME, PATH, READ/WRITE ADDRESS".

i can get the parent process but that is not conhost.exe.

code "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;
}

and i can't figure out a way to get the current conhost process.

when you open a program that uses the console, a conhost.exe process is created. and my question is how do i get that conhost.exe process...

Thanks! :)

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
HardCoded
  • 134
  • 2
  • 8
  • 1
    What are you going to do with the conhost process? The conhost process is an implementation detail that may change at any time. (Indeed, some versions of Windows don't have a conhost at all.) – Raymond Chen Jan 30 '16 at 18:31
  • I'm going change the `SetTextCol` function by `WriteProcessMemory` and then change the color to what i want. @Raymond – HardCoded Jan 30 '16 at 18:48
  • 1
    @CodeAway and why are you doing this by hijacking conhost? Why can't you instead call `SetConsoleTextAttribute()` in your own code? – andlabs Jan 30 '16 at 18:53
  • i want to use all `RGB colors`. @andlabs – HardCoded Jan 30 '16 at 19:25
  • @CodeAway [that is the question you should have asked instead of this one.](http://xyproblem.info/) But I see you have decided to continue on this path, so good luck. (I would not know the answer anyway.) – andlabs Jan 30 '16 at 22:38
  • @CodeAway: "*i want to use all RGB colors*" - Win32 consoles only support 16 colors. `SetConsoleTextAttribute()` allows you to specify 4-bit values for text and background colors. However, those 4-bit values are actually indexes into a color table, where the default color table contains predefined colors. To use other colors, you can simply swap out a different color table using [`SetConsoleScreenBufferInfoEx()`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686039.aspx). You are still limited to 16 colors, but you can use any full RGB `COLORREF` value for those 16 colors. – Remy Lebeau Jan 31 '16 at 01:45
  • you can actually use every single `RGB color`, the user is only able to use 16 colors... if you have `CheatEngine` try this is the `AutoAssembler`. after you have executed the script you need to write `Color 01`. [pastebin](http://pastebin.com/xZs96ty1). and you need to select the `conhost.exe` process @Remy – HardCoded Jan 31 '16 at 11:16
  • I seen [here](https://github.com/Elfy/getconkbl) the way to get what you need @CodeAway – BladeMight Sep 13 '17 at 00:26

3 Answers3

2

One method that comes to mind is to obtain the start time of the CMD.EXE process. Then iterate through all of the CONHOST processes looking for the same (or very close) start time.

As a proof of concept download and install Process Explorer. Find your CMD.EXE process in ProcExp, then look at Properties, Image tab. Note the start time. Then look through each CONHOST process looking for one that starts at the same time.

Note that ProcExp displays 1 second resolution, but whatever underlying API ProcExp uses probably has better resolution.

You may need to google some to get an idea what API(s) ProcExp uses to gather the process start time. Additionally there are a variety of tools you can use to see what APIs an executable (ProcExp in this case) import. You may be able to deduce from the API names that ProcExp imports which one(s) would provide a process' start time.

Χpẘ
  • 3,403
  • 1
  • 13
  • 22
2

In case you still need it (after reading the comments), here's a piece of code that gets the conhost.exe processes. Please note that I only wrote it for demonstrative purposes (to check whether [MSDN]: Tool Help Functions can be used for this scenario), so don't mind its structure or other coding NO-NOs.

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;
}

Output (as a VStudio 2010, Console App (Debug - x86) on Win 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...

So, it is possible to enumerate all running conhost.exe processes, and also get PROCESS_ALL_ACCESS to the one associated with my current application (I have to mention here that my Win user has full administrative privileges).

@EDIT0:

  • As @BladeMight noticed, on Win 7 all conhost.exe processes are children of crss.exe (as it can be also seen in ProcExp)

Output:

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...
CristiFati
  • 38,250
  • 9
  • 50
  • 87
-1

Some unbelievably convoluted answers here. Use process explorer to get the pid of the console application and then do the following in 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

This is the pid of the conhost process that it is attached to. In C++, you'd have to get the current PEB, take a look at how that is done programmatically here, study the structure of the PEB and ParameterBlock and then you'll know how to get the parameter block and at what offset it is in the parameter block. You can use the type definition for _PEB and _RTL_USER_PROCESS_PARAMETERS in winternl.h or the one here, or write your own using the ntkrnlmp.pdb symbols.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
  • That is handle is to the IOCTL file object (used with DeviceIoControl) not a handle to conhost.exe. https://pastebin.com/0h7Wn0nj – Martymoose Oct 03 '21 at 22:27
  • @Martymoose I'll check out this concern soon. I didn't know offhand, because I was investigating it myself. I have a few windows answers on here that need editing – Lewis Kelsey Oct 16 '21 at 15:43
  • @Martymoose I think you must be talking about windows 10. Can you confirm that it is not the pid of the conhost process on windows 10? I have windows 7, where of course theres no condrv driver, and from my results `ConsoleHandle` is always the pid of the conhost.exe process – Lewis Kelsey Oct 16 '21 at 15:58
  • I do have win 10. I didn't know it differed across versions, good to know. https://github.com/microsoft/terminal - Appears it's open source I was surprised. – Martymoose Nov 01 '21 at 06:54
  • This is what I get. https://ibb.co/5Gtz1Mj – Martymoose Nov 01 '21 at 07:19