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

Source Code for Module modules.processing.static

  1  # Copyright (C) 2010-2014 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   
  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  # 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 55 return file_type
56
57 - def _get_peid_signatures(self):
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
72 - def _get_imported_symbols(self):
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
100 - def _get_exported_symbols(self):
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
120 - def _get_sections(self):
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
143 - def _get_resources(self):
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
183 - def _get_versioninfo(self):
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
215 - def _get_imphash(self):
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
227 - def run(self):
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
250 -class Static(Processing):
251 """Static analysis.""" 252
253 - def run(self):
254 """Run analysis. 255 @return: results dict. 256 """ 257 self.key = "static" 258 static = {} 259 260 if HAVE_PEFILE: 261 if self.task["category"] == "file": 262 if "PE32" in File(self.file_path).get_type(): 263 static = PortableExecutable(self.file_path).run() 264 265 return static
266