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:
先通过x32dbg加载sourceinsigt4.exe:
加载脚本&运行:
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)
[注意]APP应用上架合规检测服务,协助应用顺利上架!
最后于 2020-6-8 11:49
被nevinhappy编辑
,原因: