x64dbg工具的更新速度很活跃,经过几年使用人数已经很高了。刚上手觉得它很多和OD比较类似,不过它的在线文档确比较“专家化”,因此碰到一些问题也经常需要在github上向开发者提问了解。
作为动态调试工具,它本身也支持脚本功能,不过支持高级语言才是效率工具,它通过x64dbgpy插件支持python脚本;本文内不涉及python语法。
1, 插件仓库地址:https://github.com/x64dbg/x64dbgpy
2, 安装信息仓库Wiki说明也给的比较清楚,包含三部分:
作为样例,主要解析x64dbgpy的SDK内容和API使用。本例使用场景:对sourceinsight4进行自动化Patch生成。
SDK主要需要被脚本引用,需要安装到:
1, x64dbg的plugins目录;
2, 方便IDE能进行语法提示,在自己创建的项目目录下或者Python的site-packages目录;
SDK包含有源码,所以不会细讲每个API,从目录结果上就可以看到它的API定义和分类:
1,全局API调用入口:x64dbg.py的定义,通过它可以引用全部API内容。
2,对子模块的API也可以直接引用调用,子模块有:symbol, stack, register, pattern...等。
从支持能力上,x64dbgpy应该在高级语言环境支持所有x64dbg的命令功能调用,事实也确实这样,一部分API被开发者显示的封闭成API,有一部分可扩展的API:
1, x64dbg.DbgValFromString(cmd) : 执行x64dbg命令集,并返回执行结果。如果看名称很容易被x64dbg.DbgEval给带偏了。
2, memory.Write():这个内存写操作的改变,x64dbg并不生成patch信息。
3, 可以再补充。
从功能需要分为几部分:
1,定位需要patch的模块在内存中的位置。
相关API:
from x64dbgpy.pluginsdk import * #-*--------------------------------------------------------------------------------------------- #-* VERIFY: #-* Tested under sourceinsight4 114, 115 version . #-@--------------------------------------------------------------------------------------------- class X64dbgLog(object): Dbg = [0, 'Debug'] Warn = [1, 'Warn'] Info = [2, 'Info'] Err = [3, 'Error'] Crital = [4, 'Critical'] LogLevel = Info @staticmethod def logger(msg, level=Info): if level[0] >= X64dbgLog.LogLevel[0]: x64dbg.GuiAddLogMessage('### [%s] %s\n' % (level[1], msg)) pass def str_2_hex_pattern_str(str): return ' '.join([hex(ord(c))[-2:] for c in str]) class PEPatcher(object): def __init__(self, text_patchs, public_key=None): self.patch_patterns = text_patchs self.public_key = public_key self.module_file = module.GetMainModuleName() self.module_sections = module.GetMainModuleSectionList() self.patch_dict = {self.module_file: {}} for mod_it in self.module_sections: X64dbgLog.logger("sect %s,: (0x%X, 0x%X)" % (mod_it.name, mod_it.addr, mod_it.size)) if mod_it.name == '.data': self.data_addr = mod_it.addr self.data_size = memory.GetSize(mod_it.addr, False, False) elif mod_it.name == '.text': self.text_addr = mod_it.addr self.text_size = memory.GetSize(mod_it.addr, False, False) pass def get_text_segment_patch(self): for pt_it in self.patch_patterns.keys(): match_count = 0 search_addr = self.text_addr search_size = self.text_size while True: find_ret = pattern.FindMem(search_addr, search_size, pt_it) if find_ret == 0: if match_count == 0: X64dbgLog.logger("Can't find pattern : %s \n" % pt_it, X64dbgLog.Err) exit(-1) else: break # the last point is get , stop search find_ret_rva = x64dbg.DbgValFromString( 'mod.rva(0x%X)' % (find_ret + self.patch_patterns[pt_it][0])) find_byte = memory.ReadByte(find_ret + self.patch_patterns[pt_it][0]) self.patch_dict[self.module_file][find_ret_rva] = ( find_byte, self.patch_patterns[pt_it][1]) X64dbgLog.logger(" ** Find pattern ( 0x%X #0x%X) 0x%02X -> 0x%02X :%s " % (find_ret, find_ret_rva, find_byte, self.patch_patterns[pt_it][1], pt_it)) # support multi-points of patch . search_addr = find_ret + 1 search_size = self.text_size - (search_addr - self.text_addr) match_count += 1 pass def get_data_segment_patch(self): if self.public_key is None: return public_key_pattern = '-----BEGIN PUBLIC KEY-----' ret = pattern.FindMem(self.data_addr, self.data_size, str_2_hex_pattern_str(public_key_pattern)) if ret == 0: X64dbgLog.logger("Can't find public key !!!") exit(0) X64dbgLog.logger("Find public key in : 0x%X !!!" % ret) patch_addr = ret + len(public_key_pattern) for char_it in self.public_key[len(public_key_pattern):]: tmp_byte = memory.ReadByte(patch_addr) if tmp_byte != ord(char_it): find_ret_rva = x64dbg.DbgValFromString('mod.rva(0x%X)' % patch_addr) self.patch_dict[self.module_file][find_ret_rva] = (tmp_byte, ord(char_it)) X64dbgLog.logger("Patch [0x%X #0x%X]: 0x%02X -> 0x%02X" % (patch_addr, find_ret_rva, tmp_byte, ord(char_it)), X64dbgLog.Dbg) patch_addr += 1 pass def gen_x64dbg_patch_file(self, patch_file='./gen-patch.1337'): try: patch_file = open(patch_file, 'w') patch_file.write('>%s\n' % self.module_file) for patch_it in self.patch_dict[self.module_file].keys(): patch_file.write('%08X:%X->%X\n' % (patch_it, self.patch_dict[self.module_file][patch_it][0], self.patch_dict[self.module_file][patch_it][1])) patch_file.close() except IOError as e: X64dbgLog.logger(' Failed to write patch file : %s, Exit.' % patch_file, X64dbgLog.Err) exit(-1) if __name__ == "__main__": patch_patterns = { "3D 70 17 00 00 ?? 75": [5, 0xEB], "?? C0 75 1D 8B 86 C4 0D": [0, 0x31], "?? C0 74 1E C7 84 24 28 04": [0, 0x31], "?? C0 74 47 8B CE E8 C7 E3 FF": [0, 0x31], # New patch point to bypass signature checking. "83 C4 0C ?? C8 00 00 00 0F 85": [3, 0xB8] } patch_pub_key = "-----BEGIN PUBLIC KEY-----\n" \ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoaA07NVkldoVZmPD8foI\n" \ "Q4ffxG9nMvmMiN2i0cd0+Rf6Uo2Z6JIuFseTFCoCwI62JseM247ckW5HHfeE1inE\n" \ "4Uqgq3oxdnxqImMrHeEzQ0u4UBXsVAacNl2ozwVfZqoTwkn+Uw096w1k/3Mj2PHJ\n" \ "PSHTP8D9QzuYn6X52po27Vzs82hpumiahiDxE48cxYcHJWuQpqmaCRpNrN+PyJtk\n" \ "vwqHa/zRB4/MwbtxltXlC/1ozbPuhNX91C3vw6mrcKaTVr8zNq4yy82prlwgksbA\n" \ "s7+AeF30mGbRM+mWf+FmwL1wmaEEa4QbjWdsnHz0xiPa/MbbgN6L6mrIJ3nQoqXK\n" \ "vQIDAQAB\n-----END PUBLIC KEY-----\n" X64dbgLog.logger("** Strat to run python script : ") source_insight4_patcher = PEPatcher(patch_patterns) # source_insight4_patcher = PEPatcher(patch_patterns, patch_pub_key) source_insight4_patcher.get_text_segment_patch() source_insight4_patcher.get_data_segment_patch() source_insight4_patcher.gen_x64dbg_patch_file() # show hints X64dbgLog.logger("Patch file gen-patch.1337 is generated ! Please fix %s manually !!!" % source_insight4_patcher.module_file) gui.Message("Patch file gen-patch.1337 is generated ! Please fix %s manually !!!" % source_insight4_patcher.module_file)
先通过x32dbg加载sourceinsigt4.exe:
加载脚本&运行:
[培训]科锐逆向工程师培训(6月24日远程教学开班, 第38期)!
最后于 12小时前 被nevinhappy编辑 ,原因: