|
@@ -31,13 +31,13 @@ int replace_packet(flow *f, uint8_t *packet){
|
|
|
|
|
|
tcp_hdr = (struct tcp_header*) p;
|
|
|
int size_tcp = TCP_HEADER_LEN(tcp_hdr);
|
|
|
- p += size_tcp;
|
|
|
|
|
|
/*fprintf(stderr,"Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
|
|
|
fprintf(stderr,"ID number: %u\n", htonl(ip_hdr->id));
|
|
|
fprintf(stderr,"Sequence number: %u\n", htonl(tcp_hdr->sequence_num));
|
|
|
fprintf(stderr,"Acknowledgement number: %u\n", htonl(tcp_hdr->ack_num));*/
|
|
|
- int app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
|
|
|
+ int32_t app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
|
|
|
+ printf("app_data length: %u\n", app_data_len);
|
|
|
if(app_data_len <= 0){
|
|
|
return 0;
|
|
|
}
|
|
@@ -46,6 +46,27 @@ int replace_packet(flow *f, uint8_t *packet){
|
|
|
if(ip_hdr->src.s_addr == f->src_ip.s_addr){
|
|
|
read_header(f, packet);
|
|
|
return 0;
|
|
|
+ } else {
|
|
|
+ printf("Current sequence number: %d\n", f->seq_num);
|
|
|
+ printf("Received sequence number: %d\n", htonl(tcp_hdr->sequence_num));
|
|
|
+ uint32_t offset = htonl(tcp_hdr->sequence_num) - f->seq_num;
|
|
|
+ if(offset == 0)
|
|
|
+ f->seq_num += app_data_len;
|
|
|
+ /* if incoming, replace with data from queue */
|
|
|
+ //if(htonl(tcp_hdr->sequence_num) >= f->seq_num){
|
|
|
+ replace_contents(f, p, app_data_len, offset, ip_hdr->src, ip_hdr->dst);
|
|
|
+ //}//TODO: need to do something about replaying packets (maybe store previously sent data??
|
|
|
+
|
|
|
+ p = packet + ETHER_HEADER_LEN;
|
|
|
+#ifdef DEBUG
|
|
|
+ fprintf(stdout, "ip hdr length: %d\n", htons(ip_hdr->len));
|
|
|
+ fprintf(stdout, "Injecting the following packet:\n");
|
|
|
+ for(int i=0; i< htons(ip_hdr->len); i++){
|
|
|
+ fprintf(stdout, "%02x ", p[i]);
|
|
|
+ }
|
|
|
+ fprintf(stdout, "\n");
|
|
|
+ fflush(stdout);
|
|
|
+#endif
|
|
|
}
|
|
|
return 0;
|
|
|
|
|
@@ -85,14 +106,24 @@ int read_header(flow *f, uint8_t *packet){
|
|
|
|
|
|
memcpy(decrypted_data, p, record_length);
|
|
|
|
|
|
- if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, 0x17)){
|
|
|
- fprintf(stderr,"decryption failed\n");
|
|
|
+ if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, record_hdr->type, 0)){
|
|
|
+ fprintf(stdout,"decryption failed\n");
|
|
|
return 0;
|
|
|
} else {
|
|
|
- fprintf(stderr, "decryption succeeded!\n");
|
|
|
- decrypted_data+= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
- fprintf(stderr, "request:");
|
|
|
- fprintf(stderr,"%s\n ", decrypted_data);
|
|
|
+ fprintf(stdout, "decryption succeeded!\n");
|
|
|
+ if(record_hdr->type == 0x17){
|
|
|
+ decrypted_data+= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+ fprintf(stdout, "request:");
|
|
|
+ fprintf(stdout,"%s\n ", decrypted_data);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if(record_hdr->type == 0x15){
|
|
|
+ printf("received alert\n");
|
|
|
+ for(int i=0; i<record_length; i++){
|
|
|
+ printf("%02x ", decrypted_data[i]);
|
|
|
+ }
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
|
|
|
/* search through decrypted data for x-ignore */
|
|
@@ -196,6 +227,7 @@ int read_header(flow *f, uint8_t *packet){
|
|
|
for(int i=0; i< bytes_read; i++){
|
|
|
f->censored_queue[i] = buf[i];
|
|
|
}
|
|
|
+ f->censored_length = bytes_read;
|
|
|
|
|
|
//for now, just close socket
|
|
|
close(handle);
|
|
@@ -203,3 +235,282 @@ int read_header(flow *f, uint8_t *packet){
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, struct in_addr src, struct in_addr dst){
|
|
|
+
|
|
|
+ printf("Replacing contents...\n");
|
|
|
+ uint8_t *p = data;
|
|
|
+
|
|
|
+ struct tcp_header *tcp_hdr = (struct tcp_header*) p;
|
|
|
+ int size_tcp = TCP_HEADER_LEN(tcp_hdr);
|
|
|
+ p += size_tcp;
|
|
|
+
|
|
|
+ int32_t tmp_len = data_len;
|
|
|
+
|
|
|
+ //step 1: replace record contents
|
|
|
+ //note: encrypted message will be original message size + EVP_GCM_TLS_EXPLICIT_IV_LEN + 16 byte pad
|
|
|
+ //first check to see if there's anything in the outbox
|
|
|
+ if(f->outbox_len > 0){
|
|
|
+ printf("Printing from outbox\n");
|
|
|
+ if(f->outbox_len < data_len){
|
|
|
+ printf("Next record:\n");
|
|
|
+ for(int i=0; i< RECORD_HEADER_LEN; i++){
|
|
|
+ printf("%02x ", p[f->outbox_len+i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ } else {
|
|
|
+ printf("Outbox takes up entire packet\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ if(tmp_len >= f->outbox_len){
|
|
|
+ memcpy(p, f->outbox, f->outbox_len);
|
|
|
+
|
|
|
+ p += f->outbox_len;
|
|
|
+ tmp_len -= f->outbox_len;
|
|
|
+ f->outbox_len = 0;
|
|
|
+ free(f->outbox);
|
|
|
+ printf("outbox now empty\n");
|
|
|
+ } else {
|
|
|
+ printf("Outbox has %d - %d bytes\n", f->outbox_len, tmp_len);
|
|
|
+ memcpy(p, f->outbox, tmp_len);
|
|
|
+ uint8_t *tmp = calloc(1, f->outbox_len - tmp_len);
|
|
|
+ f->outbox_len -= tmp_len;
|
|
|
+ memcpy(tmp, f->outbox + tmp_len, f->outbox_len);
|
|
|
+ free(f->outbox);
|
|
|
+ f->outbox = tmp;
|
|
|
+ printf(" = %d bytes left in outbox\n", f->outbox_len);
|
|
|
+ tmp_len -= tmp_len;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ while(tmp_len > 0){
|
|
|
+
|
|
|
+ struct record_header *record_hdr = (struct record_header*) p;
|
|
|
+ uint32_t record_length = RECORD_LEN(record_hdr);
|
|
|
+ fprintf(stdout, "Record:\n");
|
|
|
+ for(int i=0; i< RECORD_HEADER_LEN; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ p += RECORD_HEADER_LEN;
|
|
|
+ if(record_hdr->type != 0x17){
|
|
|
+ //TODO: might need to decrypt and re-encrypt
|
|
|
+ printf("received non-application data\n");
|
|
|
+ tmp_len -= (record_length+ RECORD_HEADER_LEN);
|
|
|
+ p += record_length;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t *new_record = calloc(1, record_length);
|
|
|
+ memcpy(new_record, p, record_length);
|
|
|
+ uint8_t *tmp_p = new_record;
|
|
|
+
|
|
|
+
|
|
|
+ /*// BEGIN TEST CODE //
|
|
|
+
|
|
|
+ //Print original record
|
|
|
+ printf("Original record (%d bytes):\n", record_length);
|
|
|
+ for(int i=0; i< record_length; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ //print few bytes of next record (if present)
|
|
|
+ if(data_len > record_length + RECORD_HEADER_LEN){
|
|
|
+ printf("Next record:\n");
|
|
|
+ for(int i=0; i< RECORD_HEADER_LEN; i++){
|
|
|
+ printf("%02x ", p[record_length+i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ } else {
|
|
|
+ printf("No extra record: %d = %d + %d\n", data_len, record_length, RECORD_HEADER_LEN);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //Decrypt record
|
|
|
+ printf("Decrypting record... ");
|
|
|
+ int n;
|
|
|
+ if(!(n = encrypt(f, p, p, record_length, 1, 0x17, 0))){
|
|
|
+ fprintf(stderr,"failed\n");
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "succeeded!\n");
|
|
|
+ printf("Decrypted record:\n");
|
|
|
+ for(int i=0; i< record_length; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ printf("%s\n", p+ EVP_GCM_TLS_EXPLICIT_IV_LEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ //return seq to what it was
|
|
|
+ for(int i=7; i>=0; i--){
|
|
|
+ --f->read_seq[i];
|
|
|
+ if(f->read_seq[i] >= 0)
|
|
|
+ break;
|
|
|
+ else
|
|
|
+ f->read_seq[i] = 0;
|
|
|
+ }
|
|
|
+ printf("seq reverted (%s): ", "read");
|
|
|
+ for(int i=0; i<8; i++){
|
|
|
+ printf("%02x ", f->read_seq[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ //Now reposition it to be fed into encrypt function
|
|
|
+ //memcpy(p, p+ EVP_GCM_TLS_EXPLICIT_IV_LEN, n);
|
|
|
+
|
|
|
+ // END TEST CODE */
|
|
|
+
|
|
|
+ //step 2: figure out what happens if we don't have data
|
|
|
+ tmp_p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+
|
|
|
+ struct slitheen_header *sl_hdr = (struct slitheen_header *) tmp_p;
|
|
|
+ sl_hdr->marker = 0x01;
|
|
|
+ sl_hdr->version = 0x01;
|
|
|
+ int32_t remaining = record_length - (SLITHEEN_HEADER_LEN
|
|
|
+ + EVP_GCM_TLS_EXPLICIT_IV_LEN + 16);
|
|
|
+ fprintf(stdout, "filling with censored queue data (%d out of %d) at offset %d\n", remaining, f->censored_length-offset, offset);
|
|
|
+ if(remaining > 0){
|
|
|
+ if(remaining+offset <= f->censored_length){
|
|
|
+ fprintf(stdout, "We have enough data to fill the record\n");
|
|
|
+ for(int i = 0; i< remaining; i++){
|
|
|
+ tmp_p[SLITHEEN_HEADER_LEN+i] = f->censored_queue[i + offset];
|
|
|
+ }
|
|
|
+ //TODO: when I restructure this for more data, figure out freeing these pointers
|
|
|
+ f->censored_queue += remaining;
|
|
|
+ f->censored_length -= remaining;
|
|
|
+ sl_hdr->len = htons(remaining);
|
|
|
+ fprintf(stdout, "copied %d data\n", ntohs(sl_hdr->len));
|
|
|
+
|
|
|
+ } else {
|
|
|
+ int32_t dummy_offset = f->censored_length - offset;
|
|
|
+ if(dummy_offset < 0) dummy_offset = 0;
|
|
|
+ fprintf(stdout, "Not enough data (%d bytes)\n", dummy_offset);
|
|
|
+ for(int i = 0; i< dummy_offset; i++){
|
|
|
+ tmp_p[SLITHEEN_HEADER_LEN+i] = f->censored_queue[i + offset];
|
|
|
+ }
|
|
|
+ //TODO: note, we may also be receiving misordered packets. Take Ian's suggestion into account here
|
|
|
+ f->censored_queue += dummy_offset;
|
|
|
+ f->censored_length -= dummy_offset;
|
|
|
+ sl_hdr->len = htons(dummy_offset);
|
|
|
+ //TODO: should i < record_length or remaining??
|
|
|
+ for(int i = dummy_offset; i< remaining; i++){
|
|
|
+ tmp_p[SLITHEEN_HEADER_LEN+i] = 'A';
|
|
|
+ }
|
|
|
+ fprintf(stdout, "copied %d data and %d garbage bytes\n", ntohs(sl_hdr->len), remaining - dummy_offset);
|
|
|
+ }
|
|
|
+ printf("Slitheen header\n");
|
|
|
+ for(int i=0; i<4; i++)
|
|
|
+ printf("%02x ", tmp_p[i]);
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+ tmp_p -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+ //step 3: encrypt new record
|
|
|
+ //fprintf(stderr, "computing mac\n");
|
|
|
+ //int32_t mac_size = mac(f, p, p+(record_length - (EVP_GCM_TLS_EXPLICIT_IV_LEN + 16)), record_length - (EVP_GCM_TLS_EXPLICIT_IV_LEN + 16), 1, 0x17, 1);
|
|
|
+ //printf(stderr, "mac size: %d\n", mac_size);
|
|
|
+ //fprintf(stderr, "encrypting\n");
|
|
|
+ int32_t success;
|
|
|
+ if((success = encrypt(f, tmp_p, tmp_p, record_length-16, 1, 0x17, 1))< 0){
|
|
|
+ fprintf(stdout,"encryption failed\n");
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ fprintf(stdout, "encryption succeeded!\n");
|
|
|
+ //printf("Encrypted data:\n");
|
|
|
+ //for(int i=0; i< success; i++){
|
|
|
+ // printf("%02x ", tmp_p[i]);
|
|
|
+ //}
|
|
|
+ //printf("\n");
|
|
|
+ }
|
|
|
+ //copy new record into packet
|
|
|
+ if(record_length +RECORD_HEADER_LEN > tmp_len){
|
|
|
+ //We have a partial record
|
|
|
+ printf("Warning: partial record\n");
|
|
|
+ memcpy(p, new_record, tmp_len - RECORD_HEADER_LEN);
|
|
|
+ f->outbox_len = record_length - (tmp_len - RECORD_HEADER_LEN);
|
|
|
+ //save left-overs in outbox
|
|
|
+ f->outbox = calloc(1, f->outbox_len);
|
|
|
+ memcpy(f->outbox, new_record + (tmp_len - RECORD_HEADER_LEN),
|
|
|
+ f->outbox_len);
|
|
|
+ free(new_record);
|
|
|
+ printf("Outbox has %d = %d - %d bytes\n", f->outbox_len, record_length+RECORD_HEADER_LEN, tmp_len);
|
|
|
+ } else {
|
|
|
+ memcpy(p, new_record, record_length);
|
|
|
+ free(new_record);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //check to see if next record still exists
|
|
|
+ if(data_len > record_length + RECORD_HEADER_LEN){
|
|
|
+ printf("Next record:\n");
|
|
|
+ for(int i=0; i< RECORD_HEADER_LEN; i++){
|
|
|
+ printf("%02x ", p[record_length+i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ } else {
|
|
|
+ printf("No extra record: %d <= %d + %d\n", data_len, record_length, RECORD_HEADER_LEN);
|
|
|
+ }
|
|
|
+ tmp_len -= record_length+ RECORD_HEADER_LEN;
|
|
|
+ p += record_length;
|
|
|
+
|
|
|
+ }
|
|
|
+ //step 4: recompute TCP checksum
|
|
|
+ p = data;
|
|
|
+ p[16] = 0; p[17] = 0;//zero out checksum
|
|
|
+ uint16_t chksm = tcp_checksum(p, data_len, src, dst);
|
|
|
+ p[17] = chksm & 0xFF;
|
|
|
+ p[16] = chksm >> 8;
|
|
|
+ fprintf(stdout, "Checksum: 0x%0x%0x\n", p[16], p[17]);
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/** Computes the TCP checksum of the data according to RFC 793
|
|
|
+ * sum all 16-bit words in the segment, padd the last word if
|
|
|
+ * needed
|
|
|
+ *
|
|
|
+ * there is a pseudo-header prefixed to the segment and
|
|
|
+ * included in the checksum:
|
|
|
+ *
|
|
|
+ * +--------+--------+--------+--------+
|
|
|
+ * | Source Address |
|
|
|
+ * +--------+--------+--------+--------+
|
|
|
+ * | Destination Address |
|
|
|
+ * +--------+--------+--------+--------+
|
|
|
+ * | zero | PTCL | TCP Length |
|
|
|
+ * +--------+--------+--------+--------+
|
|
|
+ */
|
|
|
+uint16_t tcp_checksum(uint8_t *data, int32_t data_len, struct in_addr src, struct in_addr dst){
|
|
|
+
|
|
|
+ uint8_t *p = data;
|
|
|
+
|
|
|
+ struct tcp_header *tcp_hdr = (struct tcp_header*) p;
|
|
|
+ int size_tcp = TCP_HEADER_LEN(tcp_hdr);
|
|
|
+ //Construct pseudo-header
|
|
|
+ uint16_t tcp_length = data_len + size_tcp;
|
|
|
+ uint8_t proto = IPPROTO_TCP;
|
|
|
+ fprintf(stdout, "summing pseudoheader\n");
|
|
|
+ uint32_t sum = (ntohl(src.s_addr)) >> 16;
|
|
|
+ sum += (ntohl(src.s_addr)) &0xFFFF;
|
|
|
+ sum += (ntohl(dst.s_addr)) >> 16;
|
|
|
+ sum += (ntohl(dst.s_addr)) & 0xFFFF;
|
|
|
+ sum += proto;
|
|
|
+ sum += tcp_length;
|
|
|
+
|
|
|
+ //now sum the text
|
|
|
+ for(int i=0; i< tcp_length-1; i+=2){
|
|
|
+ sum += (uint16_t) ((p[i] << 8) + p[i+1]);
|
|
|
+
|
|
|
+ }
|
|
|
+ if(tcp_length %2 != 0){
|
|
|
+ sum += (uint16_t) (p[tcp_length - 1]) << 8;
|
|
|
+ }
|
|
|
+ //now add most significant to last significant bits
|
|
|
+ sum = (sum >> 16) + (sum & 0xFFFF);
|
|
|
+ //now subtract from 0xFF
|
|
|
+ sum = 0xFFFF - sum;
|
|
|
+ return (uint16_t) sum;
|
|
|
+}
|