/modules/auxiliary/scanner/portscan/syn.rb

https://github.com/techpeace/metasploit-framework · Ruby · 126 lines · 92 code · 26 blank · 8 comment · 9 complexity · 576626a7ffafa5765df13a8e9d5764ed MD5 · raw file

  1. ##
  2. # This module requires Metasploit: http://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. require 'msf/core'
  6. class Metasploit3 < Msf::Auxiliary
  7. include Msf::Exploit::Capture
  8. include Msf::Auxiliary::Report
  9. include Msf::Auxiliary::Scanner
  10. def initialize
  11. super(
  12. 'Name' => 'TCP SYN Port Scanner',
  13. 'Description' => %q{
  14. Enumerate open TCP services using a raw SYN scan.
  15. },
  16. 'Author' => 'kris katterjohn',
  17. 'License' => MSF_LICENSE
  18. )
  19. register_options([
  20. OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]),
  21. OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]),
  22. OptInt.new('BATCHSIZE', [true, "The number of hosts to scan per set", 256]),
  23. OptString.new('INTERFACE', [false, 'The name of the interface'])
  24. ], self.class)
  25. deregister_options('FILTER','PCAPFILE')
  26. end
  27. # No IPv6 support yet
  28. def support_ipv6?
  29. false
  30. end
  31. def run_batch_size
  32. datastore['BATCHSIZE'] || 256
  33. end
  34. def run_batch(hosts)
  35. open_pcap
  36. pcap = self.capture
  37. ports = Rex::Socket.portspec_crack(datastore['PORTS'])
  38. if ports.empty?
  39. raise Msf::OptionValidateError.new(['PORTS'])
  40. end
  41. to = (datastore['TIMEOUT'] || 500).to_f / 1000.0
  42. # Spread the load across the hosts
  43. ports.each do |dport|
  44. hosts.each do |dhost|
  45. shost, sport = getsource(dhost)
  46. self.capture.setfilter(getfilter(shost, sport, dhost, dport))
  47. begin
  48. probe = buildprobe(shost, sport, dhost, dport)
  49. capture_sendto(probe, dhost)
  50. reply = probereply(self.capture, to)
  51. next if not reply
  52. if (reply.is_tcp? and reply.tcp_flags.syn == 1 and reply.tcp_flags.ack == 1)
  53. print_status(" TCP OPEN #{dhost}:#{dport}")
  54. report_service(:host => dhost, :port => dport)
  55. end
  56. rescue ::Exception
  57. print_error("Error: #{$!.class} #{$!}")
  58. end
  59. end
  60. end
  61. close_pcap
  62. end
  63. def getfilter(shost, sport, dhost, dport)
  64. # Look for associated SYN/ACKs and RSTs
  65. "tcp and (tcp[13] == 0x12 or (tcp[13] & 0x04) != 0) and " +
  66. "src host #{dhost} and src port #{dport} and " +
  67. "dst host #{shost} and dst port #{sport}"
  68. end
  69. def getsource(dhost)
  70. # srcip, srcport
  71. [ Rex::Socket.source_address(dhost), rand(0xffff - 1025) + 1025 ]
  72. end
  73. def buildprobe(shost, sport, dhost, dport)
  74. p = PacketFu::TCPPacket.new
  75. p.ip_saddr = shost
  76. p.ip_daddr = dhost
  77. p.tcp_sport = sport
  78. p.tcp_flags.ack = 0
  79. p.tcp_flags.syn = 1
  80. p.tcp_dport = dport
  81. p.tcp_win = 3072
  82. p.recalc
  83. p
  84. end
  85. def probereply(pcap, to)
  86. reply = nil
  87. begin
  88. Timeout.timeout(to) do
  89. pcap.each do |r|
  90. pkt = PacketFu::Packet.parse(r)
  91. next unless pkt.is_tcp?
  92. reply = pkt
  93. break
  94. end
  95. end
  96. rescue Timeout::Error
  97. end
  98. return reply
  99. end
  100. end