Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 # -*- coding: utf-8 -*- | |
2 """File containing a Windows Registry plugin to parse the Amcache Hive.""" | |
3 | |
4 from __future__ import unicode_literals | |
5 import pyregf | |
6 | |
7 from dfdatetime import filetime | |
8 from dfdatetime import posix_time | |
9 from plaso.containers import events | |
10 from plaso.containers import time_events | |
11 from plaso.lib import definitions | |
12 from plaso.parsers import interface | |
13 from plaso.parsers import manager | |
14 | |
15 __author__ = 'Ramses de Beer, rbdebeer@google.com' | |
16 | |
17 class AmcacheEventData(events.EventData): | |
18 """Amcache event data. | |
19 | |
20 Attributes: | |
21 full_path (str): full path of file | |
22 sha1 (str): sha1 of file | |
23 productname (str): product name file belongs to | |
24 companyname (str): company name that created product file belogs to | |
25 fileversion (str): version of file | |
26 languagecode (int): language code of file | |
27 filesize (int): size of file in bytes | |
28 filedescription (str): description of file | |
29 linkerts (int): unix timestamp when file was linked | |
30 lastmodifiedts (int): filetime timestamp of last modified datetime of file | |
31 createdtd (int): filetime timestamp of created datetime of file | |
32 programid (str): GUID of entry under Root/Program key file belongs to | |
33 """ | |
34 | |
35 DATA_TYPE = 'windows:registry:amcache' | |
36 | |
37 def __init__(self): | |
38 """Initializes event data.""" | |
39 super(AmcacheEventData, self).__init__(data_type=self.DATA_TYPE) | |
40 self.full_path = None | |
41 self.sha1 = None | |
42 self.productname = None | |
43 self.companyname = None | |
44 self.fileversion = None | |
45 self.languagecode = None | |
46 self.filesize = None | |
47 self.filedescription = None | |
48 self.linkerts = None | |
49 self.lastmodifiedts = None | |
50 self.createdts = None | |
51 self.programid = None | |
52 | |
53 class AmcacheProgramEventData(events.EventData): | |
54 """Amcache programs event data. | |
55 | |
56 Attributes: | |
57 name (str): name of installed program | |
58 version (str): version of program | |
59 publisher (str): publisher of program | |
60 languagecode (int): languagecode of program | |
61 entrytype (str): type of entry (usually AddRemoveProgram) | |
62 uninstallkey (str): unicode string of uninstall registry key for program | |
63 filepath (str): file path of installed program | |
64 productcode (str): product code of program | |
65 packagecode (str): package code of program | |
66 msiproductcode (str): MSI product code of program | |
67 msipackagecode (str): MSI package code of program | |
68 files (str): list of files belonging to program | |
69 """ | |
70 | |
71 DATA_TYPE = 'windows:registry:amcache:programs' | |
72 | |
73 def __init__(self): | |
74 """Initializes event data.""" | |
75 super(AmcacheProgramEventData, self).__init__(data_type=self.DATA_TYPE) | |
76 self.name = None | |
77 self.version = None | |
78 self.publisher = None | |
79 self.languagecode = None | |
80 self.entrytype = None | |
81 self.uninstallkey = None | |
82 self.filepaths = None | |
83 self.productcode = None | |
84 self.packagecode = None | |
85 self.msiproductcode = None | |
86 self.msipackagecode = None | |
87 self.files = None | |
88 | |
89 class AmcacheParser(interface.FileObjectParser): | |
90 """Amcache Registry plugin for recently run programs.""" | |
91 | |
92 NAME = 'amcache' | |
93 DESCRIPTION = 'Parser for Amcache Registry entries.' | |
94 | |
95 URLS = [ | |
96 ('http://www.swiftforensics.com/2013/12/' | |
97 'amcachehve-in-windows-8-goldmine-for.html')] | |
98 | |
99 _AMCACHE_SHA1 = "101" | |
100 _AMCACHE_DATETIME = "17" | |
101 _AMCACHE_FULL_PATH = "15" | |
102 _AMCACHE_ROOT_FILE_KEY = "Root\\File" | |
103 _AMCACHE_ROOT_PROGRAM_KEY = "Root\\Programs" | |
104 _AMCACHE_PRODUCTNAME = "0" | |
105 _AMCACHE_COMPANYNAME = "1" | |
106 _AMCACHE_FILEVERSION = "5" | |
107 _AMCACHE_LANGUAGECODE = "3" | |
108 _AMCACHE_FILESIZE = "6" | |
109 _AMCACHE_FILEDESCRIPTION = "c" | |
110 _AMCACHE_LINKERTS = "f" | |
111 _AMCACHE_LASTMODIFIEDTS = "11" | |
112 _AMCACHE_CREATEDTS = "12" | |
113 _AMCACHE_PROGRAMID = "100" | |
114 | |
115 _AMCACHE_P_INSTALLDATE = "a" | |
116 _AMCACHE_P_NAME = "0" | |
117 _AMCACHE_P_VERSION = "1" | |
118 _AMCACHE_P_PUBLISHER = "2" | |
119 _AMCACHE_P_LANGUAGECODE = "3" | |
120 _AMCACHE_P_ENTRYTYPE = "6" | |
121 _AMCACHE_P_UNINSTALLKEY = "7" | |
122 _AMCACHE_P_FILEPATHS = "d" | |
123 _AMCACHE_P_PRODUCTCODE = "f" | |
124 _AMCACHE_P_PACKAGECODE = "10" | |
125 _AMCACHE_P_MSIPRODUCTCODE = "11" | |
126 _AMCACHE_P_MSIPACKAGECODE = "12" | |
127 _AMCACHE_P_FILES = "Files" | |
128 | |
129 #TODO Add GetFormatSpecification when issues are fixed with adding | |
130 # multiple parsers for the same file format (in this case regf files) | |
131 # AddNewSignature -> | |
132 # b'\x41\x00\x6d\x00\x63\x00\x61\x00\x63\x00\x68\x00\x65', offset=88 | |
133 | |
134 def ParseFileObject(self, parser_mediator, file_object, **kwargs): | |
135 """Parses an Amcache.hve file for events. | |
136 | |
137 Args: | |
138 parser_mediator (ParserMediator): mediates interactions between parsers | |
139 and other components, such as storage and dfvfs. | |
140 file_object (dfvfs.FileIO): file-like object. | |
141 """ | |
142 regf_file = pyregf.file() # pylint: disable=no-member | |
143 try: | |
144 regf_file.open_file_object(file_object) | |
145 except IOError: | |
146 # The error is currently ignored -> see TODO above related to the | |
147 # fixing of handling multiple parsers for the same file format. | |
148 return | |
149 | |
150 root_key = regf_file.get_root_key() | |
151 if root_key is None: | |
152 regf_file.close() | |
153 return | |
154 | |
155 root_file_key = root_key.get_sub_key_by_path(self._AMCACHE_ROOT_FILE_KEY) | |
156 if root_file_key is None: | |
157 regf_file.close() | |
158 return | |
159 | |
160 for volume_key in root_file_key.sub_keys: | |
161 for am_entry in volume_key.sub_keys: | |
162 self._ProcessAMCacheFileKey(am_entry, parser_mediator) | |
163 | |
164 root_program_key = root_key.get_sub_key_by_path( | |
165 self._AMCACHE_ROOT_PROGRAM_KEY) | |
166 if root_program_key is None: | |
167 regf_file.close() | |
168 return | |
169 | |
170 for am_entry in root_program_key.sub_keys: | |
171 self._ProcessAMCacheProgramKey(am_entry, parser_mediator) | |
172 | |
173 regf_file.close() | |
174 | |
175 def _ProcessAMCacheProgramKey(self, am_entry, parser_mediator): | |
onager
2017/08/24 10:41:31
+docstring
rbdebeer
2017/08/24 11:50:49
Done.
| |
176 amcache_datetime = am_entry.get_value_by_name( | |
177 self._AMCACHE_P_INSTALLDATE).get_data_as_integer() | |
178 pevent_data = AmcacheProgramEventData() | |
onager
2017/08/24 10:41:30
just event_data
rbdebeer
2017/08/24 11:50:49
Done.
| |
179 name = am_entry.get_value_by_name(self._AMCACHE_P_NAME) | |
180 if name: | |
181 pevent_data.name = name.get_data_as_string() | |
182 version = am_entry.get_value_by_name(self._AMCACHE_P_VERSION) | |
onager
2017/08/24 10:41:30
+white line before "version", to make this more re
rbdebeer
2017/08/24 11:50:49
Done.
| |
183 if version: | |
184 pevent_data.version = version.get_data_as_string() | |
185 publisher = am_entry.get_value_by_name(self._AMCACHE_P_PUBLISHER) | |
186 if publisher: | |
187 pevent_data.publisher = publisher.get_data_as_string() | |
188 languagecode = am_entry.get_value_by_name(self._AMCACHE_P_LANGUAGECODE) | |
189 if languagecode: | |
190 pevent_data.languagecode = languagecode.get_data_as_string() | |
191 entrytype = am_entry.get_value_by_name(self._AMCACHE_P_ENTRYTYPE) | |
192 if entrytype: | |
193 pevent_data.entrytype = entrytype.get_data_as_string() | |
194 uninstallkey = am_entry.get_value_by_name(self._AMCACHE_P_UNINSTALLKEY) | |
195 if uninstallkey: | |
196 pevent_data.uninstallkey = uninstallkey.get_data().decode('utf-16-LE') | |
197 filepaths = am_entry.get_value_by_name(self._AMCACHE_P_FILEPATHS) | |
198 if filepaths: | |
199 pevent_data.filepaths = filepaths.get_data().decode('utf-16-LE') | |
200 productcode = am_entry.get_value_by_name(self._AMCACHE_P_PRODUCTCODE) | |
201 if productcode: | |
202 pevent_data.productcode = productcode.get_data_as_string() | |
203 packagecode = am_entry.get_value_by_name(self._AMCACHE_P_PACKAGECODE) | |
204 if packagecode: | |
205 pevent_data.packagecode = packagecode.get_data_as_string() | |
206 msiproductcode = ( | |
onager
2017/08/24 10:41:31
Line break list so:
msiproductcode = am_entry.get
rbdebeer
2017/08/24 11:50:49
Done.
| |
207 am_entry.get_value_by_name(self._AMCACHE_P_MSIPRODUCTCODE) | |
208 ) | |
209 if msiproductcode: | |
210 pevent_data.msiproductcode = ( | |
211 msiproductcode.get_data().decode('utf-16-LE') | |
onager
2017/08/24 10:41:31
This fits on one line, but please do the get_data(
rbdebeer
2017/08/24 11:50:49
Done.
| |
212 ) | |
213 msipackagecode = ( | |
214 am_entry.get_value_by_name(self._AMCACHE_P_MSIPACKAGECODE) | |
215 ) | |
216 if msipackagecode: | |
217 pevent_data.msipackagecode = ( | |
218 msipackagecode.get_data().decode('utf-16-LE') | |
219 ) | |
220 files = am_entry.get_value_by_name(self._AMCACHE_P_FILES) | |
221 if files: | |
222 pevent_data.files = files.get_data().decode('utf-16-LE') | |
223 event = time_events.DateTimeValuesEvent( | |
224 posix_time.PosixTime(amcache_datetime), | |
225 definitions.TIME_DESCRIPTION_INSTALLATION) | |
226 parser_mediator.ProduceEventWithEventData(event, pevent_data) | |
227 | |
228 def _ProcessAMCacheFileKey(self, am_entry, parser_mediator): | |
onager
2017/08/24 10:41:30
+docstring
rbdebeer
2017/08/24 11:50:49
Done.
| |
229 amcache_datetime = am_entry.get_value_by_name( | |
230 self._AMCACHE_DATETIME).get_data_as_integer() | |
231 event_data = AmcacheEventData() | |
232 event_data.full_path = am_entry.get_value_by_name( | |
233 self._AMCACHE_FULL_PATH).get_data_as_string() | |
234 # Strip off the 4 leading zero's from the sha1 hash. | |
235 event_data.sha1 = am_entry.get_value_by_name( | |
236 self._AMCACHE_SHA1).get_data_as_string()[4:] | |
237 productname = am_entry.get_value_by_name(self._AMCACHE_PRODUCTNAME) | |
238 if productname: | |
239 event_data.productname = productname.get_data_as_string() | |
240 companyname = am_entry.get_value_by_name(self._AMCACHE_COMPANYNAME) | |
241 if companyname: | |
242 event_data.companyname = companyname.get_data_as_string() | |
243 fileversion = am_entry.get_value_by_name(self._AMCACHE_FILEVERSION) | |
244 if fileversion: | |
245 event_data.fileversion = fileversion.get_data_as_string() | |
246 languagecode = am_entry.get_value_by_name(self._AMCACHE_LANGUAGECODE) | |
247 if languagecode: | |
248 event_data.languagecode = languagecode.get_data_as_integer() | |
249 filesize = am_entry.get_value_by_name(self._AMCACHE_FILESIZE) | |
250 if filesize: | |
251 event_data.filesize = filesize.get_data_as_integer() | |
252 filedescription = ( | |
253 am_entry.get_value_by_name(self._AMCACHE_FILEDESCRIPTION) | |
254 ) | |
255 if filedescription: | |
256 event_data.filedescription = filedescription.get_data_as_string() | |
257 linkerts = am_entry.get_value_by_name(self._AMCACHE_LINKERTS) | |
258 if linkerts: | |
259 event_data.linkerts = linkerts.get_data_as_integer() | |
260 lastmodifiedts = ( | |
261 am_entry.get_value_by_name(self._AMCACHE_LASTMODIFIEDTS) | |
262 ) | |
263 if lastmodifiedts: | |
264 event_data.lastmodifiedts = lastmodifiedts.get_data_as_integer() | |
265 createdts = am_entry.get_value_by_name(self._AMCACHE_CREATEDTS) | |
266 if createdts: | |
267 event_data.createdts = createdts.get_data_as_integer() | |
268 programid = am_entry.get_value_by_name(self._AMCACHE_PROGRAMID) | |
269 if programid: | |
270 event_data.programid = programid.get_data_as_string() | |
271 event = time_events.DateTimeValuesEvent( | |
272 filetime.Filetime(amcache_datetime), | |
273 definitions.TIME_DESCRIPTION_LAST_RUN) | |
274 parser_mediator.ProduceEventWithEventData(event, event_data) | |
275 if event_data.createdts is not None: | |
276 event = time_events.DateTimeValuesEvent( | |
277 filetime.Filetime(event_data.createdts), | |
278 definitions.TIME_DESCRIPTION_CREATION) | |
279 parser_mediator.ProduceEventWithEventData(event, event_data) | |
280 if event_data.lastmodifiedts is not None: | |
281 event = time_events.DateTimeValuesEvent( | |
282 filetime.Filetime(event_data.lastmodifiedts), | |
283 definitions.TIME_DESCRIPTION_MODIFICATION) | |
284 parser_mediator.ProduceEventWithEventData(event, event_data) | |
285 if event_data.linkerts is not None: | |
286 event = time_events.DateTimeValuesEvent( | |
287 posix_time.PosixTime(event_data.linkerts), | |
288 definitions.TIME_DESCRIPTION_CHANGE) | |
289 parser_mediator.ProduceEventWithEventData(event, event_data) | |
290 | |
291 manager.ParsersManager.RegisterParser(AmcacheParser) | |
OLD | NEW |