summaryrefslogtreecommitdiff
path: root/lib/fake_agent.rb
blob: ff618ac609d25f4b3a0f13fb09128fc27eef6dbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
100
101
102
103
104
105
106
107
require 'socket'

class FakeAgent
  include PacketFu
  attr_reader :id, :endpoint

  def initialize(id, endpoint)
    @id = id
    @endpoint = endpoint
  end

  def watch(directory)
    listener = Listen.to(directory, debug: true) do |modified, added, removed|
      publish_event(:modified, modified)
      publish_event(:added, added)
      publish_event(:removed, removed)
      (modified + added + removed).flatten.each do |file|
        scan_file(file)
      end
    end

    listener.start
    sleep
  end

  def scan(directory)
    Dir["Rakefile"].each do |file|
      scan_file(file)
    end
  end

  def scan_file(file)
    return unless File.file?(file)

    case disposition_for(file)
    when "malicious"
      publish_event(:quarantined, [file])
    when "unknown"
      puts "file is unknown"
    end
  end

  def sniff(interface)
    capture = Capture.new(iface: interface, start: true)
    capture.stream.each do |p|
      packet = Packet.parse(p)
      if packet.is_ip?
        next if packet.ip_saddr == Utils.ifconfig(interface)[:ip_saddr]
        packet_info = [packet.ip_saddr, packet.ip_daddr, packet.size, packet.proto.last]
        puts "%-15s -> %-15s %-4d %s" % packet_info
      end
    end
  end

  private

  def publish_event(event, files)
    files.each do |file|
      body = {
        event: {
          agent_id: id,
          name: event,
          data: {
            fingerprint: fingerprint_for(file),
            path: file,
            hostname: Socket.gethostname,
            ip_addresses: ip_addresses,
          }
        }
      }
      Typhoeus.post(event_url, body: body)
    end
  rescue => e
    puts "#{e.message} #{e.backtrace.join(' ')}"
  end

  def fingerprint_for(file)
    return nil unless File.exist?(file)
    result = `shasum -a 256 #{file}`
    sha, * = result.split(' ')
    sha
  end

  def ip_addresses
    Socket.ip_address_list.find_all { |x| x.ipv4? }.map { |x| x.ip_address }
  end

  def disposition_for(file)
    fingerprint = fingerprint_for(file)
    body = {
      name: 'lookup',
      data: {
        fingerprint: fingerprint,
        path: File.expand_path(file)
      }
    }
    JSON.parse(Typhoeus.get(file_query_url(fingerprint), body: body).body)["state"]
  end

  def file_query_url(fingerprint)
    "#{endpoint}/agents/#{id}/files/#{fingerprint}"
  end

  def event_url
    "#{endpoint}/agents/#{id}/events/"
  end
end