导航菜单

01前言

x64dbg工具的更新速度很活跃,经过几年使用人数已经很高了。刚上手觉得它很多和OD比较类似,不过它的在线文档确比较“专家化”,因此碰到一些问题也经常需要在Github上向开发者提问了解。
作为动态调试工具,它本身也支持脚本功能,不过支持高级语言才是效率工具,它通过x64dbgpy插件支持python脚本;本文内不涉及python语法。

02安装

1, 插件仓库地址:https://github.C++om/x64dbg/x64dbgpy
2, 安装信息仓库Wiki说明也给的比较清楚,包含三部分:

  • x64dbg 插件文件:x64dbgpy.dp64, x64dbgpy.dp32文件
  • SDK : x64dbgpy 库文件,包含Python相关的API。
  • Python依赖和系统依赖。
    完成安装后,从x64dbg的菜单下就能看到插件了: "插件"->"x64dbgpy"

03脚本开发

作为样例,主要解析x64dbgpy的SDK内容和API使用。本例使用场景:对sourceinsight4进行自动化Patch生成。

03.1 SDK目录安装:

SDK主要需要被脚本引用,需要安装到:
1, x64dbg的plugins目录;
2, 方便IDE能进行语法提示,在自己创建的项目目录下或者Python的site-packages目录;

03.2 SDK的API能力:

SDK包含有源码,所以不会细讲每个API,从目录结果上就可以看到它的API定义和分类:
1,全局API调用入口:x64dbg.py的定义,通过它可以引用全部API内容。
2,对子模块的API也可以直接引用调用,子模块有:symbol, stack, register, pattern...等。
x64dbgpy插件使用与Python代码样例

03.3SDK的几个API说明:

从支持能力上,x64dbgpy应该在高级语言环境支持所有x64dbg的命令功能调用,事实也确实这样,一部分API被开发者显示的封闭成API,有一部分可扩展的API:
1, x64dbg.DbgValFromStRing(cmd) : 执行x64dbg命令集,并返回执行结果。如果看名称很容易被x64dbg.DbgEval给带偏了。
2, memory.Write():这个内存写操作的改变,x64dbg并不生成patch信息。
3, 可以再补充。

03.4整理场景功能编写:

从功能需要分为几部分:
1,定位需要patch的模块在内存中的位置。
相关API:

  • module.GetMainModuleName() : 获取主模块信息。
  • module.GetMainModuleSectionList() :获取主模块的分段信息。
    2,Patch特征查找和生成对应的Patch结果;
  • pattern.FindMem : 内存特征匹配,不使用pattern.SearchAndReplace是因为它不产生patch信息。
    3,生成Patch文件。
  • 比较容易,主要是根据patch点的信息,只在成x64dbg支持的patch文件。其中x64dbg中的patch模式为:rva: <raw byte data>-><patch byte data>
    具体代码如下:

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] %sn' % (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('>%sn' % self.module_file)
for patch_it in self.patch_dict[self.module_file].keys():
patch_file.write('%08X:%X->%Xn' % (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"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoaA07NVkldoVZmPD8foIn"
"Q4ffxG9nMvmMiN2i0cd0+Rf6Uo2Z6JIuFseTFCoCwI62JseM247ckW5HHfeE1inEn"
"4Uqgq3oxdnxqImMrHeEzQ0u4UBXsVAacNl2ozwVfZqoTwkn+Uw096w1k/3Mj2PHJn"
"PSHTP8D9QzuYn6X52po27Vzs82hpumiahiDxE48cxYcHJWuQpqmaCRpNrN+PyJtkn"
"vwqHa/zRB4/MwbtxltXlC/1ozbPuhNX91C3vw6mrcKaTVr8zNq4yy82prlwgksbAn"
"s7+AeF30mGbRM+mWf+FmwL1wmaEEa4QbjWdsnHz0xiPa/MbbgN6L6mrIJ3nQoqXKn"
"vQIDAQABn-----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)

03.5 脚本加载:

先通过x32dbg加载sourceinsigt4.exe:
x64dbgpy插件使用与Python代码样例
加载脚本&运行:
x64dbgpy插件使用与Python代码样例

相关推荐

隐藏在Chrome中的窃密者

  简介 CVE-2019-5826是Google C++hrome里IndexedDB中的Use-after-free漏洞,在版本73.0.3683.86之前该漏洞允许攻击者通过搭配render的RCE漏洞来造成UAF并沙箱逃逸。   一、环境搭建 笔者所使用的chrom...

CVE-2020-24407/24400:Adobe Magento 远程代码执行漏洞通告

  0x01 漏洞简述 2020年10月19日,360C++ERT监测发现 Adobe 发布了 Magento Commerce/Open Source 代码执行漏洞 的风险通告,该漏洞编号为 CVE-2020-24407 & CVE-2020-24400 ,漏洞等级: 高危 ,漏洞评...