网易首页 > 网易号 > 正文 申请入驻

使用 Python 扩展 IDA 的功能:反汇编 Xtensa 指令的实际示例

0
分享至

在逆向工程过程中,您可能会遇到可用工具尚不支持您正在使用的架构的情况。

在本文中,我们将探讨这样的案例并展示扩展 IDA 功能的示例。我们探索如何实现 IDA 插件来反汇编新的 Xtensa 指令。

在我们之前的一篇文章中,我们讨论了研究固件架构的重要性。在这种情况下,我们设法找到了一个支持我们需要分析的设备架构的反汇编工具。现在,我们想要解决逆向工程工具不支持您在项目中使用的架构的问题。让我们以 IDA 为例来探讨本文。

交互式反汇编器 (IDA)是一种软件反汇编器,可从机器可执行代码生成汇编语言源代码并执行自动代码分析。该逆向工程工具通过众多插件提供广泛的反汇编和调试功能。

IDA 还使用一组称为处理器模块的插件将原始字节代码转换为反汇编文本。每个插件都是针对特定的硬件架构设计的。

由于反汇编插件的可用性很大程度上取决于架构的流行程度,因此某些处理器模块的更新频率比其他模块要高。而对新指令的支持可能需要 IDA 开发人员花一些时间才能实现。

那么,如果您当前正在使用的架构没有插件,您该怎么办?

好消息是,无需等待 IDA 开发人员实现对特定指令集的支持。您可以自己创建自定义 IDA 插件,也可以使用 Python 通过 IDA SDK 实现相关插件。
让我们探讨一个实现逆向工程 IDA 插件的示例,并使用新的 Xtensa 架构指令,在撰写本文时,IDA 7.7 尚不支持这些指令。由于这些指令未在 IDA 中反汇编,因此您将它们视为原始字节:

屏幕截图 1. Xtensa 指令在 IDA 中显示为原始字节

但如果您使用其他支持反汇编新Xtensa指令的软件,例如Lauterbach Trace32模拟器,您可以看到这些字节是商无符号(QUOU)指令:

屏幕截图 2.Xtensa 指令看起来像 Lauterbach Trace32 模拟器中的 QUOU 指令

一旦知道这些字节是什么,您就可以找到 QUOU 指令的描述并实现 IDA 插件来扩展现有处理器模块的功能。让我们探讨一下如何做到这一点。

让我们使用NECromancer插件,它为 NEC V850 CPU 扩展了 IDA 的处理器模块。

使用此插件的目标是挂钩处理器模块的事件处理程序并执行您自己的处理例程而不是现有的处理例程。该插件将允许处理器模块处理默认情况下无法处理的未知指令。

让我们看一下一个空插件。以下是在 IDA 引擎中注册插件并挂接处理器模块所需的最少代码:

(Python)

class XtensaESP(plugin_t): flags = PLUGIN_PROC | PLUGIN_HIDE comment = "" wanted_hotkey = "" help = "Adds support for additional Xtensa instructions" wanted_name = "XtensaESP" def __init__(self): self.prochook = None def init(self): if ph_get_id() != PLFM_XTENSA: return PLUGIN_SKIP self.prochook = xtensa_idp_hook_t() self.prochook.hook() print ("%s initialized." % XtensaESP.wanted_name) return PLUGIN_KEEP def run(self, arg): pass def term(self): if self.prochook: self.prochook.unhook() #--------------------------------------------------------------------------def PLUGIN_ENTRY(): return XtensaESP()


为了确保 IDA 仅在加载 Xtensa CPU 处理器模块时运行该插件,该插件会执行以下检查:

if ph_get_id() != PLFM_XTENSA


NECromancer 插件还需要xtensa_idp_hook_t挂钩类来安装处理器模块事件的处理程序。钩子类主体如下所示:

class xtensa_idp_hook_t(IDP_Hooks): def __init__(self): IDP_Hooks.__init__(self) def ev_ana_insn(self, insn): pass def ev_out_mnem(self, outctx): pass def ev_out_operand(self, outctx, op): pass


该代码片段的关键元素是:

ev_ana_insn方法,帮助您分析字节码并创建指令类

ev_out_mnem方法,允许您创建指令的可视化表示,即生成反汇编文本

ev_out_operand方法,实现指令操作数生成为文本以便反汇编

让我们一一实现这三种方法。

使用 NECromancer 插件的目标是添加对 QUOU(无符号商)指令的支持。这意味着您需要知道 CPU 实际上如何解析表示 QUOU 指令的字节。

您可以在Xtensa 指令集架构 (ISA) 参考手册 [PDF]中找到此信息:

指令词:

所需的配置选项:32 位整数除法选项。

汇编语法:QUOU ar, as, at

说明:将地址寄存器的内容除以地址寄存器的内容QUOU进行 32 位无符号除法,并将商写入地址寄存器。如果地址寄存器的内容引发整数除以零异常而不是写入结果。asatarat0, QUOU

在这种特殊情况下,您不需要详细了解指令的作用。目标是了解 CPU 如何知道一组字节实际上是 QUOU 指令。

IDA 将这条 QUOU 指令显示为字节序列:0xC0, 0x22, 0xC2。指令的第一个字节0xC0——在文档中表示如下:

让我们解释一下这意味着什么:

1、标记为 的顶部四个字节t的值为0xC。

2、低四个字节始终等于0。

3、的值t是用作指令第三个参数的寄存器的索引。

4、0xC = 12,这意味着第三个参数是a12。

指令的第二个字节指定了另外两个标记为r和 的参数s:

在我们的例子中,第二个字节是0x22,这意味着r = 0x2和s = 0x2。因此,第一和第二操作数都是a2。

最后,第三个字节是0xC2。根据文档,它始终是一个常量:

由于1100 0010 = 0xC2,您可以使用该字节来识别 QUOU 指令。

现在,一切准备就绪,可以开始实现ev_ana_insn方法了。

首先,创建新的指令ID,这将允许IDA引擎区分新指令和现有指令:

class NewInstructions: (NN_quou, NN_last) = range(CUSTOM_INSN_ITYPE, CUSTOM_INSN_ITYPE+2)


其次,让我们使用从值开始的 ID CUSTOM_INSN_ITYPE。

最后,运行指令分析方法,如下所示:

def ev_ana_insn(self, insn): buf = get_bytes(insn.ea, 3) if buf[2] == 0xC2 and (buf[0] & 0xF) == 0: insn.itype = NewInstructions.NN_quou insn.size = 3 return True return False


我们来解释一下这段代码的作用:

get_bytes ()函数从 IDA 期望的下一条指令的地址处的二进制文件中读取原始字节。

然后,它检查指令字节是否实际上看起来像 QUOU 指令。

在这种情况下,我们检查第三个字节0xC2和较低的 4 个字节是否0在第一个字节中,如文档中所定义。最后,您需要使用有关 QUOU 指令的信息填充ev_ana_insn方法的insn参数:至少指定指令 ID 和指令大小(以字节为单位)。

然后,如果ev_ana_insn方法能够在建议地址找到指令,则它必须返回True ;否则,它必须返回False。

即使您将努力保持在绝对最低限度(如上所示),IDA 也已经能够识别新指令。但我们还想向您展示如何让 IDA 也了解指令参数,否则指令将显示为没有参数。为此,您需要对ev_ana_insn()方法进行改进:

def ev_ana_insn(self, insn): buf = get_bytes(insn.ea, 3) if buf[2] == 0xC2 and (buf[0] & 0xF) == 0: insn.itype = NewInstructions.NN_quou insn.size = 3 insn.Op1.type = o_reg insn.Op1.reg = buf[1] >> 4 insn.Op2.type = o_reg insn.Op2.reg = buf[1] & 0xF insn.Op3.type = o_reg insn.Op3.reg = buf[0] >> 4 return True return False


这段新代码实现了指令参数的定义。这些是代码从指令字节中提取的r、s和值。

解析完成后,就可以设置反汇编文本的输出了。

要生成反汇编文本,您可以完全重用ev_out_mnem方法的 NECromancer 插件的现有代码:

DEBUG_PLUGIN = True NEWINSN_COLOR = COLOR_MACRO if DEBUG_PLUGIN else COLOR_INSN class NewInstructions: (NN_quou, NN_last) = range(CUSTOM_INSN_ITYPE, CUSTOM_INSN_ITYPE+2) lst = {NN_quou:"quou"} def ev_out_mnem(self, outctx): insntype = outctx.insn.itype global NEWINSN_COLOR if (insntype >= CUSTOM_INSN_ITYPE) and (insntype in NewInstructions.lst): mnem = NewInstructions.lst[insntype] outctx.out_tagon(NEWINSN_COLOR) outctx.out_line(mnem) outctx.out_tagoff(NEWINSN_COLOR) # TODO: how can MNEM_width be determined programmatically? MNEM_WIDTH = 8 width = max(1, MNEM_WIDTH - len(mnem)) outctx.out_line(' ' * width) return True return False


我们来解释一下这个例子的要点:

ev_out_mnem从NewInstructions类获取指令名称并andoutctx.out_line在 IDA 反汇编窗口中显示文本。

标志DEBUG_PLUGIN改变文本的颜色。您可以将其设置为默认颜色或宏的颜色,以使新指令脱颖而出,这在调试插件时非常方便。

ev_out_mnem输出八个空格,为引擎输出指令参数做好准备。因此,所有内容——代码、空格、代码注释——都将被对齐。

要实现指令操作数的生成,您还可以重用ev_out_operand方法的现成代码:

def ev_out_operand(self, outctx, op): insn = outctx.insn if insn.itype in [NewInstructions.NN_ld_hu, NewInstructions.NN_st_h]: if op.type == o_displ: outctx.out_value(op, OOF_ADDR) outctx.out_register(ph_get_regnames()[op.reg]) return True return False


此代码检查该指令是否是您之前添加的指令。如果指令包含参数,则需要打印操作数。然后,您将获得寄存器的名称,插件将打印它。

现在,所有准备工作都已完成,您可以开始测试您创建的插件。

将插件放在 \IDA\plugins目录中,以便 IDA 可以运行它。然后,加载包含未定义字节的IDA数据库,将光标置于其上,然后按C创建指令:

屏幕截图 3. 在 IDA 中创建新的 QUOU 指令

添加对 QUOU 指令的支持后,IDA 每当遇到该指令时都会自动识别该指令。此处指令的颜色与其他指令的颜色不同,因为我们DEBUG_PLUGIN在此示例中启用了该标志。如果您决定禁用该标志,指令的颜色将与代码的其余部分相同。

我们示例的完整 NECromancer 插件源代码如下:

from ida_lines import COLOR_INSN, COLOR_MACRO from ida_idp import CUSTOM_INSN_ITYPE, IDP_Hooks, ph_get_regnames, ph_get_id, PLFM_XTENSAfrom ida_bytes import get_bytesfrom ida_idaapi import plugin_t, PLUGIN_PROC, PLUGIN_HIDE, PLUGIN_SKIP, PLUGIN_KEEPfrom ida_ua import o_displ, o_reg, o_imm, dt_dword, OOF_ADDRfrom struct import unpackDEBUG_PLUGIN = TrueNEWINSN_COLOR = COLOR_MACRO if DEBUG_PLUGIN else COLOR_INSNclass NewInstructions: (NN_quou, NN_muluh) = range(CUSTOM_INSN_ITYPE, CUSTOM_INSN_ITYPE+2) lst = {NN_quou:"quou", NN_muluh:"muluh"}#--------------------------------------------------------------------------class xtensa_idp_hook_t(IDP_Hooks): def __init__(self): IDP_Hooks.__init__(self) def decode_instruction(self, insn): buf = get_bytes(insn.ea, 3) #print("%08X bytes %X %X %X" % (insn.ea , buf[2] , buf[1] , buf[0])) if buf[2] == 0xC2 and (buf[0] & 0xF) == 0: insn.itype = NewInstructions.NN_quou insn.size = 3 insn.Op1.type = o_reg insn.Op1.reg = buf[1] >> 4 insn.Op2.type = o_reg insn.Op2.reg = buf[1] & 0xF insn.Op3.type = o_reg insn.Op3.reg = buf[0] >> 4 return True if buf[2] == 0xA2 and (buf[0] & 0xF) == 0: insn.itype = NewInstructions.NN_muluh insn.size = 3 insn.Op1.type = o_reg insn.Op1.reg = buf[1] >> 4 insn.Op2.type = o_reg insn.Op2.reg = buf[1] & 0xF insn.Op3.type = o_reg insn.Op3.reg = buf[0] >> 4 return True return False def ev_ana_insn(self, insn): return self.decode_instruction(insn) def ev_out_mnem(self, outctx): insntype = outctx.insn.itype global NEWINSN_COLOR if (insntype >= CUSTOM_INSN_ITYPE) and (insntype in NewInstructions.lst): mnem = NewInstructions.lst[insntype] outctx.out_tagon(NEWINSN_COLOR) outctx.out_line(mnem) outctx.out_tagoff(NEWINSN_COLOR) # TODO: how can MNEM_width be determined programmatically? MNEM_WIDTH = 8 width = max(1, MNEM_WIDTH - len(mnem)) outctx.out_line(' ' * width) return True return False def ev_out_operand(self, outctx, op): insn = outctx.insn if insn.itype in [NewInstructions.NN_ld_hu, NewInstructions.NN_st_h]: if op.type == o_displ: outctx.out_value(op, OOF_ADDR) outctx.out_register(ph_get_regnames()[op.reg]) return True return False#--------------------------------------------------------------------------class XtensaESP(plugin_t): flags = PLUGIN_PROC | PLUGIN_HIDE comment = "" wanted_hotkey = "" help = "Adds support for additional Xtensa instructions" wanted_name = "XtensaESP" def __init__(self): self.prochook = None def init(self): if ph_get_id() != PLFM_XTENSA: return PLUGIN_SKIP self.prochook = xtensa_idp_hook_t() self.prochook.hook() print ("%s initialized." % XtensaESP.wanted_name) return PLUGIN_KEEP def run(self, arg): pass def term(self): if self.prochook: self.prochook.unhook()#--------------------------------------------------------------------------def PLUGIN_ENTRY(): return XtensaESP()


这就是使用 Python 实现 IDA 插件的方法。现在您已经知道了:IDA 能够反汇编新的 Xtensa 指令。

尽管 IDA 等工具支持大多数流行的架构,但了解如何扩展逆向工程工具的功能将增加您的机会。这些知识还将在您使用新架构和解决重要任务时提供帮助。

参考及来源:https://www.apriorit.com/dev-blog/reverse-extend-ida-capabilities-with-python

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
不是拜合拉木!36强赛国足最大“惊喜”出炉,成范志毅郑智后首人

不是拜合拉木!36强赛国足最大“惊喜”出炉,成范志毅郑智后首人

林子说事
2024-06-16 09:09:19
过“紧日子”的地方政府,已经把手伸进老百姓的口袋里去了

过“紧日子”的地方政府,已经把手伸进老百姓的口袋里去了

浮事记
2024-06-03 11:48:21
持续反转!奔驰车主殴打女骑手。双方当事人都曝内幕,果然有情况

持续反转!奔驰车主殴打女骑手。双方当事人都曝内幕,果然有情况

音乐时光的娱乐
2024-06-16 15:02:04
凯尔特人38分惨败,球队被打到互殴内斗,成NBA笑话

凯尔特人38分惨败,球队被打到互殴内斗,成NBA笑话

阿雄侃篮球
2024-06-16 00:08:42
扣分+降级,曝足协将公布调查结果,3队被罚,老牌豪门在列

扣分+降级,曝足协将公布调查结果,3队被罚,老牌豪门在列

东球弟
2024-06-16 11:09:42
阿南德最新预言!2024年,美国动乱,日本地震,中国将有大事发生

阿南德最新预言!2024年,美国动乱,日本地震,中国将有大事发生

飞云如水
2024-06-10 22:25:48
A股:股市或将迎来暴风雨

A股:股市或将迎来暴风雨

生活中的栗子
2024-06-16 12:34:28
同村人评价火爆全网的“数学天才少女”:孩子聪明又懂事

同村人评价火爆全网的“数学天才少女”:孩子聪明又懂事

央广网
2024-06-16 00:30:04
突发!河南车祸现场大货车撞击120救护车,目击者称司机全身是血

突发!河南车祸现场大货车撞击120救护车,目击者称司机全身是血

小毅讲历史
2024-06-16 11:37:19
成都蓉城新任董事长现身客场看台,和远征球迷们一起助威

成都蓉城新任董事长现身客场看台,和远征球迷们一起助威

懂球帝
2024-06-16 18:49:10
不足19万起平替理想L9,增程纯电双动力!车长超5米,续航超600Km

不足19万起平替理想L9,增程纯电双动力!车长超5米,续航超600Km

小史谈车
2024-06-15 23:28:21
理想汕头车友聚会多车追尾,5辆受损!车企称雨天路滑车距近

理想汕头车友聚会多车追尾,5辆受损!车企称雨天路滑车距近

南方都市报
2024-06-16 15:29:24
乘客落下30万元现金,网约车司机:没想法不可能,但不能拿

乘客落下30万元现金,网约车司机:没想法不可能,但不能拿

新晚报
2024-06-16 08:02:00
以色列把真主党的2号领导送“走”了

以色列把真主党的2号领导送“走”了

近距离
2024-06-14 19:28:25
马斯克:美国忘记如何登月很正常,埃及也不知道金字塔是怎么建的

马斯克:美国忘记如何登月很正常,埃及也不知道金字塔是怎么建的

吾天
2024-06-16 01:21:15
沉默2天后,德国率先出牌,德副总理将访华,一待就是3天

沉默2天后,德国率先出牌,德副总理将访华,一待就是3天

特特农村生活
2024-06-16 17:12:04
“一丝不挂”新舞蹈?惹争议,被摸下体更不害臊,金星质疑是对的

“一丝不挂”新舞蹈?惹争议,被摸下体更不害臊,金星质疑是对的

吃鱼思故渊
2024-05-16 21:48:21
对抗强度上升!中方大量增兵,刚排兵布阵,美航母掉头就跑

对抗强度上升!中方大量增兵,刚排兵布阵,美航母掉头就跑

青年的背包
2024-06-14 19:54:49
从现在到三伏,每天早上吃3勺它,腿脚有劲气色好,不懂吃可惜了

从现在到三伏,每天早上吃3勺它,腿脚有劲气色好,不懂吃可惜了

Lily美食谈
2024-06-13 22:44:12
《庆余年》第三季开拍,陈道明,田雨,金晨或弃演,谁接庆帝合适

《庆余年》第三季开拍,陈道明,田雨,金晨或弃演,谁接庆帝合适

综艺拼盘汇
2024-06-16 12:27:16
2024-06-16 20:36:49
嘶吼RoarTalk
嘶吼RoarTalk
不一样的互联网安全新视界
7434文章数 10509关注度
往期回顾 全部

科技要闻

iPhone 16会杀死大模型APP吗?

头条要闻

G7峰会上特鲁多口误:将努力确保乌克兰承担责任

头条要闻

G7峰会上特鲁多口误:将努力确保乌克兰承担责任

体育要闻

没人永远年轻 但青春如此无敌还是离谱了些

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

打断妻子多根肋骨 上市公司创始人被公诉

汽车要闻

售17.68万-21.68万元 极狐阿尔法S5正式上市

态度原创

亲子
本地
时尚
教育
公开课

亲子要闻

你是我最棒的老爸 祝天下所有好爸爸父亲节快乐#土豆王国彩虹糖

本地新闻

粽情一夏|海河龙舟赛,竟然成了外国人的大party!

伊姐周日热推:电影《沙漏》;动漫《眷思量2》......

教育要闻

QS排名大跳水的10所美国大学:虽然我们没充钱,但可别真拿我们当“野鸡”!

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版