• IDAPython入门教程 基于IDA7.5_Python3 第一讲 简介与地址获取


    IDA Python 7.5 python函数入门

    简介

    IDAPython是很强大的功能. 但是在7.5支持python3之后很多函数都改变了. 所以从头开始学一下.

    要学习IDA Python 首先你要会python的基本操作. 以及IDAPython文档会查询. IDC 文档会查询. 以及差异化查询.

    下面列出几个有用的链接方便直接点击学习或者查询.

    python3 入门知识: 菜鸟教程Python3入门知识

    IDAPython官方函数文档: IDAPython官方文档函数查询

    IDC函数官方文档查询: IDC函数

    IDA版本与版本之间的差异化函数查询: IDA版本函数差异化

    一丶IDApython分布讲解

    1.1 IDA Python 常见模块介绍与脚本使用

    在IDA中.有三个重要的库.分别是IDC,idautils,idaapi

    IDC 他是封装IDA与IDC函数的兼容性模块.

    Idautils 这个是IDA提供给我们的一个高级实用的模块.

    idaapi 他可以允许我们访问更加底层的数据.

    在IDA中我们要使用脚本有三种方式

    第一种 .可以直接按 shift + F2 快捷键调出界面.也可以直接在菜单中选择命令脚本.

    第二种 可以是写一个脚本文件直接进行引用.

    如下图所示:

    请更改为python来使用IDA python.当然如果拟更改为IDC 那么你只能使用IDC函数了.

    第三种方式是直接在IDA底部写命令.

    PS: 如果没有python选项 参考一下网上怎么修复python支持.

    1.2 IDAPython 汇编界面介绍

    查看IDA我们可以看到如下界面

    下面以图表的形式展示一下说明

    .text 这是程序的段名称
    0x004010B7 这是当前的Addr地址
    movups 这个汇编是当前的汇编语句操作符
    movups xmmword ptr[xxx] ,xmm0 这个是汇编指令的操作数
    movups xmmword ..,xmm0 这一整行是反汇编语句

    1.3 IDA中获取界面中地址函数

    那么下面先讲一下怎么获取界面中的地址. 至于里面的各项元素后面会一一说明.

    • 当前,最大,最小,选择开始,选择结束 等地址的获取.

      在IDA 7.5中. 我们获取地址的函数如下

      当前地址获取使用 idc.here() 函数 或者 idc.get_screen_ea() 函数

      最小地址可以使用: ida_ida.inf_get_min_ea()

      最大地址可以使用: ida_ida.inf_get_max_ea()

      当前选择地址的开始: idc.read_selection_start()

      当前选择地址的结束:idc.read_selection_end()

      如果判断地址是否存在可以使用: idaapi.BADADDR

      这些函数的返回值都是地址. 且没有参数.

      print(hex(idc.here()))          #获取当前地址
      print(hex(idc.get_screen_ea())) #另一种获取当前地址的函数
      print(hex(ida_ida.inf_get_min_ea())) #获取当前最小地址
      print(hex(ida_ida.inf_get_max_ea())) #获取当前最大地址
      print(hex(idc.read_selection_start()))#如果你选择了某块地址 那么使用此函数则返回你选择的这块地址的起始地址
      print(hex(idc.read_selection_end())) #同上 返回结束地址.
      
      if idaapi.BADADDR == idc.here(): 
          print("BadAddress addr invalid")
      else: 
          print("addr is ok")
      

      下面则使用表格来说一下上述函数的老版函数. 便于查询. 如果你使用的是7.0 那么可以使用老版函数. 没有特殊说明的说明没有新函数.可以直接使用.

      老版函数 当前7.5支持函数 作用
      idc.ScreenEA() idc.get_screen_ea() 获取当前指令地址
      idc.MinEA() idc.StartEA() idc.BeginEA() ida_ida.inf_get_min_ea() 获取当前最小地址. 其中老版的三个函数都替换为了新版.使用的是同一个函数
      idc.MaxEA() ida_ida.inf_get_max_ea() 获取当前最大地址
      idc.SelStart() idc.read_selection_start() 获取当前光标选择的的块中的 起始地址
      idc.SelEnd() idc.read_selection_end() 同上 返回结束地址

    1.4 IDAPython中的数值获取

    ​ 在IDA中.如果我们想获取一个地址处的值可以使用以下几个函数

    函数 说明
    Byte(addr) 以字节为单位获取地址处的值
    Word(addr) 同上. 以2字节(字)的单位获取
    Dword(addr) 4字节
    Qword(addr) 8字节

    但是在IDA 7.5 支持python3之后这些函数都变了.

    下面是变换之后的函数

    旧的函数 新的函数
    Byte(addr) idc.get_wide_byte(addr)
    Word(addr) idc.get_wide_word(addr)
    Dword(addr) idc.get_wide_dword(addr)
    Qword(addr) idc.get_qword(addr)

    当然与之对应的还有其判断函数
    idc.isByte() Word Dwrd Qwrd
    但在高版本中都变成了
    ida_bytes.is_byte word dword qword
    上面的word dword qword 都省略了前边的字段.使用的时候自己加上即可.
    指令实战如下:

    import idc
    
    ea = idc.get_screen_ea()
    value = idc.get_wide_byte(ea)
    print("当前指令的硬编码为 {}".format(hex(value)));
    

    1.5 IDAPython中的数值操作.

    在上面我们讲了如何获取地址.如何获取地址指令处的值.那么我们就可以说一下如何修改指令的值.

    对应的函数如下:

    指令 说明
    idc.PatchByte(addr,value) 修改addr地址的值为value.每次修改一个字节
    idc.PatchWord(addr,value) 同上一次修改变为2个字节
    idc.PatchDword(addr,value) 4
    idc.PatchQword(addr,value) 8

    这些指令在IDA7.5中统统不使用了. 统统移植到 ida_bytes里面了

    下面说一下这些新函数

    旧函数 新函数
    idc.PatchByte(addr,value) ida_bytes.patch_byte(addr,value)
    idc.PatchWord(addr,value) ida_bytes.patch_word(addr,value)
    idc.PatchDword(addr,value) ida_bytes.patch_Dword(addr,value)
    idc.PatchQword(addr,value) ida_bytes.patch_Qword(addr,value)

    下面看一下指令操作.

    ea = idc.get_screen_ea()
    value = idc.get_wide_byte(ea)
    print("我是没被修改的当前=  {}".format(hex(value)))
    ida_bytes.patch_byte(ea,0x90)
    
    value = idc.get_wide_byte(ea)
    print("我被修改过了当前我的值为 {} ".format(hex(value)))
    
    

    二丶IDAPython实战

    ​ 通过上面我们介绍的一些IDA Python的操作. 你现在能进行简单的脚本制作了.

    如遇到 简单的花指令 我们可以手动写脚本去除. 现在我们写一个脚本. 脚本的作用是

    获取我们选择区域的所有二进制值. 如果二进制数值是0x66 那么我们就替换成 0x90 (nop)

    如下图原图所示:

    首先选择这一块内容 (0x004015D1 - 0X0040166B)

    然后进行脚本编写

    import idc
    import idaapi
    import idautils
    
    #获取当前选择的起始地址
    StartSeclectAddr = idc.read_selection_start()
    
    #获取当前选择的终止地址
    EndSeclectAddr = idc.read_selection_end()
    
    #计算出当前指令长度
    SelLen = EndSeclectAddr - StartSeclectAddr;
    
    #从选择地址开始 - 选择地址结束进行遍历. 获取其指令字节. 如果是0x66 则替换成0xFF
    
    for index in range(SelLen):
        curaddr = StartSeclectAddr+index
        tmpValue = idc.get_wide_byte(curaddr)
        if (tmpValue == 0x66):
            ida_bytes.patch_byte(curaddr,0x70)
    

    PS: 虽然脚本没有任何意义.但是可以带我们熟悉下python与函数的结合使用.

    修改后如下:

    作者:IBinary


    坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。

    详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
  • 相关阅读:
    Linux 一块网卡配置多个IP的方法
    Nginx详解篇
    Nginx故障排错及一个网站小实例
    Nginx web 服务器 安装篇
    一些看起来比较专业的工具
    Linux 下软件的安装方法
    Mysq登陆后执行命令提示You must SET PASSWORD before executing this statement
    Linux-Centos 虚拟机安装
    Mysql的多种安装方法———rpm安装
    etcd安装和简单使用
  • 原文地址:https://www.cnblogs.com/iBinary/p/14642662.html
Copyright © 2020-2023  润新知