Tuesday, April 8, 2008

Usage And Compile Help For Linux/Unix Network Port Shell Program

Hey there,

Today's post is a follow up to yesterday's post on running a shell on a network socket. There are a few notes we'd like to add regarding compilation and usage, once you've got the program up and running on your Linux or Unix server.

First, the compile time note. Additional testing on other flavors of Linux showed that neither:

#include <sys/byteorder.h>

nor

#include <sys/endian.h>

worked on all systems :( We did find that this Linux "include" seems to work as a handy substitute for either:

#include <linux/byteorder/generic.h>

Of course, if none of these options work for you, we put comments in the code that name the functions and/or declarations that we're trying to grab from each of the includes. So, if you still find yourself in a pickle after trying all 3 of these include statements, you can probably find the correct include (.h header file) by typing the following at your command prompt:

host # find /usr/include |xargs egrep 'htons|htonl' /dev/null

It may be a bit tricky trying to find the correct include file, but it will probably have a name very similar to the 3 noted above.

Now, on to the fun stuff: Usage :)

To get this out of the way, if you've compiled and used the program to run a Linux or Unix shell on a network socket, you've probably noticed that the input and output don't behave exactly as you would expect in a regular shell.

Note that this line in the code:

execl("/bin/sh","sh",(char *)0);

was originally attempted in the following two manners (to try and force an interactive shell):

execl("/bin/sh","sh","-i",NULL); <--- Socket would connect, but then it would disconnect you immediately
execl("/bin/sh","sh","-i",(char *)0); <--- Socket would connect, and it wouldn't look ugly, but it wouldn't do anything else either (and we made sure it wasn't just an issue with echo by touching some files and verifying that they never got "touched" ;)

When all was said and done, this was the quickest, and dirtiest, way we could get the shell to answer on the network socket and be truly interactive. However, as mentioned above, it doesn't quite behave the way you might assume. Even shell built-in's don't work correctly for the most part, like in this mini-run-through:

host # ls
. .. netsock netsock.c
host # ./netsock
host # telnet localhost 40236
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
ls
: command not found
pwd
: command not found
id
: command not found
echo
: command not found


Yet, strangely enough, "echo," with arguments, works (???):

echo hi
hi


although "eval" doesn't work, straight up:

eval ls
: command not found


Now, we can start to have some fun :) Using the backtick operators to execute an "eval" statement and echoing that, we can actually do something, and get confirmation back on our terminal!:

echo `eval ls`
netsock netsock.c
<--- This will always pump the output out on one line, so if you have a lot of files in your directory, you'll get back a long long line.
echo `eval pwd`
/export/user/bin
echo `eval id`
uid=0(root) gid=0(root) groups=0(root)
<--- This will be your PID if you started the program, which may be good enough if you just need to get in and do something that doesn't require privilege. Note that this program runs the shell on the socket under the UID and GID of the user that invokes it (or their effective UID and GID at that time)
echo `eval touch TOUCHY`
<--- We'll touch something, just to see if it works. Of course, we get no terminal response to indicate success, but that's normal since we don't have a prompt to return to.

Now, if we disconnect from the Telnet connection and do an ls, we should have an extra file waiting for us:

^]
telnet> q
Connection closed.
host # ls
. .. netsock netsock.c TOUCHY


Good deal :) Now we'll write a simple script and see if we can execute it from the shell attached to the network port. If this works, it'll be much easier to stage work for the future:

host # vi test.sh
host # chmod 700 test.sh
host # cat test.sh
mkdir a
cd a
touch file
echo "ALL SET"
host # telnet localhost 40236
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
echo `eval ./test.sh`
ALL SET


And we get the output we expected! Just need to disconnect from Telnet again and check to make sure it actually did everything it was supposed to, and not just run the echo statement.

^]
telnet> q
Connection closed.
host # ls
. .. netsock netsock.c TOUCHY
a
host # ls a
. .. file


Success! Here's hoping this "how to" and compilation-assistance post helps you get more out of this program. If you haven't got the code already, please check out our post on running a shell on a network socket and have a blast!

Just, please, be considerate of others :)

Best wishes,

, Mike