module_tcp_synscan.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * ZMap Copyright 2013 Regents of the University of Michigan
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy
  6. * of the License at http://www.apache.org/licenses/LICENSE-2.0
  7. */
  8. // probe module for performing TCP SYN scans
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <stdint.h>
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <assert.h>
  15. #include "../../lib/includes.h"
  16. #include "../fieldset.h"
  17. #include "probe_modules.h"
  18. #include "packet.h"
  19. probe_module_t module_tcp_synscan;
  20. static uint32_t num_ports;
  21. int synscan_global_initialize(struct state_conf *state)
  22. {
  23. num_ports = state->source_port_last - state->source_port_first + 1;
  24. return EXIT_SUCCESS;
  25. }
  26. int synscan_init_perthread(void* buf, macaddr_t *src,
  27. macaddr_t *gw, port_h_t dst_port,
  28. __attribute__((unused)) void **arg_ptr)
  29. {
  30. memset(buf, 0, MAX_PACKET_SIZE);
  31. struct ether_header *eth_header = (struct ether_header *) buf;
  32. make_eth_header(eth_header, src, gw);
  33. struct ip *ip_header = (struct ip*)(&eth_header[1]);
  34. uint16_t len = htons(sizeof(struct ip) + sizeof(struct tcphdr));
  35. make_ip_header(ip_header, IPPROTO_TCP, len);
  36. struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]);
  37. make_tcp_header(tcp_header, dst_port);
  38. return EXIT_SUCCESS;
  39. }
  40. int synscan_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
  41. uint32_t *validation, int probe_num, __attribute__((unused)) void *arg)
  42. {
  43. struct ether_header *eth_header = (struct ether_header *)buf;
  44. struct ip *ip_header = (struct ip*)(&eth_header[1]);
  45. struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]);
  46. uint32_t tcp_seq = validation[0];
  47. ip_header->ip_src.s_addr = src_ip;
  48. ip_header->ip_dst.s_addr = dst_ip;
  49. tcp_header->th_sport = htons(get_src_port(num_ports,
  50. probe_num, validation));
  51. tcp_header->th_seq = tcp_seq;
  52. tcp_header->th_sum = 0;
  53. tcp_header->th_sum = tcp_checksum(sizeof(struct tcphdr),
  54. ip_header->ip_src.s_addr, ip_header->ip_dst.s_addr, tcp_header);
  55. ip_header->ip_sum = 0;
  56. ip_header->ip_sum = zmap_ip_checksum((unsigned short *) ip_header);
  57. return EXIT_SUCCESS;
  58. }
  59. void synscan_print_packet(FILE *fp, void* packet)
  60. {
  61. struct ether_header *ethh = (struct ether_header *) packet;
  62. struct ip *iph = (struct ip *) &ethh[1];
  63. struct tcphdr *tcph = (struct tcphdr *) &iph[1];
  64. fprintf(fp, "tcp { source: %u | dest: %u | seq: %u | checksum: %#04X }\n",
  65. ntohs(tcph->th_sport),
  66. ntohs(tcph->th_dport),
  67. ntohl(tcph->th_seq),
  68. ntohs(tcph->th_sum));
  69. fprintf_ip_header(fp, iph);
  70. fprintf_eth_header(fp, ethh);
  71. fprintf(fp, "------------------------------------------------------\n");
  72. }
  73. int synscan_validate_packet(const struct ip *ip_hdr, uint32_t len,
  74. __attribute__((unused))uint32_t *src_ip,
  75. uint32_t *validation)
  76. {
  77. if (ip_hdr->ip_p != IPPROTO_TCP) {
  78. return 0;
  79. }
  80. if ((4*ip_hdr->ip_hl + sizeof(struct tcphdr)) > len) {
  81. // buffer not large enough to contain expected tcp header
  82. return 0;
  83. }
  84. struct tcphdr *tcp = (struct tcphdr*)((char *) ip_hdr + 4*ip_hdr->ip_hl);
  85. uint16_t sport = tcp->th_sport;
  86. uint16_t dport = tcp->th_dport;
  87. // validate source port
  88. if (ntohs(sport) != zconf.target_port) {
  89. return 0;
  90. }
  91. // validate destination port
  92. if (!check_dst_port(ntohs(dport), num_ports, validation)) {
  93. return 0;
  94. }
  95. // validate tcp acknowledgement number
  96. if (htonl(tcp->th_ack) != htonl(validation[0])+1) {
  97. return 0;
  98. }
  99. return 1;
  100. }
  101. void synscan_process_packet(const u_char *packet,
  102. __attribute__((unused)) uint32_t len, fieldset_t *fs)
  103. {
  104. struct ip *ip_hdr = (struct ip *)&packet[sizeof(struct ether_header)];
  105. struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr
  106. + 4*ip_hdr->ip_hl);
  107. fs_add_uint64(fs, "sport", (uint64_t) ntohs(tcp->th_sport));
  108. fs_add_uint64(fs, "dport", (uint64_t) ntohs(tcp->th_dport));
  109. fs_add_uint64(fs, "seqnum", (uint64_t) ntohl(tcp->th_seq));
  110. fs_add_uint64(fs, "acknum", (uint64_t) ntohl(tcp->th_ack));
  111. fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->th_win));
  112. if (tcp->th_flags & TH_RST) { // RST packet
  113. fs_add_string(fs, "classification", (char*) "rst", 0);
  114. fs_add_uint64(fs, "success", 0);
  115. } else { // SYNACK packet
  116. fs_add_string(fs, "classification", (char*) "synack", 0);
  117. fs_add_uint64(fs, "success", 1);
  118. }
  119. }
  120. static fielddef_t fields[] = {
  121. {.name = "sport", .type = "int", .desc = "TCP source port"},
  122. {.name = "dport", .type = "int", .desc = "TCP destination port"},
  123. {.name = "seqnum", .type = "int", .desc = "TCP sequence number"},
  124. {.name = "acknum", .type = "int", .desc = "TCP acknowledgement number"},
  125. {.name = "window", .type = "int", .desc = "TCP window"},
  126. {.name = "classification", .type="string", .desc = "packet classification"},
  127. {.name = "success", .type="int", .desc = "is response considered success"}
  128. };
  129. probe_module_t module_tcp_synscan = {
  130. .name = "tcp_synscan",
  131. .packet_length = 54,
  132. .pcap_filter = "tcp && tcp[13] & 4 != 0 || tcp[13] == 18",
  133. .pcap_snaplen = 96,
  134. .port_args = 1,
  135. .global_initialize = &synscan_global_initialize,
  136. .thread_initialize = &synscan_init_perthread,
  137. .make_packet = &synscan_make_packet,
  138. .print_packet = &synscan_print_packet,
  139. .process_packet = &synscan_process_packet,
  140. .validate_packet = &synscan_validate_packet,
  141. .close = NULL,
  142. .helptext = "Probe module that sends a TCP SYN packet to a specific "
  143. "port. Possible classifications are: synack and rst. A "
  144. "SYN-ACK packet is considered a success and a reset packet "
  145. "is considered a failed response.",
  146. .fields = fields,
  147. .numfields = 7};