Class: NetMap::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/netmap/scanner.rb

Constant Summary collapse

TIMING_TEMPLATES =
{
  0 => { threads: 1,   timeout: 10.0 }, # Paranoid
  1 => { threads: 5,   timeout: 5.0 },  # Sneaky
  2 => { threads: 10,  timeout: 2.0 },  # Polite
  3 => { threads: 50,  timeout: 1.0 },  # Normal
  4 => { threads: 200, timeout: 0.8 },  # Aggressive
  5 => { threads: 400, timeout: 0.5 }   # Insane (Capped at 400 threads/0.5s)
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(targets, ports, threads: nil, timeout: nil, timing: 3, discovery: true, udp: false, os_detect: false, noping: false) ⇒ Scanner

Returns a new instance of Scanner.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/netmap/scanner.rb', line 18

def initialize(targets, ports, threads: nil, timeout: nil, timing: 3, discovery: true, udp: false, os_detect: false, noping: false)
  @timing_template = TIMING_TEMPLATES[timing] || TIMING_TEMPLATES[3]
  @targets = parse_targets(targets)
  @ports = parse_ports(ports)
  @threads = threads || @timing_template[:threads]
  @timeout = timeout || @timing_template[:timeout]
  @discovery_mode = discovery
  @udp_mode = udp
  @os_detect_mode = os_detect
  @noping_mode = noping
  @active_hosts = []
  @results = []
  
  # Inisialisasi Script Engine
  require_relative 'script_engine'
  script_dir = File.join(File.expand_path('../../../', __FILE__), 'scripts')
  @script_engine = ScriptEngine.new(script_dir)
end

Instance Attribute Details

#active_hostsObject (readonly)

Returns the value of attribute active_hosts.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def active_hosts
  @active_hosts
end

#discovery_modeObject (readonly)

Returns the value of attribute discovery_mode.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def discovery_mode
  @discovery_mode
end

#portsObject (readonly)

Returns the value of attribute ports.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def ports
  @ports
end

#targetsObject (readonly)

Returns the value of attribute targets.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def targets
  @targets
end

#threadsObject (readonly)

Returns the value of attribute threads.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def threads
  @threads
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def timeout
  @timeout
end

#timing_templateObject (readonly)

Returns the value of attribute timing_template.



7
8
9
# File 'lib/netmap/scanner.rb', line 7

def timing_template
  @timing_template
end

Instance Method Details

#runObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/netmap/scanner.rb', line 37

def run
  @arp_table = get_arp_table # Pastikan tabel ARP selalu terisi
  
  if @noping_mode
    @active_hosts = @targets
    puts "Mode -Pn aktif: Melewati Host Discovery, menganggap host ALIVE.".yellow
  elsif @discovery_mode
    puts "Melakukan Host Discovery (mencari host aktif)...".yellow
    discover_hosts
    puts "Host aktif ditemukan: #{@active_hosts.size}".green
    return [] if @ports.empty?
  else
    @active_hosts = @targets
  end

  return [] if @active_hosts.empty?

  scan_type = @udp_mode ? "UDP" : "TCP"
  puts "Memulai pemindaian port #{scan_type} pada #{@active_hosts.size} host (Async Mode)...".yellow
  
  tasks_list = []
  @active_hosts.each { |ip| @ports.each { |port| tasks_list << { ip: ip, port: port } } }
  total_tasks = tasks_list.size
  completed = 0
  
  require 'async'
  require 'async/barrier'
  require 'async/semaphore'

  Async do |task|
    barrier = Async::Barrier.new
    semaphore = Async::Semaphore.new(@threads, parent: barrier)
    
    tasks_list.each do |t|
      semaphore.async do
        if @udp_mode
          scan_udp_port(t[:ip], t[:port])
        else
          scan_port(t[:ip], t[:port])
        end
        completed += 1
        print_progress(completed, total_tasks) if total_tasks > 10
      end
    end
    barrier.wait
  end

  puts "\n" if total_tasks > 10
  
  # Refresh tabel ARP (Setelah koneksi dibuat, sistem operasi mengupdate cache ARP)
  @arp_table = get_arp_table

  # Tambahkan info MAC dan Vendor ke setiap hasil
  @results.each do |r|
    arp_info = @arp_table[r[:ip]]
    if arp_info
      r[:mac] = arp_info[:mac]
      r[:vendor] = get_vendor_by_mac(r[:mac])
    end
  end
  
  @results.sort_by { |r| [r[:ip], r[:port]] }
end