关于逆向工程:iOS逆向与安全利用IDAPython插件提高反汇编和逆向工程效率

48次阅读

共计 2859 个字符,预计需要花费 8 分钟才能阅读完成。

前言

IDA Python 是一个用 Python 语言编写的插件,它为 IDA Pro 提供了可扩展性和自动化脚本反对。应用 IDA Python,能够以更快、更简略的形式实现反汇编和逆向工程工作。

1、指标

疾速理解和开始应用 idapython。

2、开发环境和工具清单

mac 零碎
IDA Pro7.0

3、罕用 APIidaapi 模块:

该模块提供了许多外围的 IDA API,
包含:

idaapi.get_func(ea):获取给定地址处的函数对象 idaapi.get_segm_by_name(name):获取指定名称的段对象 idaapi.get_screen_ea():获取以后屏幕上显示的地址
idaapi.get_func_name(ea):获取给定地址处的函数名 idaapi.get_name_ea_simple(name):获取具备给定名称的地址 idaapi.asktext(defval, prompt):显示一个文本框,期待用户输出文本 idaapi.get_func_offset(ea): 获取指定地址绝对于函数起始地址的偏移量 idaapi.get_segment_name(ea): 获取指定地址所在的段名称

idaapi.idc 模块:该模块提供了一些旧版 IDA API 的 Python 封装,
包含:

idc.GetDisasm(ea):获取给定地址处的反汇编指令
idc.Jump(ea):跳转到指定地址
idc.SetColor(ea, what, color):设置给定地址的色彩
idc.MakeCode(ea):将给定地址处的字节转换为指令
idc.MakeName(ea, name):将给定地址处的符号名称更改为给定名称 idc.get_inf_attr(idc.INF_MIN_EA):获取载入程序的最小的无效地址 idc.get_inf_attr(idc.INF_MAX_EA):获取载入程序的最大的无效地址 idc.print_insn_mnem(ea):获取给定地址处的助记符
idc.prev_head(ea):获取给定地址的上一条指令的地址 idc.print_operand(ea,index):获取给定地址中的操作数
idc.PatchByte(ea, 0x90):批改给定地址的第一个字节
idc.PatchWord(ea, 0x9090):批改给定地址的前两个字节
idc.PatchDword(ea, 0x90909090):批改给定地址的前四个字节 idc.PatchQword(ea,0x9090909090909090):批改给定地址的前八个字节

idautils 模块:该模块提供了一些罕用的 IDA 辅助函数,
包含:

idautils.Functions():返回以后程序中所有函数的迭代器
idautils.Segments():返回以后程序中所有段的迭代器
idautils.Strings():返回以后程序中所有字符串的迭代器
idautils.XrefsFrom(ea):返回指向给定地址的所有穿插援用的迭代器 idautils.Heads(ea,ea):获取指定地址段的汇编指令

4、应用示例

移除 SVC 指令:须要被移除的汇编指令如下:

MOV X0, #0x1F
MOV X1, #0
MOV X2, #0
MOV X3, #0
MOV W16, #0x1A
SVC 0x80

idapython 脚本如下:

import idautils
import idc

# 获取二进制文件的起始地址和完结地址
start_addr = idc.get_inf_attr(idc.INF_MIN_EA)
end_addr = idc.get_inf_attr(idc.INF_MAX_EA)

print("Start")

# 遍历二进制文件中的所有指令
for addr in idautils.Heads(start_addr, end_addr):
    # 判断以后指令是否为 svc 指令
    mnem = idc.print_insn_mnem(addr)
    if mnem == "SVC":

        # 判断 svc 指令的前五行是否是 mov 指令
        prev1_addr = idc.prev_head(addr)
        prev2_addr = idc.prev_head(prev1_addr)
        prev3_addr = idc.prev_head(prev2_addr)
        prev4_addr = idc.prev_head(prev3_addr)
        prev5_addr = idc.prev_head(prev4_addr)
        if (idc.print_insn_mnem(prev1_addr) == "MOV"
            and idc.print_operand(prev1_addr, 0) == "W16"
            and idc.print_operand(prev1_addr, 1) == "#0x1A"
            and idc.print_insn_mnem(prev2_addr) == "MOV"
            and idc.print_operand(prev2_addr, 0) == "X3"
            and idc.print_operand(prev2_addr, 1) == "#0"
            and idc.print_insn_mnem(prev3_addr) == "MOV"
            and idc.print_operand(prev3_addr, 0) == "X2"
            and idc.print_operand(prev3_addr, 1) == "#0"
            and idc.print_insn_mnem(prev4_addr) == "MOV"
            and idc.print_operand(prev4_addr, 0) == "X1"
            and idc.print_operand(prev4_addr, 1) == "#0"
            and idc.print_insn_mnem(prev5_addr) == "MOV"
            and idc.print_operand(prev5_addr, 0) == "X0"
            and idc.print_operand(prev5_addr, 1) == "#0x1F"
        ):
            print '查找到一条 MOV 指令'
            # 将相干指令设为 nop
            idc.PatchDword(addr, 0xd503201f)  # nop
            idc.PatchDword(prev1_addr, 0xd503201f)  # nop
            idc.PatchDword(prev2_addr, 0xd503201f)  # nop
            idc.PatchDword(prev3_addr, 0xd503201f)  # nop
            idc.PatchDword(prev4_addr, 0xd503201f)  # nop
            idc.PatchDword(prev5_addr, 0xd503201f)  # nop
print("End")

执行前:

按下图操作执行上边的脚本

执行后成果如下:

总结

这篇文章小牛试刀的介绍如何在 IDA 中应用 IDAPython 插件,这只是一部分利用场景,期待大家持续摸索更多用法。提醒:浏览此文档的过程中遇到任何问题,请关住工众好【挪动端 Android 和 iOS 开发技术分享】或 +99 君羊【812546729】

正文完
 0