Package modules :: Package processing :: Module static
[hide private]
[frames] | no frames]

Source Code for Module modules.processing.static

  1  # Copyright (C) 2010-2015 Cuckoo Foundation. 
  2  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  3  # See the file 'docs/LICENSE' for copying permission. 
  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  # Partially taken from 
 27  # http://malwarecookbook.googlecode.com/svn/trunk/3/8/pescanner.py 
 28   
29 -class PortableExecutable:
30 """PE analysis.""" 31
32 - def __init__(self, file_path):
33 """@param file_path: file path.""" 34 self.file_path = file_path 35 self.pe = None
36
37 - def _get_filetype(self, data):
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
62 - def _get_peid_signatures(self):
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
77 - def _get_imported_symbols(self):
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
105 - def _get_exported_symbols(self):
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
125 - def _get_sections(self):
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
148 - def _get_resources(self):
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
188 - def _get_versioninfo(self):
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
220 - def _get_imphash(self):
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
232 - def _get_timestamp(self):
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
246 - def run(self):
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
270 -class Static(Processing):
271 """Static analysis.""" 272
273 - def run(self):
274 """Run analysis. 275 @return: results dict. 276 """ 277 self.key = "static" 278 static = {} 279 280 if HAVE_PEFILE: 281 if self.task["category"] == "file": 282 if "PE32" in File(self.file_path).get_type(): 283 static = PortableExecutable(self.file_path).run() 284 285 return static
286