« NTP Tunnel and Data Exfiltration (or Shell over NTP)Enhancement Ideas for DNS MRE Tool »

Piping a Shell

08/19/08

Permalink 02:29:52 am, Categories: coding

One of the traditional methods of any exploit is to pass a “shellcode” that spawns a shell. The attacker then would have a remote shell over TCP stream. The way to spawn a shell, not necessary through a shellcode but in any general way, is done by executing the following function:

     char *str[] = {“/bin/sh”};	
     execve( “bin/sh”, str, NULL);

Executing this will simply spawns an interactive shell. If this was executed locally, the input and output streams are the standard input (stdin) and the standard output (stdout). However, when it is executed remotely, the input and output streams are piped to the TCP stream.

However, what if a user wants to have a local program running and executing commands received remotely, or from an input stream other than ‘stdin’ ? there are various proposed ways to do that. Looking at the exec() family (i.e. execl, execlp, execv, execvp, and execve), these functions do not give the user a control over the input stream or output stream, they only return a status code indicating success or failure. On the other hand, there is the popen() function which actually executes a command while giving the user a file descriptor to either write input or read output of the command. For example, the following code snippet lets the user execute the command “ls –l” and get the output within the program:

     FILE *fd;
     fd = popen( “ls –l”, “r” );
     while( fgets(line, sizeof line, fd) ) 
          printf(“%s”, line);

Such piece of code would be handy to use in a program that receives commands remotely from a user, or locally from a file, and pipes the output to whatever the user wants. However, there is one drawback to such implementation, that is, a command like “cd” will not work, and the user will not be able to navigate between directories. So, in order to have a full interactive shell, the command that needs to be executed is the shell itself, i.e. “sh”. But now we face another problem, running “sh” from popen() function will actually spawns a shell where its input and output are bound to stdin and stdout, and we will not be using the piping functionality provided by pipe.

The best way to run a fully interactive shell where its input and output are controlled by the user is to execute “sh” by one of the exec() functions and at the same take control of the stdin and stdout through the use of pipes; typically, two pipes are needed. The following diagram simplifies the description:

----------------- |           | -----------------
 -->  pipe1 -->    > /bin/sh >   --> Pipe2 -->	
----------------- |           | -----------------

The steps to implement this are as follows:
1] Create two pipes (p1 and p2) and two FILE pointers (ptr1 and ptr2).
2] Fork a child process [pid=fork()].
3] The child process takes control of stdin and stdout by associating them with the reading-end of the first pipe and the writing-end of the second pipe, respectively.
4] The child process spawns a shell (“/bin/sh”) using an execlp() function.
5] The parent process associates the file descriptors with the writing-end of the first pipe and with the reading-end of the second pipe.
6] Anything written to the first file descriptor will be passed as input to the running interactive shell; and any results from the interactive shell can be read from the second file descriptor.
...

int p1[2], p2[2];
FILE *ptr1, ptr2;
pipe(p1); pipe(p2);
pid=fork;
if( pid == 0 ){
  close(0);    /* close the stdin */
  dup(p1[0]);  /* reading-end of pipe1 takes 
                  control of stdin */
  close(1);    /* close the stdout */
  dup(p2[1]);  /* writing-end of pipe2 takes 
                  control of stdout */
  execlp(“/bin/sh”, “sh”, NULL, NULL)
}
ptr1 = fdopen( p1[1], “w” ); /* writing-end of pipe1 */
ptr2 = fdopen( p2[0], “r” ); /* reading-end of pipe2 */
fprintf( ptr1, “ls –l” );
while( fgets( line, 50, ptr2) ) printf(“%s”, line);

...

In this case, the user has an interactive shell with cd-ing and also can control the input and output stream.

References:
- Popen specification
- Fork, Exec and Process control
- Using the UNIX Pipe in C

Follow up:

Feedback awaiting moderation

This post has 2 feedbacks awaiting moderation...

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)
March 2010
Sun Mon Tue Wed Thu Fri Sat
 << <   > >>
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

This is the Blog of Securebits Think-Tank. It is maintained by AR Samhuri. The blog is about topics like Network Security, Penetration Testing, TCP/IP Attacks, Security R&D, Security Tools, etc.

Search

XML Feeds

powered by b2evolution free blog software