【问题标题】:Is there a way to send data to another process's standard input under Mac OS?有没有办法在 Mac OS 下将数据发送到另一个进程的标准输入?
【发布时间】:2010-08-21 01:31:17
【问题描述】:

我想知道是否有一个 API,无论它多么晦涩难懂,它允许某人在 Mac OS X 下将数据发送到另一个进程的 stdin 流。在 Linux 下,如果我没记错的话,你可以使用文件系统在/proc 中访问这些流(当然需要正确的权限)。

我不知道。 Mach 端口,有人知道吗?

【问题讨论】:

    标签: macos stdin


    【解决方案1】:

    只是一个想法,但您不能制作一个管道,并在启动该进程时将该(命名的)管道重定向到该进程的标准输入吗?

    大概是这样的

    mkfifo MYPIPE
    Prog < MYPIPE
    echo "test" > MYPIPE
    

    【讨论】:

    • 我不是启动进程的人,所以我不能这样做。
    • 所以您希望您的 Adium 插件插入其他一些正在运行的命令行进程的输入?你可能又回到了马赫注入……
    • @AlexanderMills 你可以试试看。但答案是……mkfifo 以代码 1 退出并将“mkfifo: MYPIPE: File exists”写入标准错误。
    【解决方案2】:

    不幸的是,我不相信你能做到这一点——MacPorts 都是用户空间,你需要的操作需要(或者很多技巧,见下文,或者)内核合作,我相信这不是即将到来。例如,Mac OSX Internals, a System Approach 在文件描述符传递部分中说

    描述符是进程本地的 因为它只在 获得的过程 描述符说,通过打开一个文件。在 特别是,进程 A 无法访问 在另一个进程中打开的文件 B 通过简单地使用 表示该文件的描述符 B.

    然后继续描述 FD 是如何发送的。

    “诡计”部分将要求您获取一些代码以在其他进程中运行(在用户态或作为内核的一部分)。

    例如,您可以在用户空间中通过修补可执行文件的二进制文件来做到这一点——在其启动路径的早期找到任何肯定会执行的指令,然后跳转到您自己的代码,该代码会发送FD 到您的监视守护进程,执行修补后的指令,然后跳回到另一个进程的正常顺序流。

    要在内核级别执行此操作,需要对内核代码本身或内核加载的代码进行类似的补丁并且以完整的、未经验证的信任运行(这样他们就可以劫持不相关进程的文件描述符表条目)——我当然希望 Mac OS X 中没有这样的代码路径(因为它们的主要用途无疑是病毒、特洛伊木马和其他各种恶意软件)但是,如果有的话,你可以找到它们,这可能是比修补每个感兴趣的二进制可执行文件更通用的解决方案。

    回到用户态,另一种相当通用的方法可能是修补所有感兴趣的进程加载的动态加载的库,而不是修补各种进程的几个可执行文件。

    【讨论】:

    • 好吧,一个人可以安装驱动程序并整天劫持内核;但这当然首先需要管理权限,无论如何基本上都可以破坏安装。
    • @Billy,一般的问题是典型的 MacOSX 用户确实拥有管理权限,不幸的是,在请求时,他习惯于输入密码,以启用从网上下载的任何内容的安装。我认为安装驱动程序不需要任何不同,不是吗?
    • 不,没有什么不同。也就是说,如果一个程序可以获得管理员权限,它就可以完全摧毁机器。相比之下,能够为进程重定向标准输入相对较小。
    【解决方案3】:

    如果你在终端运行目标进程,那么你可以使用writevt,它的源代码是here。

    例如,假设您在终端 ttys000 上运行“cat”命令。

    在 1 号航站楼:

    $ tty
    /dev/ttys000
    $ cat
    

    在 2 号航站楼:

    $ sudo ./writevt /dev/ttys000 'Hello!^M'
    

    上面的^M 是一个控制字符。在我的 Mac 上,您可以通过键入 Ctrl-V 后跟 Ctrl-&lt;enter&gt; 来输入此字符。

    这是 1 号航站楼的结果:

    $ tty
    /dev/ttys000
    $ cat
    Hello!
    Hello!
    

    writevt程序可以用gcc从writevt.c源文件编译:

    $ gcc -o writevt writevt.c 
    

    【讨论】:

    • 这是一个不错的解决方案。将其与sudo chown root:wheel writevt 和sudo chmod 4755 writevt 结合使用,之后您可以在不使用sudo 命令的情况下使用writevt。如所述here
    【解决方案4】:

    假设它是在用户许可的情况下(即您想从第三方应用程序捕获信息,以重定向到另一个应用程序,例如 Rogue Amoeba 的音频应用程序或某些视频流捕获应用程序),那么我会说您要么想要查看内核扩展或输入管理器。

    (另请参见 fscript anywhere、SIMBL 和 Application Enhancer - 将功能注入第三方应用程序的所有软件示例)。

    许多旧的用户驱动代码注入技术在 10.6 中受到限制(例如,输入管理器更难安装)。

    如果您对用户输入而不是标准输入感兴趣,那么替代输入法工具包实际上可能“足够好” - 传统上,输入管理器已被用于将各种代码注入应用程序。

    另一方面,如果您想在没有用户许可的情况下执行此操作(即密钥记录),那么您就是在进行黑客攻击。可能有一系列尚未修补的漏洞可以组合起来做你想做的事,但知道它的人很可能会从中赚钱。

    【讨论】:

    • 不不,我真的只是想把东西放到标准输入中。甚至没有从中读取。我只想将用户输入从我的程序传输到另一个程序的标准输入,该标准输入是在我之前启动的。
    • 鉴于 AppleScript 可以模拟单独的按键和鼠标事件,以及更高级别的操作(如粘贴),我想知道 AppleEvent API 是否可以工作 - 它比标准输入更高的级别 / 仅适用于 Cocoa应用程序,但通过这种方式或许可以实现您的目标。
    • 好吧,我不喜欢捕获 stdin。相反,我想将数据注入其中。
    • 我是这么理解的。 AppleEvent API 允许您将事件(诸如“shift-key-down”之类的键事件、文本字符串、粘贴之类的操作)等传递到正在运行的程序中。它处于 Cocoa 级别而不是 Unix 级别,但如果 AppleEvent API 支持您要发送的数据,则它可能是一个选项。它是控制/编写第三方应用程序的受支持选项(有限)
    • 哦,我明白了。我想,当我读到你的评论时,我太困了。处于 Cocoa 而不是 UNIX 级别可能是一个问题:通过stdin 进行通信与通过击键进行通信在很大程度上不同。我很确定我没有输入 Safari 的标准输入来写这个评论;而且我很确定 UNIX CLI 程序本身不会响应击键。
    【解决方案5】:

    好吧,从技术上讲,您可以将线程注入目标进程,然后让它将标准输入文件描述符的副本发送回给您……但您可能不应该这样做。 :-)

    你真正想做什么?

    【讨论】:

    • 好吧,我为 Adium(一个聊天客户端)制作了一个插件,它可以从文本输入启动进程并将输出发送到对话。但是,我无法从 Adium 访问已启动进程的 stdin 流,因此我认为将数据注入 stdin 而不是从我的插件中找到真正可行的解决方案会很“有趣”。
    • 无论如何,写入stdin 会失败并返回fwrite,而write(0, ...) 会写入终端,但不会通过进一步的read 调用使该数据可读。只是为了科学,知道我该如何解决这个问题吗?
    • 我建议在下面探索 JulesLt 的建议……如果 Adium 实现了 AppleScript 接口,那可能是允许您的插件发送聊天消息的最佳方式(如果我理解正确的话)做)。如果 Adium 是一个 Cocoa GUI 应用程序,它无论如何都不会从标准输入读取! Mach 注入是一种高级技术……就像在进程之间传递打开的文件描述符一样。编写简单的应用程序插件可能不需要这种达尔文水平。
    • 我的计划是制作一个独立的程序,我可以从我的插件中调用它来与另一个进程的stdin 对话。我也不怕低级的东西。
    • 啊,重新阅读您的回复,您似乎不是要插入 Adium 的标准输入,而是您的插件正在启动的进程?这是一个更简单的场景,只需要标准的 Unix 舞蹈,即为您自己 fork/spawn 的子进程提供文件描述符。 (这是否准确地描述了您正在做的事情?)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    相关资源
    最近更新 更多