1
2
3
4
5 import os
6
7 try:
8 import magic
9 HAVE_MAGIC = True
10 except ImportError:
11 HAVE_MAGIC = False
12
13 try:
14 import pefile
15 import peutils
16 HAVE_PEFILE = True
17 except ImportError:
18 HAVE_PEFILE = False
19
20 from lib.cuckoo.common.abstracts import Processing
21 from lib.cuckoo.common.constants import CUCKOO_ROOT
22 from lib.cuckoo.common.objects import File
23 from lib.cuckoo.common.utils import convert_to_printable
24
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
55 return file_type
56
58 """Gets PEID signatures.
59 @return: matched signatures or None.
60 """
61 if not self.pe:
62 return None
63
64 try:
65 sig_path = os.path.join(CUCKOO_ROOT, "data",
66 "peutils", "UserDB.TXT")
67 signatures = peutils.SignatureDatabase(sig_path)
68 return signatures.match(self.pe, ep_only=True)
69 except:
70 return None
71
73 """Gets imported symbols.
74 @return: imported symbols dict or None.
75 """
76 if not self.pe:
77 return None
78
79 imports = []
80
81 if hasattr(self.pe, "DIRECTORY_ENTRY_IMPORT"):
82 for entry in self.pe.DIRECTORY_ENTRY_IMPORT:
83 try:
84 symbols = []
85 for imported_symbol in entry.imports:
86 symbol = {}
87 symbol["address"] = hex(imported_symbol.address)
88 symbol["name"] = imported_symbol.name
89 symbols.append(symbol)
90
91 imports_section = {}
92 imports_section["dll"] = entry.dll
93 imports_section["imports"] = symbols
94 imports.append(imports_section)
95 except:
96 continue
97
98 return imports
99
101 """Gets exported symbols.
102 @return: exported symbols dict or None.
103 """
104 if not self.pe:
105 return None
106
107 exports = []
108
109 if hasattr(self.pe, "DIRECTORY_ENTRY_EXPORT"):
110 for exported_symbol in self.pe.DIRECTORY_ENTRY_EXPORT.symbols:
111 symbol = {}
112 symbol["address"] = hex(self.pe.OPTIONAL_HEADER.ImageBase +
113 exported_symbol.address)
114 symbol["name"] = exported_symbol.name
115 symbol["ordinal"] = exported_symbol.ordinal
116 exports.append(symbol)
117
118 return exports
119
121 """Gets sections.
122 @return: sections dict or None.
123 """
124 if not self.pe:
125 return None
126
127 sections = []
128
129 for entry in self.pe.sections:
130 try:
131 section = {}
132 section["name"] = convert_to_printable(entry.Name.strip("\x00"))
133 section["virtual_address"] = "0x{0:08x}".format(entry.VirtualAddress)
134 section["virtual_size"] = "0x{0:08x}".format(entry.Misc_VirtualSize)
135 section["size_of_data"] = "0x{0:08x}".format(entry.SizeOfRawData)
136 section["entropy"] = entry.get_entropy()
137 sections.append(section)
138 except:
139 continue
140
141 return sections
142
144 """Get resources.
145 @return: resources dict or None.
146 """
147 if not self.pe:
148 return None
149
150 resources = []
151
152 if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"):
153 for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries:
154 try:
155 resource = {}
156
157 if resource_type.name is not None:
158 name = str(resource_type.name)
159 else:
160 name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id))
161
162 if hasattr(resource_type, "directory"):
163 for resource_id in resource_type.directory.entries:
164 if hasattr(resource_id, "directory"):
165 for resource_lang in resource_id.directory.entries:
166 data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size)
167 filetype = self._get_filetype(data)
168 language = pefile.LANG.get(resource_lang.data.lang, None)
169 sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang)
170
171 resource["name"] = name
172 resource["offset"] = "0x{0:08x}".format(resource_lang.data.struct.OffsetToData)
173 resource["size"] = "0x{0:08x}".format(resource_lang.data.struct.Size)
174 resource["filetype"] = filetype
175 resource["language"] = language
176 resource["sublanguage"] = sublanguage
177 resources.append(resource)
178 except:
179 continue
180
181 return resources
182
184 """Get version info.
185 @return: info dict or None.
186 """
187 if not self.pe:
188 return None
189
190 infos = []
191 if hasattr(self.pe, "VS_VERSIONINFO"):
192 if hasattr(self.pe, "FileInfo"):
193 for entry in self.pe.FileInfo:
194 try:
195 if hasattr(entry, "StringTable"):
196 for st_entry in entry.StringTable:
197 for str_entry in st_entry.entries.items():
198 entry = {}
199 entry["name"] = convert_to_printable(str_entry[0])
200 entry["value"] = convert_to_printable(str_entry[1])
201 infos.append(entry)
202 elif hasattr(entry, "Var"):
203 for var_entry in entry.Var:
204 if hasattr(var_entry, "entry"):
205 entry = {}
206 entry["name"] = convert_to_printable(var_entry.entry.keys()[0])
207 entry["value"] = convert_to_printable(var_entry.entry.values()[0])
208 infos.append(entry)
209 except:
210 continue
211
212 return infos
213
214
216 """Gets imphash.
217 @return: imphash string or None.
218 """
219 if not self.pe:
220 return None
221
222 try:
223 return self.pe.get_imphash()
224 except AttributeError:
225 return None
226
228 """Run analysis.
229 @return: analysis results dict or None.
230 """
231 if not os.path.exists(self.file_path):
232 return None
233
234 try:
235 self.pe = pefile.PE(self.file_path)
236 except pefile.PEFormatError:
237 return None
238
239 results = {}
240 results["peid_signatures"] = self._get_peid_signatures()
241 results["pe_imports"] = self._get_imported_symbols()
242 results["pe_exports"] = self._get_exported_symbols()
243 results["pe_sections"] = self._get_sections()
244 results["pe_resources"] = self._get_resources()
245 results["pe_versioninfo"] = self._get_versioninfo()
246 results["pe_imphash"] = self._get_imphash()
247 results["imported_dll_count"] = len([x for x in results["pe_imports"] if x.get("dll")])
248 return results
249
251 """Static analysis."""
252
266