1

I know that running cat with no argument reflects the user input

$ cat
test
test
reflected
reflected

I want to pipe the reflected output to another program such as base64. The expected behavior is like so

$ cat | base64
test
dGVzdA==
another
YW5vdGhlcg==

I want this for encoding text line-by-line as I type, and/or send them over something like nc. However, when used like this, no output seems to be reflected and escaping with ctrl+C just terminates the whole thing without output

$ cat | base64
test
fail
^C

With everything working correctly, I should be able to establish an encoded/encrypted connection (very simple chat application) like so

# client
$ $CMD | encrypt | nc $SERVER $PORT
this is a test
multiple lines
^C

# host
$ nc -lvp | decrypt
this is a test
multiple lines

Similarly, I should be able to encode & save as follows

$ CMD | base64  | tee log_file
test
dGVzdA==
another
YW5vdGhlcg==
^C

$ cat log_file
dGVzdA==
YW5vdGhlcg==

Note that the whole thing should be a single pipe line. Using a loop wouldn't work well as nc would establish a new connection every iteration and tee without -a would overwrite the file every line (per iteration). I want 1 single instance of the final command (e.g. nc, base64) taking input pipe from CMD like with cat but with user input instead of a file.

I'm looking for a way to do said piping of user input line-by-line to another process, preferably as a short one-liner. How can I get such piping of user input?

8
  • 2
    There's a while-loop answer that was deleted, which you'd misunderstood going by your comment there, I think. while read x; do echo "$x" | base64; done | nc ... seems to be what you're looking for.
    – muru
    Commented Jan 20, 2021 at 11:16
  • @muru Your specific command does work as intended. However, I'm trying to split this command into 2 parts: (1) the read-and-reflect (here, the while loop), and (2) the target command (base64, nc, etc.) and make those 2 separate. This is so that anything that would take input from stdin can all be put on the same side for more complex implementations of such a pipe line. Commented Jan 20, 2021 at 12:02
  • 1
    I think there's a disconnect here. You have two target commands per invocation, not one - one that does line-by-line, and the second which takes the first's complete output. So you can put the while loop in a function which takes the first command as an argument, and then you pipe the output of the function to the second command.
    – muru
    Commented Jan 20, 2021 at 12:45
  • 1
    So, two target commands, (1) and (2), which tallies with what I said.
    – muru
    Commented Jan 20, 2021 at 13:58
  • 1
    So parametrise it by using a function, like I said earlier.
    – muru
    Commented Jan 20, 2021 at 14:08

2 Answers 2

1

Something like this?

# this is an infinite loop, but can be changed to whatever you need
while true; do read x; echo "$x" | base64; done

Output:

foo
Zm9vCg==
bar
YmFyCg==
1
  • Trying this with while true; do read x; echo "$x" | nc localhost 1337; done, the piping doesn't persist and nc seems to only send the 1st line of the loop. Commented Jan 20, 2021 at 4:35
1

I've figured out why cat | base64 doesn't work as I intended. base64 needs to take in all of the input, terminated by (I think) an EOF. Since output from cat doesn't have the terminator, base64 never stopped taking in and buffering the input, and ctrl-C terminates both cat and base64. Basically, base64 is waiting for the output from cat to end with EOF but cat doesn't output EOF, so the encoded output never got to be returned. By using cat << EOF | base64, the user input is reflected and piped to base64 but is only output once EOF is entered.

$ cat << EOF | base64
pipe heredoc> ls
pipe heredoc> test
pipe heredoc> EOF
bHMKdGVzdAo=

On the other hand, nc takes in user input continuously and its inputs can be separated with \n. Therefore, the piping works with cat | nc. That's how cat and nc are often used to get shells in pentesting & CTFs

Bind shell

# user
$ cat | nc $IP 1337

# target
$ nc -lp 1337

Reverse shell

# user
$ cat | nc -lp 1337

# target
$ nc $IP 1337

Due to the difference in buffering and terminators between applications (base64 and nc), the pipe line I wanted to make isn't possible without some adjustments. The final chain can be achieved by putting commands with return all output in one go (e.g. base64) inside a while loop, and commands which take input line-by-line (e.g. nc on the right of the pipe)

# code courtesy of @muru in the comments
while read x; do
   echo "$x" | base64
done | nc

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .