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與函數的結合使用.

修改后如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM