日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IDC:函数

發布時間:2024/3/12 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IDC:函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

IDC:函數

  • IDC腳本中的函數必須要有返回值。在IDC腳本中,支持兩類函數:

  • 內建函數

  • 用戶自定義函數

  • 用戶自定義函數一般是像下面這樣的方式寫的:

    static func(arg1,arg2,arg3) {statements ... }

    需要注意的一點是,聲明函數參數的時候,沒必要指定函數參數的類型了,因為IDC會根據你傳入的參數自動進行參數類型轉換的。

  • 默認情況下,函數調用的時候參數傳遞是按值傳遞的,但是以下三種情況例外(引用傳遞):

  • 對象類型的參數總是使用引用方式傳參

  • 函數類型的參數總是使用應用方式傳參

  • 還可以強制使用 & 符號來讓參數使用引用方式傳參

  • 如果IDC腳本中調用的函數不存在,IDA就會嘗試解析并使用當前被調試的進程中的符號或者標簽,如果解析成功,那么就會執行一次 AppCall(AppCall稍后會進一步解釋)

IDC:AppCall

  • 首先需要明確一點,AppCall是IDC腳本中的一個內建函數

  • 先來看函數原型

    anyvalue Appcall(ea, type, ...);
    • 功能:調用被調試進程的函數

    • 參數:ea - 調用的函數地址

    • 參數:type - 調用的函數的類型或者說方式,支持三種調用形式

    • 字符串形式,比如:“int func(void);”

    • 類型對象形式,比如:GetTinfo(ea)

    • 零:相當于讓IDA自行決定,這種情況下,類型一般是從idb中進行獲取的

    • 參數:..., 這個是可變參數,用來傳遞你要調用的函數的參數

    • 返回值:被調用函數的返回值

    • Remark:如果函數調用失敗,并且失敗的原因是內存訪問異常或者其他異常,腳本會拋出一個runtime錯誤信息,可以在腳本中使用 try/catch 進行異常捕獲。在實際的使用過程中,很少使用AppCall這個函數調用,只是說IDA擁有這種在IDC腳本中存在未知函數的時候嘗試在被調試進程中匹配符號的能力,舉個例子:_printf("hello\n") 這條語句會調用被分析程序的 _printf 函數

  • AppCall函數有2個選項可以使用,我們可以在IDC腳本中使用 SetAppcallOptions宏進行設置:

  • #define APPCALL_MANUAL 0x0001

    • 只設置AppCall, 不執行,執行完畢之后,需要調用一次 CleanupAppcall

  • #define APPCALL_DEBEV 0x0002

    • 返回調試詳細信息, 如果設置了這個標志位,當AppCall執行過程中發生異常的時候,會生成一個包含詳細異常信息的異常對象

  • #define APPCALL_TIMEOUT 0x0004

    • AppCall調用的超時時間, 超時時間是以毫秒為單位的,并且值是放在option的高2位字節中,如果AppCall調用超時,錯誤信息會放到 errbuf中,并且值是字符串 timeout

  • #define SET_APPCALL_TIMEOUT(x) ((x<<16)|0x0004)

    • 指定AppCall超時時間的時候,需要拼裝option的值,這個就是一個輔助宏,用來生成option的值

  • 使用AppCall這個功能,可以很隨意的調用被調試進程內的函數而不需要進行任何的dll注入或者修改被調試進程的內存,如果被調用的函數名稱存在的話,AppCall還可以簡化成 func(args)的形式,前提是func這個符號是存在的,舉個例子:

    verinfo = object(); verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); GetVersionExA(&verinfo);

    上面這段代碼將會在被調試進程內創建一個OSVERSIONINFOA結構體,并且將結構體地址傳遞給GetVersionExA調用,調用完畢之后,verinfo 對象就被轉換成了IDC對象,內存結構如下:

    object__at__: 18FEB0hdwBuildNumber: 7600.dwMajorVersion: 6.dwMinorVersion: 1.dwOSVersionInfoSize:dwPlatformId: 2.szCSDVersion: "\x00\x00\x00\x00..."

    其中_at_屬性表示這個結構體的內存地址,在這個例子中verinfo是一個臨時變量,所以_at_的值意義不大,大家在使用使用的過程中可能會遇到這個值很有用的情況。

  • AppCall會自動在IDC對象和C對象之間進行轉換,轉換的時候依據IDA中擁有的類型信息來進行,但是還要遵循以下幾個轉換規則:

  • 基本數據類型:

    • 如果目標數據類型也是一個基本數據類型(非指針),只需要執行簡單的轉換即可(附帶符號處理或者截斷處理),比如: IDC中的值-1轉換成 _int32(0xFFFFFFFF),IDC中的0x555轉換成 _int8(0x55)

  • 指針:

    • 如果目標類型是一個指針,并且IDC的值是一個字符串,這個字符串就轉換成一個指針對象,字符串的內容直接拷貝到被調試進程,后面追加一個結束符 \0

    • 如果對應的IDC的值是一個數字,轉換之后的結果是指針所指向的內存的值是這個數值,如果你想得到一個數值的地址,可以直接使用 &符號

    • 如果對應的IDC值不是字符串,那這個值將會轉換成一個對象,指針指向的內存使用這個對象進行初始化

  • 結構體

    • 如果目標類型是一個結構體,IDA會通過對應的屬性來嘗試一個一個的初始化結構體的成員。比如:在上面的例子中只有dwOSVersionInfoSize 屬性存在,那么這個結構體字段就使用這個屬性類初始化,對于不存在的字段直接初始化成0

  • 數組

    • 數組的每個元素都是單獨初始化的,當然如果對應的IDC值是字符串除外,因為字符串本身就是可以當成一個完整的數組來使用的。

  • 下面針對上述的幾種情況,我們來舉一些例子:

  • 調用printf

    auto n = 5;auto s = "short";_printf("Hello world, number is %d, string is %s\n", n, s);
  • 調用sscanf

    auto x; auto nsuccess = _sscanf(s, "%d", &x);
  • 結構體使用

    verinfo = object();GetVersionExA(verinfo);
  • 另外,_userCall 這個內建調用也是支持這些自動轉換的

  • 對于會發生異常的調用,配合APPCALL_MANUAL 標志位,可以實現單步的效果,具體方式還需要大家仔細去研究一下.

總結

以上是生活随笔為你收集整理的IDC:函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。