├── README.md └── ripPE.py /README.md: -------------------------------------------------------------------------------- 1 | ripPE 2 | ========== 3 | 4 | **ripPE.py** helps you get at the data you want ("rip") from a Portable Exectuable (PE). ripPE focuses on extracting common sections and properties of PE files for analysis. Usage of this tool can help extract resources via the command line for quick triage, hash pertinent sections for grouping of similar files, and extract sections for developing more nuanced malware signatures (i.e. via YARA). 5 | 6 | ### Communicating ripPE to your friends/colleagues: 7 | * Hey friend, you should totally rip those resources out of that malware. 8 | * I'm going rip the heck out of this PE file. 9 | * The only thing I'm going to be ripping after eating this bean burrito are optional headers from this PE file. 10 | * I could export/extract those sections from this file but, I'd rather rip them out. 11 | 12 | ### Requires: 13 | * pefile 14 | * ssdeep 15 | * sqlite3 16 | 17 | ### Help: 18 | ``` 19 | usage: ripPE.py --file=[file] --section=[all/other] --dump (optional) --into-db (optional) --session="testing" 20 | 21 | ripPE.py - script used to rip raw structures from a PE file and list relevant 22 | characteristics. 23 | 24 | optional arguments: 25 | -h, --help show this help message and exit 26 | --file RIPFILE File to Parse 27 | --section {all,dos,header,iat,imports,exports,debug,sections,resources,dump_cert} 28 | Section to rip! 29 | --dump Dump raw data to file - when not provided only 30 | metadata printed to stdout 31 | --into-db Insert metadata into ripPE database 32 | --session SESSION_NAME 33 | Session Identifier - stored in DB 34 | ``` 35 | 36 | ### Usage: Single file saving raw sections to disk 37 | ``` 38 | python ripPE.py --file=reallybadmalware.exe --dump 39 | ``` 40 | 41 | ### Usage: Single file but storing data in a SQLite dabase stored at dbripPE/ripPE.db 42 | ``` 43 | python ripPE.py --file=reallybadmalware.exe --dump --into-db 44 | ``` 45 | 46 | ### Usage: Lots of files in a directory stored inside of a DB 47 | ``` 48 | for malware in $(ls /lotsofmalwaretobehadhere/ );do python ripPE.py --file=$malware --into-db;done 49 | ``` 50 | 51 | ### sqlite3 you say? 52 | Yes, I've joined the dark side. The serene beauty of the MySQL dolphin has been traded off for the lean, mean, fighting machine (possibly gluten-free with quinoa (or kale) sprinkled on top) sqlite3 database....may god have mercy on my soul. 53 | 54 | No worries for now. The tradeoff was for ultimate portability - meant to be as portable as the road warrior; the lone soul incident responder/malware researcher who needs to rip stuff out of a file and possibly find releated stuff in the same pile of unknowns....15 minutes ago. 55 | 56 | ## Future work... 57 | This code was more or less dusted off and bound together from previous projects - it works, but there are no guarantees. My goal in the future is to have less caveats and more features that suit those doing triage. 58 | -------------------------------------------------------------------------------- /ripPE.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os,sys 4 | import pefile 5 | import binascii 6 | import hashlib 7 | import argparse 8 | import textwrap 9 | import time 10 | import sqlite3 11 | from argparse import ArgumentParser 12 | 13 | 14 | class ripPE(object): 15 | 16 | def __init__(self,file_to_rip,dump_mode=False,into_db=False,session=False,hash_mode=False,ssdeep_it=False): 17 | 18 | self._date = time.time() 19 | self._hash_mode=hash_mode 20 | self._md5="" 21 | if self._hash_mode == "md5": 22 | self._md5 = hashlib.md5(open(file_to_rip).read()).hexdigest() 23 | elif self._hash_mode == "sha1": 24 | self._md5 = hashlib.sha1(open(file_to_rip).read()).hexdigest() 25 | elif self._hash_mode == "sha256": 26 | self._md5 = hashlib.sha256(open(file_to_rip).read()).hexdigest() 27 | self._dump_mode = dump_mode 28 | self._filename = os.path.basename(file_to_rip) 29 | self._ssd=ssdeep_it 30 | self._oep=None 31 | 32 | if self._ssd: 33 | try: 34 | exec "import ssdeep" in globals() 35 | except: 36 | print "Python ssdeep package not found... exiting" 37 | sys.exit(0) 38 | 39 | if session == False: 40 | self._session="ripPE-" + str(self._date) 41 | else: 42 | self._session = session 43 | 44 | try: 45 | self._pe = pefile.PE(file_to_rip) 46 | except: 47 | print "%s,%s,FAIL,FAIL,FAIL" % (self._filename,self._md5) 48 | sys.exit(0) 49 | 50 | self._imphash=self._pe.get_imphash() 51 | 52 | #::Begin static stuff::# 53 | self._pe_compile = self._pe.FILE_HEADER.TimeDateStamp 54 | self._oep=self._pe.OPTIONAL_HEADER.AddressOfEntryPoint 55 | self._ssdeep=None 56 | if self._ssd: 57 | self._ssdeep = ssdeep.hash_from_file(file_to_rip) 58 | self._into_db = into_db 59 | self._dbcon = False 60 | self._query = False 61 | 62 | if self._into_db: 63 | #::Check if DB exists::# 64 | #::Save shit in a local folder so you don't accidentally rm -rf the DB::# 65 | if not (os.path.isdir("./dbripPE")): 66 | os.mkdir("./dbripPE") 67 | 68 | #::Does DB exist::# 69 | if os.path.isfile("./dbripPE/ripPE.db") == False: 70 | #open('dbripPE/ripPE.db') 71 | self._dbcon=sqlite3.connect('./dbripPE/ripPE.db') 72 | self._dbcon.execute('''CREATE TABLE ripPE ( 73 | session VARCHAR(255) NOT NULL, 74 | date INT NOT NULL, 75 | file_name VARCHAR(255) NOT NULL, 76 | file_md5 VARCHAR(255) NOT NULL, 77 | section_type VARCHAR(255) NOT NULL, 78 | section_sub VARCHAR(255) NOT NULL, 79 | value VARCHAR(255))''') 80 | self._dbcon.commit() 81 | 82 | else: 83 | self._dbcon=sqlite3.connect('./dbripPE/ripPE.db') 84 | 85 | def db_close(self): 86 | self._dbcon.close() 87 | 88 | def output_handle(self,strOutput): 89 | print strOutput 90 | if self._into_db: 91 | #try: 92 | insVal = strOutput.split(',') 93 | #::prepend identifiers::# 94 | insVal.insert(0,self._date) 95 | insVal.insert(0,self._session) 96 | 97 | insertStatement = "INSERT INTO ripPE VALUES ( ?, ?, ?, ?, ?, ?, ?)" 98 | self._dbcon.execute(insertStatement, (insVal)) 99 | self._dbcon.commit() 100 | 101 | #except: 102 | # print "Couldn't insert into DB...exiting." 103 | # sys.exit(0) 104 | 105 | def run_all(self): 106 | self.list_standard() 107 | self.dump_iat() 108 | self.list_imports() 109 | self.dump_import() 110 | self.list_exports() 111 | self.get_virtual_section_info() 112 | self.get_debug() 113 | self.get_resource_info() 114 | self.dump_cert() 115 | 116 | def list_standard(self): 117 | 118 | self.output_handle("%s,%s,file_md5,file_md5,%s" % (self._filename,self._md5,self._md5)) 119 | 120 | if self._ssd: 121 | self.output_handle("%s,%s,file_ssdeep,file_header,%s" % (self._filename,self._md5,self._ssdeep)) 122 | self.output_handle("%s,%s,timedatestamp,file_header,%s" % (self._filename,self._md5,self._pe_compile)) 123 | self.output_handle("%s,%s,entry_point,file_header,%s" % (self._filename,self._md5,self._oep)) 124 | 125 | version_cat = [] 126 | version_value = [] 127 | version_both = [] 128 | version_list=[] 129 | 130 | if hasattr(self._pe, 'FileInfo'): 131 | try: 132 | for key,value in self._pe.FileInfo[0].StringTable[0].entries.items(): 133 | version_cat.append(key) 134 | version_value.append(value) 135 | version_both.append(key + ": " + value) 136 | self.output_handle("%s,%s,version_info,file_header_category,%s" % (self._filename,self._md5,key.encode('utf-8').strip())) 137 | self.output_handle("%s,%s,version_info,file_header_value,%s" % (self._filename,self._md5,value.encode('utf-8').strip())) 138 | self.output_handle("%s,%s,version_info,file_header_complete,%s: %s" % (self._filename,self._md5,key,value.encode('utf-8').strip())) 139 | except: 140 | true="Dat" 141 | version_list.append(version_cat) 142 | version_list.append(version_value) 143 | version_list.append(version_both) 144 | 145 | version_cat_str = "\n".join(version_list[0]) 146 | version_value_str = "\n".join(version_list[1]) 147 | version_both_str = "\n".join(version_list[2]) 148 | 149 | if self._hash_mode == "md5": 150 | self.output_handle("%s,%s,version_category_md5,file_header_category,%s" % (self._filename,self._md5,hashlib.md5(version_cat_str.encode('utf-8').strip()).hexdigest())) 151 | elif self._hash_mode == "sha1": 152 | self.output_handle("%s,%s,version_category_md5,file_header_category,%s" % (self._filename,self._md5,hashlib.sha1(version_cat_str.encode('utf-8').strip()).hexdigest())) 153 | elif self._hash_mode == "sha256": 154 | self.output_handle("%s,%s,version_category_md5,file_header_category,%s" % (self._filename,self._md5,hashlib.sha256(version_cat_str.encode('utf-8').strip()).hexdigest())) 155 | 156 | if self._ssd: 157 | self.output_handle("%s,%s,version_category_ssdeep,file_header_category,%s" % (self._filename,self._md5,ssdeep.hash(version_cat_str.encode('utf-8').strip()))) 158 | 159 | if self._hash_mode == "md5": 160 | self.output_handle("%s,%s,version_value_md5,file_header_value,%s" % (self._filename,self._md5,hashlib.md5(version_value_str.encode('utf-8').strip()).hexdigest())) 161 | elif self._hash_mode == "sha1": 162 | self.output_handle("%s,%s,version_value_md5,file_header_value,%s" % (self._filename,self._md5,hashlib.sha1(version_value_str.encode('utf-8').strip()).hexdigest())) 163 | elif self._hash_mode == "sha256": 164 | self.output_handle("%s,%s,version_value_md5,file_header_value,%s" % (self._filename,self._md5,hashlib.sha256(version_value_str.encode('utf-8').strip()).hexdigest())) 165 | 166 | if self._ssd: 167 | self.output_handle("%s,%s,version_category_ssdeep,file_header_value,%s" % (self._filename,self._md5,ssdeep.hash(version_value_str.encode('utf-8').strip()))) 168 | 169 | if self._hash_mode == "md5": 170 | self.output_handle("%s,%s,version_version_md5,file_header_version,%s" % (self._filename,self._md5,hashlib.md5(version_both_str.encode('utf-8').strip()).hexdigest())) 171 | elif self._hash_mode == "sha1": 172 | self.output_handle("%s,%s,version_version_md5,file_header_version,%s" % (self._filename,self._md5,hashlib.sha1(version_both_str.encode('utf-8').strip()).hexdigest())) 173 | elif self._hash_mode == "sha256": 174 | self.output_handle("%s,%s,version_version_md5,file_header_version,%s" % (self._filename,self._md5,hashlib.sha256(version_both_str.encode('utf-8').strip()).hexdigest())) 175 | 176 | if self._ssd: 177 | self.output_handle("%s,%s,version_version_ssdeep,file_header_value,%s" % (self._filename,self._md5,ssdeep.hash(version_both_str.encode('utf-8').strip()))) 178 | 179 | #def dump_dos(self): 180 | # #::TODO: LIST OUT DOS HEADER PARAMETERS + IMAGE TYPE::# 181 | # if hasattr(self._pe, 'IMAGE_SECTION_HEADER'): 182 | # print dir(self._pe.IMAGE_SECTION_HEADER) 183 | 184 | def dump_import(self): 185 | 186 | if not hasattr(self._pe, 'DIRECTORY_ENTRY_IMPORT'): 187 | return 188 | 189 | for idx in xrange(len(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY)): 190 | if self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].name == "IMAGE_DIRECTORY_ENTRY_IMPORT": 191 | data=self._pe.get_data(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].VirtualAddress,self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].Size) 192 | 193 | if self._hash_mode == "md5": 194 | struct_md5=hashlib.md5(data).hexdigest() 195 | elif self._hash_mode == "sha1": 196 | struct_md5=hashlib.sha1(data).hexdigest() 197 | elif self._hash_mode == "sha256": 198 | struct_md5=hashlib.sha256(data).hexdigest() 199 | 200 | 201 | struct_ssdeep="NoMode" 202 | if self._ssd: 203 | struct_ssdeep=ssdeep.hash(data) 204 | if self._dump_mode == True: 205 | write_iat=open("ripPE-IMPORT-" + self._md5 + "-" + struct_md5 + ".import","wb+") 206 | write_iat.write(data) 207 | write_iat.close() 208 | 209 | if self._ssd: 210 | self.output_handle("%s,%s,import_ssdeep,IMAGE_DIRECTORY_ENTRY_IMPORT,%s" % (self._filename,self._md5,struct_ssdeep)) 211 | 212 | def dump_iat(self): 213 | 214 | for idx in xrange(len(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY)): 215 | if self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].name == "IMAGE_DIRECTORY_ENTRY_IAT": 216 | data=self._pe.get_data(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].VirtualAddress,self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].Size) 217 | if self._hash_mode == "md5": 218 | struct_md5=hashlib.md5(data).hexdigest() 219 | elif self._hash_mode == "sha1": 220 | struct_md5=hashlib.sha1(data).hexdigest() 221 | elif self._hash_mode == "sha256": 222 | struct_md5=hashlib.sha256(data).hexdigest() 223 | 224 | struct_ssdeep="NoMode" 225 | if self._ssd: 226 | struct_ssdeep=ssdeep.hash(data) 227 | if self._dump_mode == True: 228 | write_iat=open("ripPE-IAT-" + self._md5 + "-" + struct_md5 + ".iat","wb+") 229 | write_iat.write(data) 230 | write_iat.close() 231 | self.output_handle("%s,%s,iat_md5,IMAGE_DIRECTORY_ENTRY_IAT,%s" % (self._filename,self._md5,struct_md5)) 232 | if self._ssd: 233 | self.output_handle("%s,%s,iat_ssdeep,IMAGE_DIRECTORY_ENTRY_IAT,%s" % (self._filename,self._md5,struct_ssdeep)) 234 | 235 | def list_imports(self): 236 | #::Bound Imports::# 237 | #::TODO: FIX THIS::# 238 | if hasattr(self._pe, 'DIRECTORY_ENTRY_BOUND_IMPORT'): 239 | for entry in self._pe.DIRECTORY_ENTRY_BOUND_IMPORT: 240 | for imports in entry.entries: 241 | if (imports.name != None) and (imports.name != ""): 242 | self.output_handle("%s,%s,import_symbol,DIRECTORY_ENTRY_IMPORT_BOUND,%s" % (self._filename,self._md5,imports.name)) 243 | 244 | #::Delayed Imports::# 245 | if hasattr(self._pe, 'DIRECTORY_ENTRY_DELAY_IMPORT'): 246 | for module in self._pe.DIRECTORY_ENTRY_DELAY_IMPORT: 247 | for symbol in module.imports: 248 | if symbol.import_by_ordinal is True: 249 | self.output_handle("%s,%s,import_symbol_ord,DIRECTORY_ENTRY_DELAY_IMPORT,%s-%s" % (self._filename,self._md5,module.dll,symbol.ordinal)) 250 | else: 251 | self.output_handle("%s,%s,import_symbol_ord,DIRECTORY_ENTRY_DELAY_IMPORT,%s-%s-%s" % (self._filename,self._md5,module.dll,symbol.name,str(symbol.hint))) 252 | 253 | #::Dynamic Imports::# 254 | if hasattr(self._pe, 'DIRECTORY_ENTRY_IMPORT'): 255 | if self._dump_mode == True: 256 | self.dump_import() 257 | imports_total = len(self._pe.DIRECTORY_ENTRY_IMPORT) 258 | #::hash em!::# 259 | import_list=[] 260 | import_list_raw=[] 261 | if imports_total > 0: 262 | for entry in self._pe.DIRECTORY_ENTRY_IMPORT: 263 | for imp in entry.imports: 264 | if (imp.name != None) and (imp.name != ""): 265 | self.output_handle("%s,%s,import_symbol,DIRECTORY_ENTRY_IMPORT,%s" % (self._filename,self._md5,entry.dll + "." + imp.name)) 266 | import_list.append(str(entry.dll + "." + imp.name).upper()) 267 | import_list_raw.append(entry.dll + "." + imp.name) 268 | import_list.sort() 269 | resultingImports="" 270 | resultingImportsRaw="" 271 | for impo in import_list: 272 | resultingImports+=impo + "\n" 273 | 274 | for impo in import_list_raw: 275 | resultingImportsRaw+=impo + "\n" 276 | 277 | self.output_handle("%s,%s,imphash,IMPORT_HASH,%s" % (self._filename,self._md5,self._imphash)) 278 | 279 | 280 | def list_exports(self): 281 | if not hasattr(self._pe, 'DIRECTORY_ENTRY_EXPORT'): 282 | return 283 | else: 284 | exports_total = len(self._pe.DIRECTORY_ENTRY_EXPORT.symbols) 285 | if exports_total > 0: 286 | for entry in self._pe.DIRECTORY_ENTRY_EXPORT.symbols: 287 | if (entry.name != None) and (entry.name != ""): 288 | self.output_handle("%s,%s,export_symbol,DIRECTORY_ENTRY_EXPORT,%s" % (self._filename,self._md5,entry.name)) 289 | 290 | def get_virtual_section_info(self): 291 | for section in self._pe.sections: 292 | name=str(section.Name.rstrip('\0')) 293 | data=self._pe.get_data(section.VirtualAddress,section.SizeOfRawData) 294 | data_md5="hash2be" 295 | 296 | if self._hash_mode == "md5": 297 | data_md5=hashlib.md5(data).hexdigest() 298 | elif self._hash_mode == "sha1": 299 | data_md5=hashlib.sha1(data).hexdigest() 300 | elif self._hash_mode == "sha256": 301 | data_md5=hashlib.sha256(data).hexdigest() 302 | 303 | data_ssdeep="NoMode" 304 | if self._ssd: 305 | data_ssdeep = ssdeep.hash(data) 306 | if self._dump_mode == True: 307 | section_write=open("ripPE-SECTION-" + self._md5 + "-" + data_md5 + name,"wb+") 308 | section_write.write(data) 309 | section_write.close() 310 | 311 | self.output_handle("%s,%s,section_hash,%s,%s" % (self._filename,self._md5,name,data_md5)) 312 | 313 | if self._ssd: 314 | self.output_handle("%s,%s,section_ssdeep,%s,%s" % (self._filename,self._md5,name,data_ssdeep)) 315 | 316 | def get_debug(self): 317 | if not hasattr(self._pe, 'DIRECTORY_ENTRY_DEBUG'): 318 | return 319 | else: 320 | for idx in xrange(len(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY)): 321 | if self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].name == "IMAGE_DIRECTORY_ENTRY_DEBUG": 322 | name=self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].name 323 | for dbg in self._pe.DIRECTORY_ENTRY_DEBUG: 324 | data=self._pe.get_data(dbg.struct.AddressOfRawData,dbg.struct.SizeOfData) 325 | data_md5="hash2be" 326 | 327 | if self._hash_mode == "md5": 328 | data_md5=hashlib.md5(data).hexdigest() 329 | elif self._hash_mode == "sha1": 330 | data_md5=hashlib.sha1(data).hexdigest() 331 | elif self._hash_mode == "sha256": 332 | data_md5=hashlib.sha256(data).hexdigest() 333 | 334 | data_ssdeep="NoMode" 335 | if self._ssd: 336 | data_ssdeep=ssdeep.hash(data) 337 | if self._dump_mode == True: 338 | section_object=open("ripPE-DEBUG-" + self._md5 + "-" + data_md5 + ".debug","wb+") 339 | section_object.write(data) 340 | section_object.close() 341 | self.output_handle("%s,%s,debug_hash,DIRECTORY_ENTRY_DEBUG,%s" % (self._filename,self._md5,data_md5)) 342 | if self._ssd: 343 | self.output_handle("%s,%s,debug_ssdeep,DIRECTORY_ENTRY_DEBUG,%s" % (self._filename,self._md5,data_ssdeep)) 344 | 345 | def get_resource_info(self): 346 | if hasattr(self._pe, 'DIRECTORY_ENTRY_RESOURCE'): 347 | for resource_type in self._pe.DIRECTORY_ENTRY_RESOURCE.entries: 348 | if resource_type.name is not None: 349 | name = "%s" % resource_type.name 350 | else: 351 | name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) 352 | if name == None: 353 | name = "%d" % resource_type.struct.Id 354 | if hasattr(resource_type, 'directory'): 355 | for resource_id in resource_type.directory.entries: 356 | if hasattr(resource_id, 'directory'): 357 | for resource_lang in resource_id.directory.entries: 358 | data = self._pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) 359 | lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') 360 | sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) 361 | resource_md5 = "hash2be" 362 | 363 | if self._hash_mode == "md5": 364 | resource_md5=hashlib.md5(data).hexdigest() 365 | elif self._hash_mode == "sha1": 366 | resource_md5=hashlib.sha1(data).hexdigest() 367 | elif self._hash_mode == "sha256": 368 | resource_md5=hashlib.sha256(data).hexdigest() 369 | 370 | if self._ssd: 371 | resource_ssdeep = ssdeep.hash(data) 372 | if self._dump_mode == True: 373 | resource_dump=open("ripPE-RESOURCE-" + self._md5 + "-" + name + "-" + resource_md5 + ".rsrc","wb+") 374 | resource_dump.write(data) 375 | resource_dump.close() 376 | self.output_handle("%s,%s,resource_md5,RESOURCE-%s,%s" % (self._filename,self._md5,name,resource_md5)) 377 | if self._ssd: 378 | self.output_handle("%s,%s,resource_ssdeep,RESOURCE-%s,%s" % (self._filename,self._md5,name,resource_ssdeep)) 379 | 380 | def dump_cert(self): 381 | for idx in xrange(len(self._pe.OPTIONAL_HEADER.DATA_DIRECTORY)): 382 | if self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].name == 'IMAGE_DIRECTORY_ENTRY_SECURITY': 383 | if self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].Size == 0 and self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].VirtualAddress == 0: 384 | return 385 | address=self._pe.OPTIONAL_HEADER.DATA_DIRECTORY[idx].VirtualAddress 386 | signature=self._pe.write()[address+8:] #::Thanks Didier Stevens!! 387 | cert_md5="hash2be" 388 | if self._hash_mode == "md5": 389 | cert_md5=hashlib.md5(signature).hexdigest() 390 | elif self._hash_mode == "sha1": 391 | cert_md5=hashlib.sha1(signature).hexdigest() 392 | elif self._hash_mode == "sha256": 393 | cert_md5=hashlib.sha256(signature).hexdigest() 394 | 395 | cert_ssdeep="NoMode" 396 | if self._ssd: 397 | cert_ssdeep=ssdeep.hash(signature) 398 | if self._dump_mode == True: 399 | hash_dump=open("ripPE-CERT-" + self._md5 + "-" + cert_md5 + ".crt","wb+") 400 | hash_dump.write(signature) 401 | hash_dump.close() 402 | self.output_handle("%s,%s,certificate_hash,DIRECTORY_ENTRY_SECURITY,%s" % (self._filename,self._md5,cert_md5)) 403 | if self._ssd: 404 | self.output_handle("%s,%s,certificate_ssdeep,DIRECTORY_ENTRY_SECURITY,%s" % (self._filename,self._md5,cert_ssdeep)) 405 | 406 | def main(): 407 | 408 | p = ArgumentParser(description='ripPE.py - script used to rip raw structures from a PE file and list relevant characteristics.',usage='ripPE.py --file=[file] --dump') 409 | p.add_argument('--file',action='store',dest='ripFile',help='File to Parse',required=True) 410 | p.add_argument('--section',action='store',dest='ripSection',choices=['all','header','iat','imports','exports','debug','sections','resources','dump_cert'],default='all',help='Section to rip!',required=False) 411 | p.add_argument('--dump',action='store_true',default=False,dest='dump_mode',help='Dump raw data to file - when not provided only metadata printed to stdout',required=False) 412 | p.add_argument('--into-db',action='store_true',default=False,dest='into_db',help='Insert metadata into ripPE database',required=False) 413 | p.add_argument('--session',action='store',default=False,dest='session_name',help='Session Identifier - stored in DB',required=False) 414 | p.add_argument('--hash_mode',action='store',dest='hashMode',choices=['md5','sha1','sha256'],help='Checksum method section hashing. (Default sha256)',default='sha256',required=False) 415 | p.add_argument('--ssdeep',action='store_true',default=False,dest='ssdeep_it',help='Print ssdeep value for sections/resources',required=False) 416 | args = p.parse_args(sys.argv[1:]) 417 | 418 | pe=ripPE(args.ripFile,args.dump_mode,args.into_db,args.session_name,args.hashMode,args.ssdeep_it) 419 | 420 | if args.ssdeep_it: 421 | import ssdeep 422 | 423 | if args.ripSection.upper() == "ALL": 424 | pe.run_all() 425 | elif args.ripSection.upper() == "HEADER": 426 | pe.list_standard() 427 | elif args.ripSection.upper() == "IAT": 428 | pe.dump_iat() 429 | elif args.ripSection.upper() == "IMPORTS": 430 | pe.list_imports() 431 | #pe.dump_import() 432 | elif args.ripSection.upper() == "EXPORTS": 433 | pe.list_exports() 434 | elif args.ripSection.upper() == "DEBUG": 435 | pe.get_debug() 436 | elif args.ripSection.upper() == "SECTIONS": 437 | pe.get_virtual_section_info() 438 | elif args.ripSection.upper() == "RESOURCES": 439 | pe.get_resource_info() 440 | elif args.ripSection.upper() == "DUMP_CERT": 441 | pe.dump_cert() 442 | else: 443 | print "Something bad happened..." 444 | 445 | #::Close DB::# 446 | if args.into_db == True: 447 | pe.db_close() 448 | 449 | if __name__ == '__main__': 450 | main() 451 | --------------------------------------------------------------------------------