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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

IDA Plugin 编写基础

發布時間:2024/4/11 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IDA Plugin 编写基础 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
IDA?Plugin?編寫基礎

IDA是迄今為止最為強大的反匯編器,它有著眾多的功能。但是如果它不具備通過附加的模塊來對標準的函數進行擴展的功能(粗俗點說就是plugin)的話,也就有負此盛名了。現在我們就來更為詳細地研究一下如何編寫這些plugin。

喏,首要的就是要有這個叫做IDA的反匯編器,同時還要有與之匹配的IDA?SDK。SDK里主要的部分就是include目錄及其下的所有文件,這些文件里包含了編寫plugin所用到的所有的宏定義和函數原型,同時用到它們的還有import?lib?——?ida.lib。我這里使用的編譯器是Intel?C++,與VC++結合起來用。我選擇它的原因就是,在SDK中沒有對它進行內嵌的支持(比如在SDK中就有Borland?C++和VC++編譯器的安裝文件),而這能使我們更好地理解。ida.lib文件是ida.wll(位于IDA目錄下)的import?library。其中所有的函數都是用ordinal導出的,而ordinal與函數名的比較是在ida.lib里進行的。這就是需要使用與IDA版本相匹配的SDK的原因了,因為導出函數的ordinal會因版本的不同而發生變化。喏,好了,萬事具備了,我們開始吧。

plugin到底是個什么東東呢?其實它也沒什么稀奇的,就像一個通常的DLL,只是導出了下面這個名為PLUGIN的結構體:



?struct?plugin_t
?{int?version;????????//?IDA的版本,用于plugin的編寫,通常這個域的值為IDP_INTERFACE_VERSION?-?表示SDK版本的constant。
?????????????????????????如果這個域的值與所用IDA的版本不一致,就不會加載此plugin。
??int?flags???????????//?這個好理解,就是些標志。嫌麻煩添0就行了。但這里要講一下所有可能的取值。
?????????????????????????
?????????????????????????PLUGIN_MOD?-?置位表示plugin會修改database(坦白講,沒有什么plugin會修改它)。如果此位置位,
?????????????????????????而進程模塊卻禁止修改database,則plugin就不會被使用。這個標志我們并不需要,另外的幾個也是一樣。

?????????????????????????PLUGIN_DRAW?-?置位表示IDA在調用plugin后需要重畫(即刷新)所有窗口。

?????????????????????????PLUGIN_SEG?-?plugin只在鼠標所放之處的地址屬于某個segment時才能使用。這里也不需要。

?????????????????????????PLUGIN_UNL?-?若置位,則plugin在使用后會從內存中卸載。這對于調試器來說當然是好了,但對我們來說
?????????????????????????就不太合適了。?

?????????????????????????這些標志可以用邏輯或(我們這里用or,C語言里用“|”)結合起來。但我說過,更為簡單的是把所有這些
?????????????????????????域都填成紅色的NULL。

??void?(idaapi*?init)(void);????????//初始化函數加載plugin的時候調用,如果函數返回了什么不好的東西,則plugin就不會被加載。

??void?(idaapi*?term)(void);????????//卸載plugin時調用。一般不使用。

??void?(idaapi*?run)(int?arg);??????//也許這是最重要的域了?-?working?function,每次調用plugin都要運行,包含著plugin的主要
??????????????????????????????????????代碼。
??char*?comment;????????????????????//注釋,作提示用的。
??char*?help;???????????????????????//help自然就是help了.
??char*?wanted_name;????????????????//首選的plugin名。
??char*?wanted_hotkey;??????????????//首選的熱鍵。一般來說不依賴于plugin作者選用的鍵,實際的熱鍵值記錄在plugin.cfg,這個
??????????????????????????????????????文件后面會講到。
};

一般來說,include里的loader.hpp文件里這個結構體是作為類來聲明的,我想對那些不了解類的讀者說,其實在C++里類和結構體在本質上都是一樣的。喏,好像到了該給出源代碼的時候了。我這里給出一個最簡單的plugin,這個plugin會將database中的無用指令:
бесполезные?группы?инструкций:

pusha
popa

push?eax
push?edx
rdtsc
pop?edx
pop?eax

push?edx
push?eax
rdtsc
pop?eax
pop?edx

替換為“更為明了”的nop指令。下面是代碼:

#pragma?comment(linker,"/NODEFAULTLIB")
#pragma?comment(linker,"/Entry:Dllmain")????//Runtime庫占了40kb字節,卻沒什么有用的東西,特別是對plugin。
??????????????????????????????????????????????然而,如果切斷它,則需要重新標記入口點。

#define?__NT__
#define?__IDP__????//這個一定要有,否則plugin就罷工。

typedef?unsigned?char?BYTE;????//這里沒有包含標準的include文件需要額外定義BYTE類型

#i?nclude?<ida.hpp>
#i?nclude?<idp.hpp>
#i?nclude?<bytes.hpp>
#i?nclude?<loader.hpp>
#i?nclude?<kernwin.hpp>????//"紳士的選擇"?IDA中的頭文件

??//重新標記入口點
bool?Dllmain(void*?hInstDLL,?int?reason,?int?reserved)
{return?true;}

char?comment[]?=?"Experimental?plugin";
char?help[]?=?"Experimental?plugin";
char?wanted_name[]?=?"ExpPlugin";
char?wanted_hotkey[]?=?"F11";

BYTE?rdtsc1[]={0x52,?0x0F,?0x31,?0x5A,?0x58};
BYTE?rdtsc2[]={0x50,?0x0F,?0x31,?0x58,?0x5A};????//就是些opcodes

??//plugin的initialization?procedure

根據不同的返回值,IDA可以加載或者不加載plugin。可能返回的值有:

????PLUGIN_SKIP?-?不加載返回值。

????PLUGIN_OK?-?喏,一個OK自然要加載plugin啦。

????PLUGIN_KEEP?-?不但要加載,還要常駐內存。

比如說,要想讓plugin只處理PE格式的文件,需要這樣寫initialization?procedure:

if?(inf.filetype?!=?f_PE)?return?PLUGIN_SKIP;
return?PLUGIN_OK;

這里就不研究那個inf結構體了,詳情請見SDK。我們這里總是要加載plugin的,所以代碼如下:

int?init(void)
{return?PLUGIN_OK;}

????//在unload?procedure里也是什么也不用干,空著它。

void?term(void)
{return;}

????//最后就是主要的run函數了
在研究主函數之前有興趣可以研究一下database的讀寫函數,還有獲取當前地址的函數,也即IDA中鼠標所放之處的地址:

?get_byte
?get_word
?get_long?-?從database中讀取各種長度字節。接受一個參數——listing中的地址。

?patch_byte
?patch_word
?patch_long?-?向database中寫入各種長度字節。兩個參數,第一個——地址,第二個——值。

可以猜到,名字里有byte的函數是用于(即接受或返回)字節的,word——字,而long——雙字。

?get_screen_ea?-?獲取當前地址的函數,當前地址就是它的返回值。

void?run(int?arg)
{BYTE?cb1;
??int?i,?tmp0;

?ea_t?CA?=?get_screen_ea();
?cb1=get_byte(CA);

????//pusha
????//popa
?if?(cb1==0x60?&&?get_byte(CA+1)==0x61)????//?pusha的opcode?-?60h,而popa?-?61h
???{patch_word(CA,?0x9090);
?????return;}

????//rdtsc
?if?(cb1==0x50)????//序列的第一個字節?-?push?eax的opcode
???{tmp0=1;
????for?(i=0;?i<5;?i++)????//數組中的其它字節,使用循環檢驗
????if?(get_byte(CA+i+1)!=rdtsc1[i])?{tmp0=0;?break;}

????if?(tmp0==1)
??????{patch_long(CA,?0x90909090);
????????patch_word(CA+4,?0x9090);
????????return;}}

?if?(cb1==0x52)
???{tmp0=1;
?????for?(i=0;?i<4;?i++)
?????if?(get_byte(CA+i+1)!=rdtsc2[i])?{tmp0=0;?break;}

?????if?(tmp0==1)
???????{patch_long(CA,?0x90909090);
?????????patch_word(CA+4,?0x9090);
?????????return;}}
};

????//現在放入前面講過的導出結構體。
????//一定要寫上extern?"C",使得linker能正確找到導出結構體的名字

extern?"C"?plugin_t?PLUGIN?=?{
IDP_INTERFACE_VERSION,
0,
init,
term,
run,
comment,
help,
wanted_name,
wanted_hotkey
};

????????現在我們來看如何將它編譯。以下是bat文件:

icl?-Gz?/I?<SDK的include目錄的路徑>?plugin.cpp?ida.lib?/link?/subsystem:windows?/DLL?/def:plugin.def?/out:exp.plw
del?"<IDA目錄路徑>\plugins\exp.plw"
copy?exp.plw?"<IDA目錄路徑>\plugins\"
PAUSE

我已經說過,此處是以Intel?C++為例的,如果用VC++的話,源代碼不用改,而編譯用的命令行則需要修改(不過就是把icl換成cl)。現在來詳細講一下。

-Gz告訴intel?complier,默認使用stdcall規則向函數傳遞參數。
/I?-?IDA?SDK的include目錄的路徑
plugin.cpp?-?plungin源代碼。
ida.lib?-?SDK的import?library,應該和源代碼放入一個目錄。
/link參數的后面是liner?options,就不用多說了。除了def文件。因為這里已經有源代碼和bat文件了,就需要生成def文件。

LIBRARY?exp
EXPORTS?PLUGIN

def文件指明需要導出PLUGIN結構體。一般來說,到這里就都完成了,plugin已經可以使用了,剩下的只是把它加到IDA里了。可以把它拷貝到IDA的plugins目錄里。但這還不夠,還需要配置一下。所有plugins的配置都保存在plugins目錄下plugins.cfg文件里。通常文件的起始處是注釋,后面就是plugin的配置了。為了將我們的exp.plw(Windows下的plugin的擴展名都是plw)加入進去,需要在文件末尾加入四個參數,順序?如下:

????plugin名??文件名??熱鍵??參數。

這里的參數就是傳給run函數的,我個人覺得沒什么用,所以就設為0。熱鍵嘛,可以設為F11,好像IDA用不到這個鍵。這樣,我們所添加的這一行就是下面這個樣子的:

????????expplugin????exp????F11????0

不主張在前面寫一個句點加一個逗號,因為那樣就成了注釋。喏,一般來說可以認為,mission?accomplished。剩下的就是啟動IDA,打開某個文件,那個文件里要有我們前面給出的指令(比如,可以自己立馬用ASM寫一個),然后進行檢查。如果沒有問題,就按下F11鍵或從菜單里選擇我們的plugin,這時那些指令就應該都被替換成nop了。當然,鼠標應該放在這些scrambled的指令(如果可以這樣說的話)的前面,當然這些都是些垃圾指令了。到這里就真的都完成了。
????????
[C]?dragon
www.wasm.ru/article.php?article=idaplugin

鄙人拙譯
http://greatdong.blog.edu.cn

總結

以上是生活随笔為你收集整理的IDA Plugin 编写基础的全部內容,希望文章能夠幫你解決所遇到的問題。

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