Hacker News new | past | comments | ask | show | jobs | submit login

Is there any historical reason that conhost is the only executable able to open a master handle?



Well, originally, console handles weren't real handles. They were userspace hacks, which is why DuplicateHandle[1] has special cases for console handles. (Imagine using negative file descriptor values that libc understood.) Originally, the terminal emulator ran as SYSTEM and was spawned from (IIRC) csrss (which is special, because reasons). In Vista, with integrity levels introduced, the terminal emulator had to run in a different security context, and so wasn't themed. (To prevent shatter attacks.) In Windows 7 and 8, Microsoft developed a real, honest-to-god pseudoconsole API, with a real protocol. In this implementation, console handles are real handles and conhost is just a normal program that speaks a protocol.

IIRC, the only thing at this point stopping Microsoft creating a pseudoconsole API based on real, honest-to-god kernel HANDLEs is a willingness to externalize, document, and support what has been until now a Windows-internal API.

[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms7...


Regarding a public API, this GitHub comment suggests that people at Microsoft are working on it.[1] Of course, Microsoft can't commit to anything. As the winpty maintainer, I hope some kind of public API emerges to reduce my maintenance burden and make winpty more robust and efficient.

Aside: About a year ago, I studied how the console handles worked (especially in relation to console attach/detach/alloc and CreateProcess), and I discovered a bunch of interesting things. For example, the "fake" handles were inherited regardless of the bInheritHandles parameter to CreateProcess, and an entire "ConsoleHandleSet" was inherited if a process attached to another process' console. Real handles in Win8 seemed to be either "bound" to a particular input/screen buffer or "unbound" so they worked with any attached console. It was possible to have a console open with no attached processes.

I tried to formalize the behavior I observed here: https://github.com/rprichard/win32-console-docs

In the course of testing, I found some neat bugs like:

- A small program that blue-screens Vista

- The inheritable flag on a console handle can be changed on any Windows version, except for Windows 7.

- CreateProcess has an undocumented(?) behavior where it duplicates stdio handles into the new process rather than inherit them. (The handle values will generally change.) Up until Windows 8.1, a stdio handle of INVALID_HANDLE_VALUE was duplicated into a true handle to the parent process. (Because INVALID_HANDLE_VALUE is actually the GetCurrentProcess() pseudo-handle, you see.)

- Assorted inconsistencies in Windows XP and WOW64 (probably fixed in newer OSs).

I'm not sure how much confidence I have in the spec. It is backed by a big test suite, but there are so many cases to consider.

[1] https://github.com/Microsoft/BashOnWindows/issues/111#issuec...


> winpty

Cool. There's a third option that you might want to consider for winpty. (I was experimenting with it before I left Microsoft.)

The basic idea is to use a DLL shim to provide your own console API implementation for a process and its children --- you can replace the system console API with your own by shimming DLL import and export tables. You'd use your own type of pseudohandle for your fake console handles; programs written to work with the old console pseudohandles should work correctly with your pseudohandles, provided you've hooked the relevant HANDLE-using APIs.


Yeah, I considered that route, but I was concerned that it'd be unreliable -- maybe with other programs doing clever tricks with import/export tables, or maybe with antivirus. I can't think of a specific reason it wouldn't work, though. I think it'd have to override CreateProcess to propagate the API hook. IIRC, ConEmu's CreateProcess starts a child in a suspended state so it can install its hook before resuming the child. Maybe it'd have to hook GetProcAddress, too.

I was assuming I'd use genuine console handles, but recognize that they're associated with the special console, so divert their API calls.

Maybe the technique would make programs slower. I know that's a complaint people have about ConEmu.

There's a similar (4th?) technique I've considered -- instead of hooking every process attached to the console, hook APIs in the conhost process and reimplement the internal protocol. It should avoid the performance problems and confine the hackiness to one address space. The trouble is that the protocol is undocumented. A small change could break everything without warning, but MS could also redesign the whole thing, making a fix impossible.


I also tried using the console accessibility APIs [1] to at least synchronize scraping and forwarding to the pty. The problem with this approach is that the console code issues EVENT_CONSOLE_UPDATE_REGION and such with its internal locks held, so attempting to read from the console from inside the accessibility handler deadlocks.

[1] https://msdn.microsoft.com/en-us/library/ms971319.aspx


To do that, you have to attach the conhost.exe process to its own console with AttachConsole, right? I tried that and also noticed the deadlock. An out-of-context handler avoids the deadlock, but then it's not synchronized.

The other interesting problems I found with that API were: (1) when editing an input line, EVENT_CONSOLE_CARET notifications were delayed, (2) if I hit ESC when editing an input line, the line would clear, but there'd be no update-region notification, and (3) it's impossible to distinguish between a call to ScrollConsoleScreenBuffer and the whole buffer scrolling because we've reached the end. ScrollConsoleScreenBuffer might scroll only part of the buffer.

winpty doesn't use the WinEvents API (yet), but it might be good enough to reduce polling when the console is idle.


> - A small program that blue-screens Vista

You mean like on current up-to-date versions of Vista and Server 2008? With a PoC on the github page? You realise that you have found a security vulnerability and are disclosing it publicly, right? Userspace must never crash the kernel, even if not further exploitable, especially so if it's possible for an unprivileged user. Be responsible, send a mail to secure@microsoft.com


Yes, it's a tiny program that (1) detaches the console, (2) attaches a new console, (3) closes all screen buffer handles, then (4) creates a new screen buffer. The fourth step caused a BSOD on Vista and Server 2008. AFAIK, they were up-to-date.

I did report it to Microsoft before making it public. The reply was:

> Thank you for contacting the Microsoft Security Response Center (MSRC). I would suggest trying on a local VM to confirm BSOD. However, this currently is just a local DOS, which would would not be something we would investigate further. If you have any additional information on how this could be further used to exploit another user or a remote DOS, please let us know and we will look into it.

> For an in-depth discussion of what constitutes a product vulnerability please see the following:

> "Definition of a Security Vulnerability" <https://technet.microsoft.com/library/cc751383.aspx>

>Again, we appreciate your report.


I might be suffering from reverse nostalgia, but it was never hard to bluescreen Vista, and I never considered those issues worth reporting.


Just debugged it and it looks like a NULL pointer read in CSRSS, in winsrv!SrvCreateConsoleScreenBuffer.


In fact, the same bug exists in XP, but the NULL page is mapped in XP which is why it does not BSoD. So far I have not seen writes, only reads.

Update: it looks like the NULL pointer is accessed several times in the code. They mostly are 16-bit accesses, so it is probably not addresses. They seems to be in font-related code.


Yes. Please report these bugs!


On Vista, conhost.also ran in user context and console windows were themed, on XP they was not. I believe that conhost.exe was introduced in Vista together with new desktop separation mechanism and on earlier version all the console window logic was internal to csrss (which in original NT design was essentially display server and window manager and placing console emulation in there makes some kind of sense given the NT's model of that).


Ah, yes, you're right! The windows were created directly.


Win7, not Vista.


How do you know all this? :)


Three years on Windows and Windows Phone. I sometimes miss those days. :-)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: