def packer_mpress(filepath): ''' Mpress packs the file in place and it might fail, so we need to compare the hash before and after. ''' try: random_options = ['-q', '-q -m', '-q -r', '-q -s', '-q -m'] selected_option = random_options[random.randint( 0, len(random_options))] orig_hashes = utils.get_hashes(filepath=filepath) orig_hash = orig_hashes.get('md5', '') print("\nORIGINAL HASH: {}".format(orig_hash)) print(orig_hashes) proc1 = subprocess.Popen(r"C:\packers\mpress\mpress.exe {} {}".format( selected_option, filepath)) time.sleep(15.0) # Clean up proc1.kill() time.sleep(1.0) new_hashes = utils.get_hashes(filepath=filepath) new_hash = new_hashes.get('md5', '') print("NEW HASH: {}".format(new_hash)) print(new_hashes) # They are both valid MD5 values, but not equal if len(orig_hash) == 32 and len( new_hash) == 32 and orig_hash != new_hash: return filepath return '' except Exception as e: return ''
def packer_pecompact(filepath): ''' PECompact packs the file in place and it might fail, so we need to compare the hash before and after. ''' try: options = '' for option in [ '/StripDebug', '/MultiCompress', '/TruncateLastSection', '/StripFixups', '/MergeSections', '/KeepOverlay', '/EnforceMemoryProtection', '/CompressResources' ]: if random.randint(0, 1): options = '{} {}'.format(options, option) orig_hashes = utils.get_hashes(filepath=filepath) orig_hash = orig_hashes.get('md5', '') print("\nORIGINAL HASH: {}".format(orig_hash)) print(orig_hashes) proc1 = subprocess.Popen( r"C:\packers\PECompact\pec2.exe {} /Quiet {}".format( filepath, options)) time.sleep(15.0) # Clean up proc1.kill() time.sleep(1.0) new_hashes = utils.get_hashes(filepath=filepath) new_hash = new_hashes.get('md5', '') print("NEW HASH: {}".format(new_hash)) print(new_hashes) # They are both valid MD5 values, but not equal if len(orig_hash) == 32 and len( new_hash) == 32 and orig_hash != new_hash: return filepath return '' except Exception as e: return ''
def packer_mew(filepath): ''' Mew packs the file in place and it might fail, so we need to compare the hash before and after. ''' try: # Save current working directory cwd = os.getcwd() # Change dir to temp os.chdir(os.path.dirname(filepath)) shutil.copyfile("C:\\packers\\MEW\\mew11.exe", os.path.join(os.path.dirname(filepath), "mew11.exe")) orig_hashes = utils.get_hashes(filepath=filepath) orig_hash = orig_hashes.get('md5', '') print("\nORIGINAL HASH: {}".format(orig_hash)) proc1 = subprocess.Popen(r"mew11.exe {}".format( os.path.basename(filepath))) time.sleep(15.0) proc1.kill() time.sleep(1.0) new_hashes = utils.get_hashes(filepath=filepath) os.chdir(cwd) new_hash = new_hashes.get('md5', '') print("NEW HASH: {}".format(new_hash)) # They are both valid MD5 values, but not equal if len(orig_hash) == 32 and len( new_hash) == 32 and orig_hash != new_hash: return filepath return '' except Exception as e: os.chdir(cwd) return ''
def analyze_file(prepared_input): combined_results = {} filepath = prepared_input['filepath'] yara_rules = prepared_input.get('yara_rules', None) full_details = prepared_input.get('full_details', False) temp_path = prepared_input.get('temp_path', './temp') label = prepared_input.get('label', 'n/a') individual_results = [{'filename': filepath, 'label': label}] is_gz = False if filepath.endswith('.gz'): is_gz = True temp_path_this_file = os.path.join(temp_path, os.path.basename(filepath)) os.makedirs(temp_path_this_file, exist_ok=True) temp_name = os.path.join( temp_path_this_file, '{}.decompressed'.format(os.path.basename(filepath))) utils.decompress_file(filepath, temp_name) filepath = temp_name # Hashes / Strings try: individual_results.append(utils.get_strings(filepath=filepath)) individual_results.append(utils.get_hashes(filepath=filepath)) individual_results.append(utils.get_type(filepath=filepath)) except Exception as e: individual_results.append({ 'msg_basic_file_analysis': 'Basic file analysis error: {}'.format(e) }) # EXIF try: exif_instance = exif.Exif_Engine() exif_results = exif_instance.analyze(filepath) exif_results_renamed = { 'exif_{}'.format(key): value for key, value in exif_results.items() } individual_results.append(exif_results_renamed) except Exception as e: individual_results.append( {'msg_exif': 'Exif result error: {}'.format(e)}) # PE try: pe_analyzer = pe_analysis.PEFile(filepath) pe_analyzer.analyze() pe_results = pe_analyzer.summarize_results() pe_results_renamed = { 'pe_{}'.format(key): value for key, value in pe_results.items() } individual_results.append(pe_results_renamed) except Exception as e: individual_results.append( {'msg_pe': 'PE analysis result error: {}'.format(e)}) # Yara try: if yara_rules is not None: yara_analyzer = yara_engine.Yara_Engine(yara_rules) yara_result = yara_analyzer.analyze(filepath) yara_result_renamed = { 'yara_{}'.format(key): value for key, value in yara_result.items() } individual_results.append(yara_result_renamed) except Exception as e: individual_results.append( {'msg_yara': 'Yara result error: {}'.format(e)}) for individual_result in individual_results: combined_results.update(individual_result) # Clean up if is_gz: try: shutil.rmtree(temp_path_this_file) except Exception as e: print("Error removing temp directory: {}".format(e)) return combined_results
def process_file(input_file): orig_filepath = input_file.get('filepath', 'none') output_dir = input_file.get('output_dir', 'none') temp_dir = input_file.get('temp_dir', 'none') packer = input_file.get('packer', 'none') result = input_file input_file_temp_dir = 'none' try: if not os.path.exists(orig_filepath): result['status'] = 'Input file did not exist' return result # Ensure our directories exist base_filename = os.path.basename(orig_filepath) input_file_temp_dir = os.path.join(temp_dir, base_filename) os.makedirs(input_file_temp_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True) temp_filepath = os.path.join(input_file_temp_dir, base_filename) # We either copy the file or unzip it if orig_filepath.endswith('.gz'): temp_filepath = temp_filepath[:-3] utils.decompress_file(orig_filepath, temp_filepath) else: shutil.copy(orig_filepath, temp_filepath) hashes = utils.get_hashes(filepath=temp_filepath) orig_hashes = { 'orig_{}'.format(key): value for key, value in hashes.items() } result.update(orig_hashes) # Call packing routine packed_filepath = pack_file(temp_filepath, packer) if packed_filepath != '': hashes = utils.get_hashes(filepath=packed_filepath) packed_hashes = { 'packed_{}'.format(key): value for key, value in hashes.items() } result.update(packed_hashes) new_packed_filename = '{}.gz'.format(hashes.get('sha256', 'error')) new_packed_filepath = os.path.join(output_dir, new_packed_filename) utils.compress_file(packed_filepath, new_packed_filepath) else: result['status'] = 'Failed to pack file: {}'.format(temp_filepath) shutil.rmtree(input_file_temp_dir, ignore_errors=True, onerror=None) return result # Destroy temporary space shutil.rmtree(input_file_temp_dir, ignore_errors=True, onerror=None) result['status'] = 'Success' # Some packers are creating .tmp files (e.g. MEW and PECompact) # Let's remove them to not fill disk try: temp_files = [ str(filename) for filename in Path(os.getenv("TEMP")).glob('*.tmp*') ] now = calendar.timegm(time.gmtime()) for filename in temp_files: filetime = os.path.getctime(filename) # delete temp files more than a minute old if now - filetime > 60: os.remove(filename) except: pass except Exception as e: result['status'] = 'Unrecoverable error: {}'.format(e) if input_file_temp_dir != 'none': shutil.rmtree(input_file_temp_dir, ignore_errors=True, onerror=None) return result return result