是否有可能伪造windows控制台api

本文关键字:控制台 api windows 伪造 有可能 是否 | 更新日期: 2023-09-27 18:12:39

我用c#编写了一个ssh服务器,我认为将powershell作为shell连接起来会很简洁。我已经尝试了2种方法来让这个正常工作,但两者都远非完美。以下是我尝试过的:

    启动powershell.exe并重定向它的std(in/out)。这并不工作良好,因为powershell.exe检测到它被重定向,更改它的行为。更重要的是,它期望在stdid上输入数据,而不是命令。所以它使用控制台api读取命令。
  1. "包装器"应用程序中的主机powershell。这样做的好处是能够为powershell提供一个"控制台"实现(通过PSHostRawUserInterface)。这样做效果更好,但您仍然可以调用命令(主要是真正的控制台应用程序),比如"…【更多】,谓之期待为了能够使用控制台api,然后尝试从

所以我想做的是用一组函数代替控制台应用程序使用的常规控制台输入/输出函数,这样我就可以处理它们了。但这似乎太激烈了,以至于成为一个糟糕的设计理念。

现在我的想法是通过发送本地/Pinvoke函数(如WriteConsoleInput)的相关键来操纵控制台。我认为这是可能的。但是我不知道如何"读取"控制台上发生的事情。

还请记住,它是一个服务,所以最好不要产生一个实际的控制台窗口,尽管可能在windows会话0中不会显示,也无关紧要。

是否有可能伪造windows控制台api

您有用于此目的的PSSession和Enter-PSSession CmdLet。在Powershell中,你的SSH会做什么,而PSSession没有做?

但是如果你想这样做,这里有一个不需要写任何东西的解决方案:通过SSH使用PowerShell


编辑02/11/2011

PowerShell内部提供了另一种无需编写任何内容的方法(个人使用免费)。

Host03的样例,也许可以提供基本的代码来做你想做的事情。

我按照JPBlanc的建议安装了PowerShellInside,但没有使用很长时间。一个连接的事情太局限了,我不喜欢被限制(特别是如果这个限制是基于利润的,但这是另一个我不应该讨论的话题)。尽管它是原始问题的解决方案,但感觉不满意,因为它不能解决我遇到的编程问题。

然而,我最终设法解决了这个问题,确实是通过在包装器进程中使用windows api调用。因为有很多陷阱,我决定回答我自己的问题,并给其他人看同样的问题一些提示。基本结构如下:

  • 使用重定向的stdin/out(如果需要,还可以使用stderr)启动包装器进程。(在我的情况下,stdin和out将是xterm控制序列和数据流,因为这是ssh的方式)
  • 使用GetStdHandle()检索重定向输入和输出句柄。接下来SetStdHandle()是"CONIN$"answers"CONOUT$"的CreateFile(),这样子进程继承了控制台而没有包装器进程的重定向。(注意,createfile需要允许继承的安全描述符)
  • 设置控制台模式、大小、标题、Ctrl-C处理程序等注意:如果你想要unicode支持,一定要设置一个字体,我使用Lucida Console(。FontFamily = 54, . facename = "Lucida Console")。否则,从控制台输出中读取字符将返回编码版本,这在托管代码中是非常可怕的。
  • 读取输出可以用SetWinEventHook()来完成,一定要使用上下文外的通知,因为我很确定,让你的托管应用程序突然在另一个进程上下文/地址空间中运行是一个坏主意™(我很确定,我甚至没有尝试)。事件将为每个控制台窗口触发,而不仅仅是您自己的控制台窗口。所以通过窗口句柄过滤所有对回调的调用。使用GetConsoleWindow()获取当前控制台应用程序的窗口句柄。另外,不要忘记在应用程序完成时取消回调。注意,到目前为止,请确保不要使用(或做任何导致系统负载的事情)系统。控制台类,否则事情很可能会出错。在此点之后的使用将表现为子进程已经写入输出。
  • 生成所需的子进程(注意,你必须使用。useshellexecute = false,否则它将不会继承控制台)
  • 你可以使用WriteConsoleInput()开始向控制台提供输入
  • 在这一点上(或在一个单独的线程上),你必须运行一个windows消息循环,否则你将不会收到控制台事件通知回调。您可以简单地使用无参数的Application.Run()来完成此操作。要中断消息循环,必须在某个时刻向消息循环发布退出消息。我在子进程的. exit事件中的Application.Exit()中做到了这一点。(注意使用.EnableRaisingEvents来工作)
  • 当控制台发生变化时,将调用win事件回调。注意滚动事件,这可能在某种程度上出乎意料。另外,不要对同步交付做任何假设。如果子进程写入3行,那么在处理第一个事件时,剩下的3行可能已经写入了。公平地说,windows在组合事件方面做得很好,这样你就不会被单个字符的变化所淹没,并且可以跟上变化。
  • 确保用CharSet=CharSet标记所有PInvoke定义。如果它们在输入或输出中包含字符,则使用Unicode。PInvoke.net漏掉了很多。

所有这些的最终结果是:windows控制台api的包装应用程序。包装器可以读/写重定向的标准输入和标准输出,以便与外界通信。当然,如果你想变得更花哨,你可以在这里使用任何流(命名管道,tcp/ip等)。我实现了一些xterm控制序列,并设法获得了一个完全工作的终端包装器,它应该能够包装任何windows控制台进程,将xterm输入转换为目标应用程序控制台输入上的输入,并将应用程序的输出处理为xterm控制序列。我甚至让鼠标工作了。将powershell.exe作为子进程启动现在解决了在ssh会话中运行powershell的原始问题。Cmd.exe也可以。如果有人感兴趣,我会考虑在某个地方发布完整的代码。