ida--02 执行python 几种方式,常用脚本

IDA Python 运行脚本

方式1:执行IDA Python(IDC/IDAPython) 函数

Python 输入框(交互式 REPL):单独表达式会自动回显返回值
Shift+F2(Execute script 脚本窗口):纯脚本模式,只执行语句,不会自动打印返回值!

# 1) 看那个字符串
idc.get_strlit_contents(0x65B15, -1, 0)   # -> b' &\t:=;\nplzdontcrackme856c91'
  1. 0x65B15 → ea
    字符串的起始地址(Effective Address),在 IDA 里就是这个字符串所在的地址。
  2. -1 → length

-1 含义:自动读取,由 IDA 自动判断字符串长度(读到字符串结束符为止)
如果填数字(比如10)就是强制只读取 N 个字节。

  1. 0 → strtype 字符串类型
    IDA 字符串类型常量:
    • 0 → STRTYPE_C:标准 C 风格以\0空字符结尾的 ASCII 字符串(最常用)
    • 1:宽字符串 unicode16,2:pascal 字符串(前缀存长度)等

返回值

  • 成功:返回bytes 原始字节串(不是 python str),比如 b"hello"
  • 失败:返回 None

ida python 输入框


ida python 输入框

⚠️ 注意:返回的是 bytes,如果你要打印成文本,需要手动 .decode('ascii'),遇到中文可能用utf-8/gbk

方式2:shit f2 (ida/file/script command...)
import idc
res = idc.get_strlit_contents(0x65B15, -1, 0)
print("shift+f2运行脚本log:", res)

python运行脚本
# 1) 看那个字符串
idc.get_strlit_contents(0x65B15, -1, 0)   # -> b' &\t:=;\nplzdontcrackme856c91'

# 2) 验证 SHA-256 表(前 6 个 u32)
import ida_bytes, struct
b = ida_bytes.get_bytes(0x65B31, 24)  # 直接从程序内存读取原始字节
[hex(struct.unpack('<I', b[i:i+4])[0]) for i in range(0,24,4)]
# -> ['0x428a2f98','0x71374491','0xb5c0fbcf','0xe9b5dba5','0x3956c25b','0x59f111f1']

# 3) 确认字符串只有 2 个引用
import idautils
for x in idautils.XrefsTo(0x65B15): print(hex(x.frm))
# -> 0x2b6b8, 0x2ba00
方式3:script file...

选择 python 脚本文件


IDA Python 脚本:导出 qimei_core_generate 函数完整二进制 + 反汇编文本

text:0000000000025BC0 ; QIMEI 核心生成引擎 (超大 + 混淆)。据 type 参数生成不同 QIMEI 子串: type=0 → z 设备 ID; type=1 → o 缓存 QIMEI; type=3 → z2 设备 ID + 版本;type=6 → m QIMEI 字符串;type=7 → r 上报串;type=13 → r4 加密;type=15 → a 加密字节。内含 q16/q36 标识、plzdontcrackme856c91 反破解提示、XTEA 加密、设备特征采集 (ActivityThread/signatures/NetworkInterface/stat 等)
.text:0000000000025BC0 ; Attributes: bp-based frame
.text:0000000000025BC0
.text:0000000000025BC0 ; _QWORD *__fastcall qimei_core_generate (_QWORD *__return_ptr, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD, _QWORD)
.text:0000000000025BC0 qimei_core_generate                     ; CODE XREF: qimei_str_manip+130↑p
.text:0000000000025BC0                                         ; qimei_str_manip+880↑p ...
.text:0000000000025BC0
.text:0000000000025BC0 var_4070        = -0x4070
.text:0000000000025BC0 var_4058        = -0x4058
.text:0000000000025BC0 var_4050        = -0x4050
.text:0000000000025BC0 var_4048        = -0x4048

脚本
适用 IDA Pro 9.x,ARM64,目标函数:qimei_core_generate(0x25BC0)
输出两类文件:

  1. qimei_core_generate.bin:函数原始机器码二进制(可丢进 IDA/Ghidra 单独分析)
  2. qimei_core_generate_disasm.txt:完整反汇编文本,方便阅读

dumpFunc.py

import ida_funcs
import ida_bytes
import idautils
import idaapi
import ida_ua
import os

def dump_func_full(func_ea, out_bin_name="qimei_core_generate.bin", out_disasm_name="qimei_core_generate_disasm.txt"):
    func = ida_funcs.get_func(func_ea)
    if not func:
        print(f"错误:找不到函数 @ {hex(func_ea)}")
        return

    print(f"函数 qimei_core_generate: start={hex(func.start_ea)}, end={hex(func.end_ea)}")
    chunks = list(idautils.Chunks(func.start_ea))
    print(f"检测到函数碎片数量: {len(chunks)}")

    # 拼接全部碎片原始二进制
    all_raw = b""
    for chunk_start, chunk_end in chunks:
        chunk_data = ida_bytes.get_bytes(chunk_start, chunk_end - chunk_start)
        all_raw += chunk_data

    # 计算绝对路径
    bin_fullpath = os.path.abspath(out_bin_name)
    disasm_fullpath = os.path.abspath(out_disasm_name)

    with open(bin_fullpath, "wb") as f:
        f.write(all_raw)
    print(f"✅ 合并全部碎片机器码保存至: {bin_fullpath},总字节: {len(all_raw)}")

    # 导出反汇编文本
    disasm_lines = []
    for chunk_start, chunk_end in chunks:
        ea = chunk_start
        while ea < chunk_end:
            insn = ida_ua.insn_t()
            if ida_ua.decode_insn(insn, ea):
                # line = idaapi.generate_disasm_line(ea, 0) 第二个参数**flags 传 0 在 IDA9.3 SP2 ARM64 会输出原始格式化标记字符 `SOH`(ASCII 0x01,控制字符)**,不是人类可读汇编文本。
                line = idaapi.generate_disasm_line(ea, idaapi.GENDSM_FORCE_CODE)
                disasm_lines.append(f"{hex(ea):<16} {line}")
                ea += insn.size
            else:
                ea += 1

    with open(disasm_fullpath, "w", encoding="utf-8") as f:
        f.write("\n".join(disasm_lines))
    print(f"✅ 完整反汇编保存至: {disasm_fullpath}")

    # 打印调用交叉引用
    print("\n----- XrefsTo: 调用 qimei_core_generate 的位置 -----")
    for xref in idautils.XrefsTo(func.start_ea):
        print(f"  call from: {hex(xref.frm)}")

# 入口
if __name__ == "__main__":
    dump_func_full(0x25BC0)


  1. 优先:idautils.Chunks 遍历全部函数碎片(解决 OLLVM 拆分函数,完整导出全部代码)
  2. 遍历指令改用 ida_ua 规范 API,避开 FuncItems 类型 bug
  3. Chunks 是关键:OLLVM 控制流扁平化会把函数拆成多个不连续碎片,只用start~end会漏掉部分代码,idautils.Chunks会取出全部片段,合并 bin 才完整。
  4. 输出的qimei_core_generate.bin:所有碎片按地址顺序拼接,不是原 ELF 内存连续块,单独加载进 IDA 时,基址填原库基址,按顺序加载即可。

重要说明(libqimei.so 这个超大混淆函数重点)

打开汇编文本-有乱码

dumpFunc_tag_remove.py

import ida_funcs
import ida_bytes
import idautils
import idaapi
import ida_ua
import os

def dump_func_full(func_ea,
                   out_bin_name="qimei_core_generate.bin",
                   out_disasm_name="qimei_core_generate_disasm_fixed.txt"):
    func = ida_funcs.get_func(func_ea)
    if not func:
        print(f"错误:找不到函数 @ {hex(func_ea)}")
        return

    print(f"函数 qimei_core_generate: start={hex(func.start_ea)}, end={hex(func.end_ea)}")
    chunks = list(idautils.Chunks(func.start_ea))
    print(f"检测到函数碎片数量: {len(chunks)}")

    # 1、导出原始二进制(bin文件是好的,不变)
    all_raw = b""
    for chunk_start, chunk_end in chunks:
        chunk_data = ida_bytes.get_bytes(chunk_start, chunk_end - chunk_start)
        all_raw += chunk_data

    bin_fullpath = os.path.abspath(out_bin_name)
    with open(bin_fullpath, "wb") as f:
        f.write(all_raw)
    print(f"✅ bin: {bin_fullpath} 总字节:{len(all_raw)}")

    # 2、导出汇编:使用 tag_remove() 清除IDA内部 !reg! )!xxx! 标记
    disasm_lines = []
    for chunk_start, chunk_end in chunks:
        ea = chunk_start
        while ea < chunk_end:
            insn = ida_ua.insn_t()
            insn_len = ida_ua.decode_insn(insn, ea)
            if insn_len <= 0:
                ea += 1
                continue
            raw_line = idaapi.generate_disasm_line(ea, idaapi.GENDSM_FORCE_CODE)
            # ===== 关键:tag_remove 剥离IDA所有内部标记符号!官方API =====
            clean_line = idaapi.tag_remove(raw_line)
            disasm_lines.append(f"{hex(ea):<18} {clean_line}")
            ea += insn_len

    disasm_fullpath = os.path.abspath(out_disasm_name)
    with open(disasm_fullpath, "w", encoding="utf‑8") as f:
        f.write("\n".join(disasm_lines))
    print(f"✅ 修复后disasm: {disasm_fullpath}")

    print("\n----- XrefsTo: 调用 qimei_core_generate -----")
    for xref in idautils.XrefsTo(func.start_ea):
        print(f"  call from: {hex(xref.frm)}")

if __name__ == "__main__":
    dump_func_full(0x25BC0)

打开汇编文本-去tag
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容