#!/usr/bin/python

'''
exefinder - Version 1.2 (2013-03-04).
Latest version at http://www.itsec.se

A utility for finding executable files based on their file signatures
(magic number), rather than their filename extension. Also able to detect
file extension missrepresentation (file camouflaging). Other file formats
are also supported, despite it's name (e.g. swf, jar, class). 

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the named License,
or any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

Copyright (C) 2013 by Gustav Nordenskjold, Sweden.
'''

import os, sys, datetime

JPG = ['ffd8', '4a464946', '45786966'] # JFIF/Exif
PNG = ['89504e470d0a1a0a'] # \211 P N G \r \n \032 \n 
GIF = ['474946383961', '474946383761'] # GIF89a/GIF87a
IMG_EXT = ['jpg', 'jpeg', 'png', 'gif']

SWF = ['435753', '465753'] # CWS / FWS
SWF_EXT =  ['swf']

JAVA = ['504B0304140008000800', 'cafebabe', 'cafed00d'] # JAR / CLASS
JAVA_EXT = ['jar', 'class']

EXE = ['4d5a', '5a4d'] # MZ/ZM
EXE_EXT = ['cpl', 'exe', 'dll', 'ocx', 'sys', 'scr', 'drv']

def usage():
	print 'Usage: python ' + sys.argv[0] + ' [-p path] [-t type] [-c] [-v] [-h]'
	print '-p path\t\tPath to include in file search.'
	print '-t type\t\tType of file. Options are EXE (default), SWF, JAVA and IMG.'
	print '-c\t\tDetect if file extensions does not match (file camouflaging).'
	print '-v\t\tVerbose output (includes MAC times).'
	print '-h\t\tThis help text.'
	print ''
	

if __name__ == '__main__':

	print 'exefinder - find files based on their file signatures'
	print 'Version 1.2 (2013-03-04). Latest version at http://www.itsec.se'
	print ''
	
	if len(sys.argv) < 2:
		usage()
		sys.exit(0)
	
	TYPE = EXE
	EXT = EXE_EXT
	VERIFY_EXT = False
	VERBOSE = False
	ROOT = ''
	
	for i in range(len(sys.argv)):
		if sys.argv[i][:2] == '-t':			
			if sys.argv[i+1] == 'EXE':
				TYPE = TYPE + EXE
				EXT = EXE_EXT
				print 'Searching for executable files.'
				print ''
			elif sys.argv[i+1] == 'IMG':
				TYPE = JPG + PNG + GIF
				EXT = IMG_EXT
				print 'Searching for image files (jpg, png, gif).'
				print ''
			elif sys.argv[i+1] == 'JAVA':
				TYPE = JAVA
				EXT = JAVA_EXT
				print 'Searching for java files, common targets for malware (jar, class).'
				print ''
			elif sys.argv[i+1] == 'SWF':
				TYPE = SWF
				EXT = SWF_EXT
				print 'Searching for flash files, common targets for malware (swf).'
				print ''
			else:
				print 'Setup Error: Filetype not recognized/supported (' + sys.argv[i+1] + ').'
				print ''
				print 'Run "python ' + sys.argv[0] + ' -h" for more information.'
				sys.exit(0)
		elif sys.argv[i][:2] == '-p':
			ROOT = sys.argv[i+1]
		elif sys.argv[i][:2] == '-v':
			VERBOSE = True
		elif sys.argv[i][:2] == '-c':
			VERIFY_EXT = True
		elif sys.argv[i][:2] == '-h':
			usage()
			sys.exit(0)
		
	if not ROOT:
		print 'Setup Error: Path not specified.'
		sys.exit(0)

	print "Filename, Path",
	
	if VERBOSE:
		print ", Modification time (mtime), Access time (atime), Change time / creation time (ctime)",

	if VERIFY_EXT: 
		print ", File camouflaging",
				
	print ''
					
	for dirpath, dirnames, filenames in os.walk(ROOT):
		for filename in filenames:
			try:
				filepath = os.path.join(dirpath, filename)
				with open(filepath,'r') as file:
					magic = file.read(12)
				
				#print filepath 
				for type in TYPE:
					if  magic.encode('hex').lower().startswith(type):
						print filename + " , " + filepath, 
						
						if VERBOSE:
							m = datetime.datetime.fromtimestamp(os.path.getmtime( filepath ))
							a = datetime.datetime.fromtimestamp(os.path.getatime( filepath ))
							c = datetime.datetime.fromtimestamp(os.path.getctime( filepath ))
							print ", " + str(m) + ", " + str(a) + ", " + str(c), 
						
						if VERIFY_EXT:
							if filename.split(".")[-1].strip().lower() not in EXT:
								print ", Possible file camouflaging",
							else:
								print ", - ",
						
						print ''
			
			except IOError as e:
				print 'IOError: Please make sure you have sufficient privilages to read file "' + filepath + '".',
				if VERBOSE:
					print str(e),
				print ''
			except Exception as e:
				print ''
				print 'Exception: ' + str(e)
				sys.exit(0)


