├── .gitignore ├── LICENSE.md ├── README.md ├── malwarehouse.cfg ├── malwarehouse.py └── yararules └── yararules.yar /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ~/Desktop/malwarehouse/malwarehouse.db 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2012 Toga Foam Party Studios. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY TOGA FOAM PARTY STUDIOS ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOGA FOAM PARTY STUDIOS OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Toga Foam Party Studios. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Malwarehouse is a warehouse for your malware. Malwarehouse is a useful command line utility for storing, tagging, storing, and searching for malware. This is intended to help analyst manage their workflow by conducting basic triage and making it easy to look up past samples. 2 | 3 | ## Requirements 4 | * Python 2.7 5 | 6 | ## Authors 7 | * Scott J Roberts - [@sroberts](https://twitter.com/sroberts) 8 | 9 | ## License 10 | See LICENSE for more information 11 | 12 | ## Thanks 13 | * Jonathan Hencinski 14 | * Chris St.Myers 15 | 16 | -------- 17 | 18 | Xen0ph0ns Fork of Malwarehouse below this point: 19 | Let me know if stuff is broken chris@xenosec.org 20 | 21 | ## New Requirements (Each Optional and Can Be Disabled) 22 | * ssdeep / pydeep 23 | * exiftool / pyexiftool 24 | * yara / python yara 25 | * VirusTotal API (Free is fine) 26 | 27 | ## New Features 28 | 29 | * Moved directory settings / VT API Key / Yara Rule File Settings to malwarehouse.cfg 30 | * Added SSdeep Fuzzy Hashing 31 | * Added Extraction and Search Feature for Metadata 32 | * Added Full File Yara Scanning and Search Feature 33 | * Added VirusTotal Hit Ratio / Scan Date Lookup (can do much better stuff with a paid API) 34 | * Increased breadth of sample search to cover Tags / Source / Name (No longer needs exact match) 35 | * Redid other various things to make the above happy... 36 | 37 | ## Instructions for set up 38 | 39 | Install the prereqs.. then edit the following to the malwarehouse.cfg file: 40 | 41 | ``` 42 | #Config File for Malwarehouse 43 | #Turn on or off options here 44 | [options] 45 | vtcheck: Off 46 | metadata: On 47 | yara: On 48 | ssdeep: On 49 | 50 | [settings] 51 | #This is where you want the malware and DB to live 52 | basedir: /Path/to/Malwarehouse/MWH/ 53 | #This is the path to your yara rules file full path please. 54 | yararules: /Path/To/yararules/yararules.yar 55 | #This is your free virus total API, max lookups is 4 per minute IIRC. Make a VT Account then click Profile API in the upper right corner, it's free. 56 | vtapikey: VTAPI KEY GOES HERE 57 | ``` 58 | 59 | ## Usage 60 | ``` 61 | Usage: malwarehouse.py [options] filepath 62 | 63 | Options: 64 | --version show program's version number and exit 65 | -h, --help show this help message and exit 66 | -s SOURCE, --source=SOURCE 67 | Source of file 68 | -t TAGS, --tags=TAGS Any characteristics of the malware 69 | -n NOTES, --notes=NOTES 70 | Notes about file 71 | -f FIND, --find=FIND Find a sample by name, tags, source, md5, or sha256 72 | -m MFIND, --metadata=MFIND 73 | Find a sample by searching Extracted Metadata 74 | -y YFIND, --yara=YFIND 75 | Find a sample by searching Yara Matches 76 | -r QUANTITY, --recent=QUANTITY 77 | Find the most recent # samples 78 | ``` 79 | 80 | 81 | ## Example Query Result 82 | ``` 83 | Results for "Virus Total Intel API": 84 | 85 | -> record.doc (2568615875525003688839cb8950aeae) Source: Virus Total Intel API 86 | VirusTotal: 25/45 on 2013-02-13 01:25:41 Tags: Document Carrier File, Flash 0 Day, poop 87 | Notes: Found on OSI, targeted defense first, january 88 | Yara: [TestYara_Hit, TestYara_HitNumber2, More_Of_Yara] 89 | -> Sample Location: /Users/cclark/Desktop/MWH/26fae6918bb8c9e48fda95b96accf3fb0145183055dfba917bb3b6de84c7f7a7 90 | 91 | -> 3a861b8526e397b3684a99f363ec145b-cupsd (3a861b8526e397b3684a99f363ec145b) Source: Virus Total Intel API 92 | VirusTotal: 10/46 on 2013-02-21 06:22:37 Tags: OSX, Plist, Facebook, WateringHole 93 | Notes: OSX Malware from FB/Twitter/Apple Pop referenced on PasteBin 94 | Yara: [TestYara_Hit] 95 | -> Sample Location: /Users/cclark/Desktop/MWH/a610bb3396a2eb6186a135de5d0a5d29e16525fb7c069e853d0ce2bb90ca4921 96 | 97 | ``` 98 | 99 | ## Example Output Per File 100 | ``` 101 | datetime: 2013-02-24 14:49:30.553211 102 | name: record.doc 103 | source: Virus Total Intel API 104 | tags: Document Carrier File, Flash 0 Day 105 | notes: Published on Contagio, targeted DIB first, january 106 | mimetype: application/msword 107 | size: 563200 108 | md5: 2568615875525003688839cb8950aeae 109 | sha256: 26fae6918bb8c9e48fda95b96accf3fb0145183055dfba917bb3b6de84c7f7a7 110 | ssdeep: 3072:jXkvs80OQiRNfzaR8Yun8ZzTVedcnR6BY2LT+MAAKxrYzaR8Yun8ZzTVedcn9VW1:jks8vzaRLaod0Y2LTpAazaRLaodDV0 111 | virustotal: 25/45 on 2013-02-13 01:25:41 112 | yara: [TestYara_Hit, TestYara_HitNumber2, More_Of_Yara] 113 | metadata: 114 | Subject: 115 | ScaleCrop: 0 116 | FileAccessDate: 2013:02:24 16:59:17-05:00 117 | CompObjUserTypeLen: 35 118 | Words: 821 119 | FileModifyDate: 2013:02:24 16:59:17-05:00 120 | TotalEditTime: 0 121 | Security: 0 122 | Characters: 4683 123 | HyperlinksChanged: 0 124 | FileSize: 563200 125 | Template: Normal.dotm 126 | Hyperlinks: [u'https://portal.adp.com/'] 127 | AppVersion: 12.0 128 | Paragraphs: 10 129 | Lines: 39 130 | FileType: DOC 131 | FileName: record.doc 132 | Keywords: 133 | SharedDoc: 0 134 | CharCountWithSpaces: 5494 135 | CreateDate: 2013:02:05 09:36:00 136 | Pages: 1 137 | RevisionNumber: 2 138 | Author: Admin 139 | Company: 140 | CodePage: 936 141 | FileInodeChangeDate: 2013:02:24 16:59:17-05:00 142 | Software: Microsoft Office Word 143 | LinksUpToDate: 0 144 | ModifyDate: 2013:02:05 09:36:00 145 | Title: 146 | LastModifiedBy: smith 147 | 148 | ``` 149 | -------------------------------------------------------------------------------- /malwarehouse.cfg: -------------------------------------------------------------------------------- 1 | #Config File for Malwarehouse 2 | # 'On' to turn options on, anything else = off. 3 | [options] 4 | vtcheck: On 5 | metadata: On 6 | yara: On 7 | ssdeep: On 8 | 9 | # You need to set up each of these 10 | [settings] 11 | basedir: /Users/cclark/Desktop/MWH/ 12 | yararules: /Users/cclark/Desktop/Malwarehouse/yararules/yararules.yar 13 | vtapikey: APIKEYGOESHERE 14 | -------------------------------------------------------------------------------- /malwarehouse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | malwarehouse.py 5 | 6 | Created by Scott Roberts. 7 | Copyright (c) 2012 TogaFoamParty Studios. All rights reserved. 8 | 9 | Yara/Exiftool/SSdeep/VT added by Chris Clark chris@xenosec.org 10 | """ 11 | 12 | import datetime, os, hashlib, sqlite3, shutil, re, urllib, urllib2, ConfigParser, json 13 | import magic 14 | from optparse import OptionParser 15 | from collections import OrderedDict 16 | 17 | #Get Config Options 18 | config = ConfigParser.SafeConfigParser() 19 | config.read("malwarehouse.cfg") 20 | 21 | option_base_dir = config.get('settings','basedir') 22 | 23 | # Import optional requirments 24 | 25 | if config.get('options', 'metadata') == 'On': 26 | import exiftool 27 | if config.get('options', 'yara') == 'On': 28 | import yara 29 | if config.get('options', 'ssdeep') == 'On': 30 | import pydeep 31 | 32 | def check_prelim(): 33 | """Initial setup code. Eventually this will set options.""" 34 | 35 | db_path = option_base_dir + "malwarehouse.db" 36 | dir_path = os.path.dirname(option_base_dir) 37 | 38 | if not os.path.exists(dir_path): 39 | print "[ERROR] Base directory %s doesn't exist. Creating it..." % (dir_path) 40 | os.makedirs(dir_path) 41 | 42 | if not os.path.exists(db_path): 43 | print "[ERROR] Database %s doesn't exist. Creating it..." % (db_path) 44 | 45 | conn = sqlite3.connect(db_path) 46 | c = conn.cursor() 47 | 48 | # Create table 49 | c.execute('''CREATE TABLE IF NOT EXISTS malwarehouse_index (datetime text, name text, mimetype text, tags text, size integer, md5 text, sha256 text, source text, notes text, vtapi text, metadata text, ssdeep text, yara text)''') 50 | 51 | # Save (commit) the changes 52 | conn.commit() 53 | 54 | # We can also close the cursor if we are done with it 55 | c.close() 56 | 57 | return True 58 | 59 | def vtapi(md5): 60 | url = "https://www.virustotal.com/vtapi/v2/file/report" 61 | parameters = {"resource": md5, "apikey": config.get('settings','vtapikey') } 62 | data = urllib.urlencode(parameters) 63 | req = urllib2.Request(url, data) 64 | response = urllib2.urlopen(req) 65 | VTjson = json.loads(response.read()) 66 | #print VTjson 67 | if VTjson['response_code'] == 1 : 68 | return str(VTjson['positives']) + '/' + str(VTjson['total']) + ' on ' + str(VTjson['scan_date']) 69 | else : 70 | return "File Does Not Exist in VirusTotal" 71 | 72 | def yara_scan(malware_path): 73 | compiledRules = yara.compile(config.get('settings','yararules')) 74 | matches = compiledRules.match(malware_path) 75 | return str(matches) 76 | 77 | def get_md5(malware_path): 78 | """Wrapper for the usual md5 call because it's so verbose.""" 79 | 80 | return hashlib.md5(file(malware_path, 'r').read()).hexdigest() 81 | 82 | def get_ssdeep(malware_path): 83 | return pydeep.hash_file(malware_path) 84 | 85 | def get_sha256(malware_path): 86 | """Wrapper for the usual sha256 call because it's so verbose.""" 87 | 88 | return hashlib.sha256(file(malware_path, 'r').read()).hexdigest() 89 | 90 | def get_mime_type(malware_path): 91 | """Using magic library to detect the mime type of a given file.""" 92 | try: 93 | mime = magic.Magic(mime=True) 94 | return mime.from_file(malware_path) 95 | except Exception: 96 | return "Unknown" 97 | 98 | def get_metadata(malware_path): 99 | with exiftool.ExifTool() as et: 100 | metadata = et.get_metadata(malware_path) 101 | del metadata[u'SourceFile'] 102 | del metadata[u'File:FilePermissions'] 103 | del metadata[u'File:Directory'] 104 | del metadata[u'ExifTool:ExifToolVersion'] 105 | del metadata[u'File:MIMEType'] 106 | metadataString = '\n' 107 | for each in metadata.items(): 108 | try: 109 | metadataString += '\t\t' + str(each[0]).split(':', 1)[-1] + ": " + str(each[1]) + "\n" 110 | except Exception, e: 111 | continue 112 | 113 | return metadataString 114 | 115 | def summary(report_json): 116 | """Prints an easy to read summary of the malware.""" 117 | 118 | return "-> %s (%s) Source: %s \n VirusTotal: %s Tags: %s \n Notes: %s \n Yara: %s \n -> Sample Location: %s \n" % (report_json['name'], report_json['md5'], report_json['source'], report_json['vtapi'], report_json['tags'], report_json['notes'], report_json['yara'], option_base_dir + report_json['sha256']) 119 | 120 | def details(report_json): 121 | """Prints an easy to read summary of the malware.""" 122 | 123 | details = "" 124 | details += "datetime: %s\n" % (report_json['datetime']) 125 | details += "name: %s\n" % (report_json['name']) 126 | details += "source: %s\n" % (report_json['source']) 127 | details += "tags: %s\n" % (report_json['tags']) 128 | details += "notes: %s\n" % (report_json['notes']) 129 | details += "mimetype: %s\n" % (report_json['mimetype']) 130 | details += "size: %s\n" % (report_json['size']) 131 | details += "md5: %s\n" % (report_json['md5']) 132 | details += "sha256: %s\n" % (report_json['sha256']) 133 | details += "ssdeep: %s\n" % (report_json['ssdeep']) 134 | details += "virustotal: %s\n" % (report_json['vtapi']) 135 | details += "yara: %s\n" % (report_json['yara']) 136 | details += "metadata: %s\n" % (report_json['metadata']) 137 | details += "\n" 138 | details += "sample directory: %s" % option_base_dir + report_json['sha256'] 139 | 140 | return details 141 | 142 | def load_db(report_json): 143 | """Load information about the sample into the index DB.""" 144 | 145 | conn = sqlite3.connect(option_base_dir + "malwarehouse.db") 146 | c = conn.cursor() 147 | 148 | # Insert a row of data 149 | c.execute("INSERT INTO malwarehouse_index VALUES (\"%s\", \"%s\", \"%s\", \"%s\", \"%d\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\")" % (report_json['datetime'], report_json['name'], report_json['mimetype'], report_json['tags'], report_json['size'], report_json['md5'], report_json['sha256'], report_json['source'], report_json['notes'], report_json['vtapi'], report_json['metadata'], report_json['ssdeep'], report_json['yara'],)) 150 | 151 | # Save (commit) the changes 152 | conn.commit() 153 | 154 | # We can also close the cursor if we are done with it 155 | c.close() 156 | 157 | print "Sample %s loaded..." % report_json['name'] 158 | return True 159 | 160 | def load_directory(report_json, malware_path): 161 | """Creates a directory to store the malware and summary.""" 162 | print "Loading Malware %s" % malware_path 163 | 164 | sample_dir = "%s%s" % (option_base_dir, report_json['sha256']) 165 | 166 | if not os.path.exists(sample_dir): 167 | print "Creating %s" % (sample_dir) 168 | os.makedirs(sample_dir) 169 | 170 | shutil.move(malware_path, sample_dir) 171 | 172 | with open(sample_dir + '/summary.txt', 'w') as text_file: 173 | text_file.write(details(report_json)) 174 | 175 | return True 176 | 177 | def malware_loader(report_json, malware_path): 178 | load_db(report_json) 179 | load_directory(report_json, malware_path) 180 | 181 | def parse_sqlite_result(unparsed): 182 | "Takes the results from a SQLite query and parses it as a dictionary." 183 | 184 | return {'datetime': unparsed[0], 'name': unparsed[1], 'mimetype': unparsed[2], 'tags': unparsed[3], 'size': unparsed[4], 'md5': unparsed[5], 'sha256': unparsed[6], 'source': unparsed[7], 'notes': unparsed[8], 'vtapi': unparsed[9], 'metadata': unparsed[10], 'ssdeep': unparsed[11], 'yara': unparsed[12]} 185 | 186 | def find_sample(find_string): 187 | 188 | conn = sqlite3.connect(option_base_dir + "malwarehouse.db") 189 | c = conn.cursor() 190 | 191 | if re.findall(r"^([a-fA-F\d]{64})$", find_string): 192 | #print "\nResults for sha256: %s" % find_string 193 | c.execute("SELECT * FROM malwarehouse_index WHERE sha256 = ?", (find_string,)) 194 | elif re.findall(r"^([a-fA-F\d]{32})$", find_string): 195 | #print "\nResults for md5: %s" % find_string 196 | c.execute("SELECT * FROM malwarehouse_index WHERE md5 = ?", (find_string,)) 197 | else: 198 | #print "\nResults for file name: %s" % find_string 199 | c.execute("SELECT * FROM malwarehouse_index WHERE name LIKE :query OR tags LIKE :query OR source LIKE :query ", {"query" : '%' + find_string + '%'}) 200 | 201 | data=c.fetchall() 202 | 203 | if data: 204 | print "\nResults for \"" + find_string + "\":\n" 205 | for result in data: 206 | print summary(parse_sqlite_result(result)) 207 | return True 208 | else: 209 | print('No Samples Named, Hashed, Sourced or Tagged: %s'%find_string) 210 | return False 211 | 212 | def find_sample_meta(find_string): 213 | 214 | conn = sqlite3.connect(option_base_dir + "malwarehouse.db") 215 | c = conn.cursor() 216 | 217 | c.execute("SELECT * FROM malwarehouse_index WHERE metadata LIKE :query", {"query" : '%' + find_string + '%'}) 218 | 219 | data=c.fetchall() 220 | 221 | if data: 222 | print "\nResults for \"" + find_string + "\" in Metadata:\n" 223 | for result in data: 224 | print summary(parse_sqlite_result(result)) 225 | return True 226 | else: 227 | print('No Samples have Metadata matches for: %s'%find_string) 228 | return False 229 | 230 | def find_sample_yara(find_string): 231 | 232 | conn = sqlite3.connect(option_base_dir + "malwarehouse.db") 233 | c = conn.cursor() 234 | 235 | c.execute("SELECT * FROM malwarehouse_index WHERE yara LIKE :query", {"query" : '%' + find_string + '%'}) 236 | 237 | data=c.fetchall() 238 | 239 | 240 | if data: 241 | print"\nResults for \"" + find_string + "\" in Yara Matches:\n" 242 | for result in data: 243 | print summary(parse_sqlite_result(result)) 244 | return True 245 | else: 246 | print('No Samples have yara matches for: %s'%find_string) 247 | return False 248 | 249 | 250 | def recent(quanity='5'): 251 | """Returns a summary of the last n (default: n = 5) pieces of malware.""" 252 | conn = sqlite3.connect(option_base_dir + "malwarehouse.db") 253 | c = conn.cursor() 254 | 255 | try: 256 | float(quanity) 257 | except: 258 | raise ValueError 259 | 260 | c.execute("SELECT DISTINCT * FROM malwarehouse_index ORDER BY datetime DESC LIMIT %s;" % quanity) 261 | data = c.fetchall() 262 | 263 | print "\n%s Most Recent Samples:" % quanity 264 | for result in data: 265 | print summary(parse_sqlite_result(result)) 266 | 267 | return True 268 | 269 | def basic_analyzer(malware_path, source, tags, notes): 270 | """Basic analyzer does the initial triage analysis getting size & hashes along with user supplied data. Returns a dictionary with info.""" 271 | 272 | try: 273 | with open(malware_path) as f: pass 274 | except IOError as e: 275 | print "You specified an invalid malware target path." 276 | exit(0) 277 | return False 278 | 279 | malware_definition = {} 280 | 281 | #Parsing Custom Options 282 | malware_definition["source"] = source 283 | malware_definition["tags"] = tags 284 | malware_definition["notes"] = notes 285 | 286 | #Parsing Automatically Generated Options 287 | malware_definition["name"] = malware_path.split('/')[-1] 288 | malware_definition["datetime"] = str(datetime.datetime.now()) 289 | malware_definition["size"] = os.stat(malware_path).st_size 290 | malware_definition["md5"] = get_md5(malware_path) 291 | malware_definition["ssdeep"] = get_ssdeep(malware_path) if config.get('options', 'ssdeep') == 'On' else 'Disabled' 292 | malware_definition["yara"] = yara_scan(malware_path) if config.get('options', 'yara') == 'On' else 'Disabled' 293 | malware_definition["sha256"] = get_sha256(malware_path) 294 | malware_definition["mimetype"] = get_mime_type(malware_path) 295 | malware_definition["vtapi"] = vtapi(malware_definition["md5"]) if config.get('options', 'vtcheck') == 'On' else 'Disabled' 296 | malware_definition["metadata"] = get_metadata(malware_path) if config.get('options', 'metadata') == 'On' else 'Disabled' 297 | 298 | return malware_definition 299 | 300 | def main(): 301 | if not check_prelim(): 302 | print "[ERROR] Initial setup unable to complete. Exiting..." 303 | return False 304 | 305 | parser = OptionParser(usage="usage: %prog [options] filepath", version="%prog 0.1") 306 | parser.add_option("-s", "--source", 307 | action="store", 308 | type="string", 309 | dest="SOURCE", 310 | default=None, 311 | help="Source of file") 312 | parser.add_option("-t", "--tags", 313 | action="store", 314 | type="string", 315 | dest="TAGS", 316 | default="No tags", 317 | help="Any characteristics of the malware") 318 | parser.add_option("-n", "--notes", 319 | action="store", 320 | type="string", 321 | dest="NOTES", 322 | default="", 323 | help="Notes about file") 324 | parser.add_option("-f", "--find", 325 | action="store", 326 | type="string", 327 | dest="FIND", 328 | default="", 329 | help="Find a sample by name, tags, source, md5, or sha256") 330 | parser.add_option("-m", "--metadata", 331 | action="store", 332 | type="string", 333 | dest="MFIND", 334 | default="", 335 | help="Find a sample by searching Extracted Metadata") 336 | parser.add_option("-y", "--yara", 337 | action="store", 338 | type="string", 339 | dest="YFIND", 340 | default="", 341 | help="Find a sample by searching Yara Matches") 342 | parser.add_option("-r", "--recent", 343 | action="store", 344 | type="string", 345 | dest="QUANTITY", 346 | default="", 347 | help="Find the most recent # samples") 348 | 349 | (options, args) = parser.parse_args() 350 | 351 | if options.QUANTITY: 352 | if recent(options.QUANTITY): 353 | return True 354 | else: 355 | return False 356 | elif options.FIND: 357 | if find_sample(options.FIND): 358 | return True 359 | else: 360 | return False 361 | elif options.MFIND: 362 | if find_sample_meta(options.MFIND): 363 | return True 364 | else: 365 | return False 366 | elif options.YFIND: 367 | if find_sample_yara(options.YFIND): 368 | return True 369 | else: 370 | return False 371 | elif len(args) != 1 and not options.FIND and not options.MFIND and not options.YFIND: 372 | parser.error("You didn't specify a malware target path.") 373 | return False 374 | else: 375 | #Parse malware file path and name 376 | malware_path = args[0] 377 | 378 | malware_definition = basic_analyzer(malware_path, options.SOURCE, options.TAGS, options.NOTES) 379 | 380 | print "Analysis complete. Loading." 381 | malware_loader(malware_definition, malware_path) 382 | 383 | return True 384 | 385 | if __name__ == "__main__": 386 | try: 387 | main() 388 | except KeyboardInterrupt: 389 | print "User aborted." 390 | except SystemExit: 391 | pass 392 | #except: 393 | #SystemExit 394 | 395 | -------------------------------------------------------------------------------- /yararules/yararules.yar: -------------------------------------------------------------------------------- 1 | rule Clear_Executable 2 | { 3 | meta: 4 | description = "Identifies basic MZ header strings" 5 | thread_level = 3 6 | in_the_wild = true 7 | strings: 8 | $1 = "MZ" 9 | $2 = "This program cannot" 10 | $3 = "PE" 11 | condition: 12 | ($1 and $2) or ($2 and $3) 13 | } 14 | 15 | rule MetaData_Author_OracleReports_Test 16 | { 17 | meta: 18 | description = "This is just an example" 19 | thread_level = 3 20 | in_the_wild = true 21 | 22 | strings: 23 | $a = "'PDF:Author': u'Oracle Reports'" nocase 24 | 25 | condition: 26 | $a 27 | } 28 | 29 | rule Insidefile_String_Test 30 | { 31 | meta: 32 | description = "This is an example" 33 | thread_level = 3 34 | in_the_wild = true 35 | 36 | strings: 37 | $a = "xenophon" nocase 38 | 39 | condition: 40 | $a 41 | } 42 | --------------------------------------------------------------------------------