main
1require 'socket'
2
3class FakeAgent
4 include PacketFu
5 DEFAULT_ENDPOINT='http://localhost:3000'
6 attr_reader :id, :endpoint
7
8 def initialize(endpoint = DEFAULT_ENDPOINT)
9 @endpoint = endpoint
10 end
11
12 def register
13 response = Typhoeus.post(registration_url, body: { agent: { hostname: hostname } })
14 json = JSON.parse(response.body)
15 @id = json["id"]
16 end
17
18 def watch(directory)
19 listener = Listen.to(directory, debug: true) do |modified, added, removed|
20 publish_event(:modified, modified)
21 publish_event(:added, added)
22 publish_event(:removed, removed)
23 (modified + added + removed).flatten.each do |file|
24 scan_file(file)
25 end
26 end
27
28 listener.start
29 sleep
30 end
31
32 def scan(directory)
33 Dir["**/**/*"].each do |file|
34 scan_file(file)
35 end
36 end
37
38 def scan_file(file)
39 return unless File.file?(file)
40
41 case disposition_for(file)
42 when "malicious"
43 publish_event(:quarantined, [file])
44 when "unknown"
45 puts "file is unknown"
46 end
47 rescue StandardError => error
48 log_error(error)
49 end
50
51 def sniff(interface)
52 capture = Capture.new(iface: interface, start: true)
53 capture.stream.each do |p|
54 packet = Packet.parse(p)
55 if packet.is_ip?
56 yield packet if block_given?
57 end
58 end
59 end
60
61 def packet_capture(interface)
62 sniff(interface) do |packet|
63 if packet.ip_saddr == Utils.ifconfig(interface)[:ip_saddr]
64 else
65 packet_info = [packet.ip_saddr, packet.ip_daddr, packet.size, packet.proto.last]
66 #puts packet.dissect
67 puts "%-15s -> %-15s %-4d %s" % packet_info
68 end
69 end
70 end
71
72 private
73
74 def publish_event(event, files)
75 files.each do |file|
76 body = {
77 event: {
78 agent_id: id,
79 type: event,
80 data: {
81 fingerprint: fingerprint_for(file),
82 path: file,
83 hostname: hostname,
84 ip_addresses: ip_addresses,
85 }
86 }
87 }
88 Typhoeus.post(event_url, body: body)
89 end
90 rescue StandardError => error
91 log_error(error)
92 end
93
94 def fingerprint_for(file)
95 return nil unless File.exist?(file)
96 result = `shasum -a 256 #{file}`
97 sha, * = result.split(' ')
98 sha
99 end
100
101 def hostname
102 @hostname ||= "#{Socket.gethostname}-#{Faker::Internet.slug}"
103 end
104
105 def ip_addresses
106 @ipaddresses ||= Socket.ip_address_list.find_all { |x| x.ipv4? }.map { |x| x.ip_address }
107 end
108
109 def disposition_for(file)
110 fingerprint = fingerprint_for(file)
111 body = {
112 data: {
113 fingerprint: fingerprint,
114 path: File.expand_path(file)
115 }
116 }
117 JSON.parse(Typhoeus.get(file_query_url(fingerprint), body: body).body)["state"]
118 end
119
120 def file_query_url(fingerprint)
121 "#{endpoint}/api/agents/#{id}/files/#{fingerprint}"
122 end
123
124 def event_url
125 "#{endpoint}/api/agents/#{id}/events/"
126 end
127
128 def registration_url
129 "#{endpoint}/api/agents"
130 end
131
132 def log_error(error)
133 puts "#{error.message} #{error.backtrace.join(' ')}"
134 end
135end