1
2
3
4
5 import os
6 from datetime import datetime
7
8 try:
9 import magic
10 HAVE_MAGIC = True
11 except ImportError:
12 HAVE_MAGIC = False
13
14 try:
15 import pefile
16 import peutils
17 HAVE_PEFILE = True
18 except ImportError:
19 HAVE_PEFILE = False
20
21 from lib.cuckoo.common.abstracts import Processing
22 from lib.cuckoo.common.constants import CUCKOO_ROOT
23 from lib.cuckoo.common.objects import File
24 from lib.cuckoo.common.utils import convert_to_printable
25
26
27
28
30 """PE analysis."""
31
33 """@param file_path: file path."""
34 self.file_path = file_path
35 self.pe = None
36
38 """Gets filetype, uses libmagic if available.
39 @param data: data to be analyzed.
40 @return: file type or None.
41 """
42 if not HAVE_MAGIC:
43 return None
44
45 try:
46 ms = magic.open(magic.MAGIC_NONE)
47 ms.load()
48 file_type = ms.buffer(data)
49 except:
50 try:
51 file_type = magic.from_buffer(data)
52 except Exception:
53 return None
54 finally:
55 try:
56 ms.close()
57 except:
58 pass
59
60 return file_type
61
63 """Gets PEID signatures.
64 @return: matched signatures or None.
65 """
66 if not self.pe:
67 return None
68
69 try:
70 sig_path = os.path.join(CUCKOO_ROOT, "data",
71 "peutils", "UserDB.TXT")
72 signatures = peutils.SignatureDatabase(sig_path)
73 return signatures.match(self.pe, ep_only=True)
74 except:
75 return None
76
78 """Gets imported symbols.
79 @return: imported symbols dict or None.
80 """
81 if not self.pe:
82 return None
83
84 imports = []
85
86 if hasattr(self.pe, "DIRECTORY_ENTRY_IMPORT"):
87 for entry in self.pe.DIRECTORY_ENTRY_IMPORT:
88 try:
89 symbols = []
90 for imported_symbol in entry.imports:
91 symbol = {}
92 symbol["address"] = hex(imported_symbol.address)
93 symbol["name"] = imported_symbol.name
94 symbols.append(symbol)
95
96 imports_section = {}
97 imports_section["dll"] = convert_to_printable(entry.dll)
98 imports_section["imports"] = symbols
99 imports.append(imports_section)
100 except:
101 continue
102
103 return imports
104
106 """Gets exported symbols.
107 @return: exported symbols dict or None.
108 """
109 if not self.pe:
110 return None
111
112 exports = []
113
114 if hasattr(self.pe, "DIRECTORY_ENTRY_EXPORT"):
115 for exported_symbol in self.pe.DIRECTORY_ENTRY_EXPORT.symbols:
116 symbol = {}
117 symbol["address"] = hex(self.pe.OPTIONAL_HEADER.ImageBase +
118 exported_symbol.address)
119 symbol["name"] = exported_symbol.name
120 symbol["ordinal"] = exported_symbol.ordinal
121 exports.append(symbol)
122
123 return exports
124
126 """Gets sections.
127 @return: sections dict or None.
128 """
129 if not self.pe:
130 return None
131
132 sections = []
133
134 for entry in self.pe.sections:
135 try:
136 section = {}
137 section["name"] = convert_to_printable(entry.Name.strip("\x00"))
138 section["virtual_address"] = "0x{0:08x}".format(entry.VirtualAddress)
139 section["virtual_size"] = "0x{0:08x}".format(entry.Misc_VirtualSize)
140 section["size_of_data"] = "0x{0:08x}".format(entry.SizeOfRawData)
141 section["entropy"] = entry.get_entropy()
142 sections.append(section)
143 except:
144 continue
145
146 return sections
147
149 """Get resources.
150 @return: resources dict or None.
151 """
152 if not self.pe:
153 return None
154
155 resources = []
156
157 if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"):
158 for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries:
159 try:
160 resource = {}
161
162 if resource_type.name is not None:
163 name = str(resource_type.name)
164 else:
165 name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id))
166
167 if hasattr(resource_type, "directory"):
168 for resource_id in resource_type.directory.entries:
169 if hasattr(resource_id, "directory"):
170 for resource_lang in resource_id.directory.entries:
171 data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size)
172 filetype = self._get_filetype(data)
173 language = pefile.LANG.get(resource_lang.data.lang, None)
174 sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang)
175
176 resource["name"] = name
177 resource["offset"] = "0x{0:08x}".format(resource_lang.data.struct.OffsetToData)
178 resource["size"] = "0x{0:08x}".format(resource_lang.data.struct.Size)
179 resource["filetype"] = filetype
180 resource["language"] = language
181 resource["sublanguage"] = sublanguage
182 resources.append(resource)
183 except:
184 continue
185
186 return resources
187
189 """Get version info.
190 @return: info dict or None.
191 """
192 if not self.pe:
193 return None
194
195 infos = []
196 if hasattr(self.pe, "VS_VERSIONINFO"):
197 if hasattr(self.pe, "FileInfo"):
198 for entry in self.pe.FileInfo:
199 try:
200 if hasattr(entry, "StringTable"):
201 for st_entry in entry.StringTable:
202 for str_entry in st_entry.entries.items():
203 entry = {}
204 entry["name"] = convert_to_printable(str_entry[0])
205 entry["value"] = convert_to_printable(str_entry[1])
206 infos.append(entry)
207 elif hasattr(entry, "Var"):
208 for var_entry in entry.Var:
209 if hasattr(var_entry, "entry"):
210 entry = {}
211 entry["name"] = convert_to_printable(var_entry.entry.keys()[0])
212 entry["value"] = convert_to_printable(var_entry.entry.values()[0])
213 infos.append(entry)
214 except:
215 continue
216
217 return infos
218
219
221 """Gets imphash.
222 @return: imphash string or None.
223 """
224 if not self.pe:
225 return None
226
227 try:
228 return self.pe.get_imphash()
229 except AttributeError:
230 return None
231
233 """Get compilation timestamp.
234 @return: timestamp or None.
235 """
236 if not self.pe:
237 return None
238
239 try:
240 pe_timestamp = self.pe.FILE_HEADER.TimeDateStamp
241 except AttributeError:
242 return None
243
244 return datetime.fromtimestamp(pe_timestamp).strftime("%Y-%m-%d %H:%M:%S")
245
247 """Run analysis.
248 @return: analysis results dict or None.
249 """
250 if not os.path.exists(self.file_path):
251 return None
252
253 try:
254 self.pe = pefile.PE(self.file_path)
255 except pefile.PEFormatError:
256 return None
257
258 results = {}
259 results["peid_signatures"] = self._get_peid_signatures()
260 results["pe_imports"] = self._get_imported_symbols()
261 results["pe_exports"] = self._get_exported_symbols()
262 results["pe_sections"] = self._get_sections()
263 results["pe_resources"] = self._get_resources()
264 results["pe_versioninfo"] = self._get_versioninfo()
265 results["pe_imphash"] = self._get_imphash()
266 results["pe_timestamp"] = self._get_timestamp()
267 results["imported_dll_count"] = len([x for x in results["pe_imports"] if x.get("dll")])
268 return results
269
271 """Static analysis."""
272
286