IDA 和 IDA-Python 学习笔记

  • 说明:个人笔记,不适合新手学习用,只适合于文档查询用途

IDA 快捷键

  • 注意:定位依靠光标,按键只是对当前选中的地址执行快捷操作
按键 快捷操作
Enter 进入函数内部,查看标号对应地址
Esc 返回Enter前的位置
A 强制解释光标处地址为字符串(但不一定是字符串)
B 16进制数转2进制
C 强制解释光标处地址为指令
D 强制解释光标处地址为数据
G 快速查找对应地址
H 16进制转10进制
k 将数据解释为栈变量
; 添加注释
M 解释为枚举类型
N 重新命名
O 解释地址为数据段偏移量,用于字符串标号
T 解释数据为结构体成员
X 转换视图到交叉参考模式
shift+F9 添加结构体
shift+F12 添加字符串
shift+e 提取数据
R 数字转字符
P 脚本修改源程序后让IDA重新分析当前程序

IDA-python

  • 官方文档 doc
  • IDA-Python 重要模块
    • IDC: 封装IDA与IDC函数的兼容性模块, 提供IDC中所有的函数功能(例如返回段名、起始地址)
    • idautils: IDA提供的一个高级utils,能够转换成python的相关对象,如列表
    • idaapi: 通过类的方式,访问更多底层数据

[非常重要说明] 防止踩坑

  • idapython 是 ida pro 的一个插件,必须 要在 ida 中使用或者通过 ida 程序的命令行执行方式运行,并不像普通的python包那样,可以在自己的项目中独立使用,这也意味着它难以用一般的 ide (如pycharm)进行代码调试
  • ida安装目录/cfg/idapython.cfg: 建议修改如下设置为 YES,因为很多参考代码是旧的 api,初学者很难处理兼容错误
// Should the plugin automatically load a 6.95 bw-compatibility layer?
AUTOIMPORT_COMPAT_IDA695 = YES
  • 现代python开发很多用conda环境,用conda环境下的python解释器来作为IDA内置的python:设置环境变量
PYTHONHOME = C:\ProgramData\Anaconda3\

VSCode 调试 IDA-Python

  • win10 环境变量新增 pythonpath=C:\Program Files\IDA 7.0\python;C:\Program Files\IDA 7.0\plugins;
  • VSCode 安装插件 IDACode,为正常使用IDACode,还需要安装相应的 IDA 插件,在这里下载插件 ida.zip。下载完成后直接解压(idacode.py和idacode_utils文件夹)到%IDAPATH%/plugins或者%APPDATA%\Hex-Rays\IDA Pro\plugins中。
  • 编辑idacode_utils/settings.py,把 Python 的可执行文件路径改为自己电脑上 Python 的路径:
  • 打开ida,随便打开一个exe,观察 output window。

    如图pip install --user debugpy tornado或者 pip install --user debugpy tornado -i https://mirrors.aliyun.com/pypi/simple安装依赖即可。


pip install futures
如果如下图所示即代表成功:
调试方式参考 REF[1]


验证 IDA-Python 安装

IDA 上面的 File->Script Command 打开之后看 Scripting language 是否是存在 IDC 和 Python
用下面的脚本测试:

import idaapi
import idc
import idautils

if __name__ == "__main__":
    fp = open("Test.txt", "w")
    fp.write("Success\n")
    fp.close()

IDA-Python 常用命令和函数

  • EA effective address 当前光标所处的地址
    • here()
    • ida.ScreenEA()
  • 当前 IDA 加载的程序中的最小/最大有效地址:MinEA()/MaxEA()

IDA-Python Some useful scripts

打印全部函数名

# -*- coding: utf-8 -*-
from idaapi import *
from idautils import *
import idc

idc.Wait()              # 单线程的感觉,分析完一个之后才会运行后续脚本
ea = BeginEA()          # 找到程序 _start (针对 ELF 而言) 返回是 <type 'long'>

fp = open(r"D:\binary\ida-python-scripts\rop_fun_output.txt", "w")
fp.write("check\n")

idx = 0
# 在.text段中 SegStart() 找到程序地址最小的汇编指令的地址,SegEnd() 找到程序地址最大的汇编指令的地址
for funcea in Functions(SegStart(ea), SegEnd(ea)):  # Functions() 返回为 <type 'generator'>
    functionName = GetFunctionName(funcea)          # funcea 类型为 <type 'long'>  为地址 GetFunctionName() 将地址转换为函数名
    fp.write("%d " % idx)
    fp.write(functionName + "\n")
    idx += 1

fp.close()
idc.Exit(0)             # 在脚本运行结束之后能够自动关闭 IDA

IDAPython plugin

  • 菜单栏 Edit -> plugin -> 你的插件。插件写好后,放到IDA 目录下的plugins即可。

插件模板

class myIdaPlugin(plugin_t):
    flags=0                       #插件类别 或者特性
    wanted_name="my ida plugin"  #展示名称
    wanted_hotkey="Alt+C"        #其快捷键
    comment="my ida plugin"         #插件描述
    help="Something helpful"     #帮助信息
 
    #初始化时运行的,可以判断是否要启用这个插件,比如你这个插件主要是针对x86的,
    #那你就要判断当前分析的是不是x86,然后在决定是否要显示或者启用这个插件
    def init(self):
        return PLUGIN_KEEP
 
    #插件退出时要做的操作,比如说你打开了某个文件,要到插件结束时才能关闭,
    #这里就给你这个机会
    def term(self):
        pass
 
    #按快捷键等 插件运行时 的地方
    def run(self,arg):       
        pass
#插件入口      
def PLUGIN_ENTRY():
    return myIdaPlugin()


获取鼠标指向的位置的函数的asm代码的插件

#File name : copy_func_asm.py
#coding=utf-8
from idc_bc695 import *
import pyperclip #剪贴板
import idautils
import idaapi
import idc
 
class CopyFunctionAsm(idaapi.plugin_t):
    comment = "Copy here Function assembly to clip" #插件描述
    help = "todo"                                   #帮助信息
    wanted_name = "Copy here func asm"              #菜单中显示的名字
    wanted_hotkey = "Ctrl-Alt-C"                    #希望注册的快捷键
    flags = 0                                       #插件的特征
 
    def __init__(self):
        super(CopyFunctionAsm,self).__init__()
        self._data = None
 
    def term(self):#相当于析构函数
        print("[+] copy func asm plugin term......")
 
    def init(self):#相当于构造函数
        self.view = None
        print("[+] copy func asm plugin init .....")
        return idaapi.PLUGIN_OK                    #任何情况我们都可以的
 
    def run(self,arg):
        print("[-] Copy Function asm .......")
        print("------------------------------------------------------")
        #output function name and Screen offset
        FuncStartAddr = LocByName(GetFunctionName(here()))
        FuncEndAddr = FindFuncEnd(FuncStartAddr)
        print("[*]Function Name     offset  ")
        print("[*]%10s    0x%08X"%(GetFunctionName(FuncStartAddr),here()-FuncStartAddr))
        print("------------------------------------------------------")
 
 
        asm = ''
        for ea in idautils.Heads(FuncStartAddr,FuncEndAddr):
            asm += GetDisasm(ea)+'\n'
 
        pyperclip.copy(asm) #数据发送到剪贴板
        print("[+] run compile..... asmble to clipboard.")
# register IDA plugin
def PLUGIN_ENTRY():
    return CopyFunctionAsm()

把 copy_func_asm.py 放到 ida 主目录 plugins 目录下,重启IDA即可,重启后,我们可以在Output window看到 init和term方法输出的信息(如果你init返回的是PLUGIN_KEEP那么这个时候你将看不到term方法的调用),知道他们已经被调用。可以在ida的菜单栏edit -> plugins下增加了一个Copy here func asm的选项,这个就是我们的插件了,我们选择点击他后,我们就会发现我们的output窗口输出了我们run方法下的print内容,并且我们的剪贴板获取到了鼠标所在的函数的asm代码。

Reference

1.使用 VSCode 调试 IDAPython 脚本
2.IDA 强大的插件 IDApython 北理ctfer的笔记
3.IDAPython Script 与 plugin 看雪
4.【idapython】逆向分析脚本实践 _

推荐中文阅读材料

1.《IDAPython手册(中文版)》
2.《IDA Pro权威指南(第二版)》
3.《IDAPython 初学者指南》url

猜你喜欢

转载自blog.csdn.net/qq_33583069/article/details/128445048
IDA