struct flow_record * process_tcp(const struct pcap_pkthdr *h, const void *tcp_start, int tcp_len, struct flow_key *key) { unsigned int tcp_hdr_len; const unsigned char *payload; unsigned int payload_len; const struct tcp_hdr *tcp = (const struct tcp_hdr *)tcp_start; struct flow_record *record = NULL; unsigned int cur_itr = 0; if (output_level > none) { fprintf(output, " protocol: TCP\n"); } // tcp_hdr_len = TCP_OFF(tcp)*4; tcp_hdr_len = tcp_hdr_length(tcp); if (tcp_hdr_len < 20 || tcp_hdr_len > tcp_len) { // fprintf(output, " * Invalid TCP header length: %u bytes\n", tcp_hdr_len); return NULL; } /* define/compute tcp payload (segment) offset */ payload = (unsigned char *)(tcp_start + tcp_hdr_len); /* compute tcp payload (segment) size */ payload_len = tcp_len - tcp_hdr_len; if (output_level > none) { fprintf(output, " src port: %d\n", ntohs(tcp->src_port)); fprintf(output, " dst port: %d\n", ntohs(tcp->dst_port)); fprintf(output, "payload len: %u\n", payload_len); fprintf(output, " tcp len: %u\n", tcp_len); fprintf(output, "tcp hdr len: %u\n", tcp_hdr_len); fprintf(output, " flags:"); if (tcp->tcp_flags & TCP_FIN) { fprintf(output, "FIN "); } if (tcp->tcp_flags & TCP_SYN) { fprintf(output, "SYN "); } if (tcp->tcp_flags & TCP_RST) { fprintf(output, "RST "); } if (tcp->tcp_flags & TCP_PSH) { fprintf(output, "PSH "); } if (tcp->tcp_flags & TCP_ACK) { fprintf(output, "ACK "); } if (tcp->tcp_flags & TCP_URG) { fprintf(output, "URG "); } if (tcp->tcp_flags & TCP_ECE) { fprintf(output, "ECE "); } if (tcp->tcp_flags & TCP_CWR) { fprintf(output, "CWR "); } fprintf(output, "\n"); if (output_level > packet_summary) { if (payload_len > 0) { fprintf(output, " payload:\n"); print_payload(payload, payload_len); } } } key->sp = ntohs(tcp->src_port); key->dp = ntohs(tcp->dst_port); record = flow_key_get_record(key, CREATE_RECORDS); if (record == NULL) { return NULL; } if (output_level > none) { fprintf(output, " SEQ: %d\trelative SEQ: %d\n", ntohl(tcp->tcp_seq), ntohl(tcp->tcp_seq) - record->seq); fprintf(output, " ACK: %d\trelative ACK: %d\n", ntohl(tcp->tcp_ack), ntohl(tcp->tcp_ack) - record->ack); // fprintf(output, " SEQ: %d\n", ntohl(tcp->tcp_seq) - record->seq); // fprintf(output, " ACK: %d\n", ntohl(tcp->tcp_ack) - record->ack); } if (payload_len > 0) { if (ntohl(tcp->tcp_seq) < record->seq) { // fprintf(info, "retransmission detected\n"); record->retrans++; } } if (include_zeroes || payload_len > 0) { flow_record_process_packet_length_and_time_ack(record, payload_len, &h->ts, tcp); } // if initial SYN/ACK packet, parse TCP options unsigned int offset = 20; if (tcp->tcp_flags == 2 || tcp->tcp_flags == 18) { // SYN==2, SYN/ACK==18 // get initial window size if (!record->tcp_initial_window_size) { record->tcp_initial_window_size = ntohs(tcp->tcp_win); } // get SYN packet size if (tcp->tcp_flags == 2) { record->tcp_syn_size = tcp_len; } // parse TCP options cur_itr = 0; while (offset < tcp_hdr_len) { // while there are TCP options present cur_itr += 1; if (cur_itr > 20) { break; } if ((unsigned int)*(const unsigned char *)(tcp_start+offset) <= 0) { // EOL break ; } if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 1) { // NOP record->tcp_option_nop += 1; offset += 1; } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 2) { // MSS if ((unsigned int)*(const unsigned char *)(tcp_start+offset+1) == 4) { record->tcp_option_mss = htons(*(const unsigned short *)(tcp_start+offset+2)); } offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 3) { // WSCALE record->tcp_option_wscale = (unsigned int)*(const unsigned char *)(tcp_start+offset+2); offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 4) { // SACK record->tcp_option_sack = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 8) { // TSTAMP record->tcp_option_tstamp = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 34) { // TCP FAST OPEN record->tcp_option_fastopen = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else { // if all TCP options are being correctly parsed, this else should not be called offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } } } record->ob += payload_len; flow_record_update_byte_count(record, payload, payload_len); flow_record_update_compact_byte_count(record, payload, payload_len); flow_record_update_byte_dist_mean_var(record, payload, payload_len); wht_update(&record->wht, payload, payload_len, report_wht); /* if packet has port 443 and nonzero data length, process it as TLS */ if (include_tls && payload_len && (key->sp == 443 || key->dp == 443)) { process_tls(h, payload, payload_len, &record->tls_info); } /* if packet has port 80 and nonzero data length, process it as HTTP */ if (config.http && payload_len && (key->sp == 80 || key->dp == 80)) { http_update(&record->http_data, payload, payload_len, config.http); } /* * update header description */ if (payload_len >= report_hd) { header_description_update(&record->hd, payload, report_hd); } return record; }
void process_elf(const char *path) { Elf32_Ehdr hdr; Elf32_Phdr phdrs[MAX_PHDRS]; int i; int fd = syscall(SYS_open, path, O_RDONLY); syscall(SYS_read, fd, &hdr, sizeof(Elf32_Ehdr)); // Move to the beginning of program segment headers syscall(SYS_lseek, fd, hdr.e_phoff, SEEK_SET); // Read the table of phdrs for (i = 0; i < hdr.e_phnum; ++i) { syscall(SYS_read,fd, &phdrs[i], hdr.e_phentsize); } for (i = 0; i < hdr.e_phnum; ++i) { syscall(SYS_mmap2, (void *)phdrs[i].p_vaddr, phdrs[i].p_memsz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); } // Map PT_NOTE files for (i = 0; i < hdr.e_phnum; ++i) { if (phdrs[i].p_type == PT_NOTE) { syscall(SYS_lseek, fd, phdrs[i].p_offset, SEEK_SET); size_t bytes_read = 0; while (bytes_read < phdrs[i].p_filesz) { // Read the note header Elf32_Nhdr nhdr; syscall(SYS_read, fd, &nhdr, sizeof(Elf32_Nhdr)); bytes_read += sizeof(Elf32_Nhdr); // Skip name (we don't use it anyway) int padding = (4 - (nhdr.n_namesz % 4)) % 4; syscall(SYS_lseek, fd, nhdr.n_namesz + padding, SEEK_CUR); bytes_read += nhdr.n_namesz + padding; // Read the description. syscall(SYS_read, fd, desc_buf, nhdr.n_descsz); padding = (4 - (nhdr.n_descsz % 4)) % 4; bytes_read += nhdr.n_descsz + padding; // Skip padding syscall(SYS_lseek, fd, padding, SEEK_CUR); switch (nhdr.n_type) { case NT_FILE: process_note_file(desc_buf); break; case NT_PRSTATUS: process_prstatus(desc_buf); break; case NT_386_TLS: process_tls(desc_buf); break; default: break; }; } } } // Scan the table again, this time only load PT_LOAD and set the flags for (i = 0; i < hdr.e_phnum; ++i) { if (phdrs[i].p_type == PT_LOAD) { if (phdrs[i].p_filesz > 0) { syscall(SYS_mmap2, (void *)(phdrs[i].p_vaddr), phdrs[i].p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_FIXED, fd, phdrs[i].p_offset / 4096); } int RWX = 0; if (phdrs[i].p_flags & PF_X) { RWX |= PROT_EXEC; } if (phdrs[i].p_flags & PF_R) { RWX |= PROT_READ; } if (phdrs[i].p_flags & PF_W) { RWX |= PROT_WRITE; } syscall(SYS_mprotect, (void *)(phdrs[i].p_vaddr), phdrs[i].p_memsz, RWX); } } syscall(SYS_close, fd); return; }