OllyDbg插件開發(fā)入門知識_第1頁
OllyDbg插件開發(fā)入門知識_第2頁
OllyDbg插件開發(fā)入門知識_第3頁
OllyDbg插件開發(fā)入門知識_第4頁
OllyDbg插件開發(fā)入門知識_第5頁
已閱讀5頁,還剩38頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

PAGEPAGE43OllyDbg插件開發(fā)入門0.11版目 錄前言 2一、前期準(zhǔn)備 31、OllyDbg插件工作原理 3從OllyDbg的角度 3從插件的角度 32、學(xué)習(xí)建議 43、開發(fā)資源與環(huán)境 44、必要的設(shè)置 5C++中的設(shè)置 5C++程序中的設(shè)置 5二、常用函數(shù) 61、回調(diào)函數(shù) 6必須的回調(diào)函數(shù) 6可選的回調(diào)函數(shù) 82、插件函數(shù) 12(1)注冊窗口類 12(2).ini文件交互 13(3)查詢系統(tǒng)信息 13(4).udd文件交互 143、其他函數(shù) 14三、實例分析 151、Hello,world 152、Command 183、Bookmark 28參考文獻(xiàn) 43好的開始,是成功的一半。一、前期準(zhǔn)備1、OllyDbg插件工作原理OllyDbg還具有良好的擴(kuò)展結(jié)構(gòu),允許用戶自行開發(fā)插件完成特定的工作。在開發(fā)插件之前,需要大致了解插件在OllyDbg中工作的方式。(DLL)OllyDbg使用。在OllyDbg主菜單plugin(請注意,如果這里的值是形如./plugin/)OllyDbg與插件是如何交互完成工作的?可以從兩個方面來看這個問題。OllyDbg的角度在OllyDbg的啟動過程中,有一步是檢查插件路徑下是否存在DLL文件。如果存在,逐一進(jìn)行如下掃描:DLL文件,找到其入口點通過回調(diào)函數(shù),獲取插件名稱、版本等信息通過回調(diào)函數(shù),對插件進(jìn)行初始化,包括申請資源、恢復(fù)全局參數(shù)等如果某個DLL文件無法順利執(zhí)行這三步,OllyDbg的啟動將失敗、報錯并退出。OllyDbg啟動以后,會一直維護(hù)插件的隊列,并在以下情況(但不僅限于這些情況)出現(xiàn)時向該隊列發(fā)送消息,或者直接調(diào)用插件中定義的函數(shù):用戶通過插件菜單或快捷鍵主動執(zhí)行插件某功能正在調(diào)試的程序狀態(tài)發(fā)生改變,例如載入、運行、暫停、結(jié)束、重啟等系統(tǒng)自身的啟動、關(guān)閉系統(tǒng)收到無法識別的消息(比如組合鍵)系統(tǒng)在配置文件中發(fā)現(xiàn)無法識別的數(shù)據(jù)最后,當(dāng)OllyDbg被關(guān)閉時,還會調(diào)用插件中的回調(diào)函數(shù),釋放插件申請到的資源,并將需要保存的參數(shù)、配置和附加信息分別予以保存。從插件的角度插件的工作可以分為以下幾類:搜集和整理調(diào)試過程中的信息供用戶參考增加一些輔助信息讓調(diào)試更加方便直接參與調(diào)試通過加載腳本程序,將一部分行為自動化OllyDbgOllyDbgOllyDbgPluginAPI來做到這些。WindowsOllyDbgOllyDbg加清晰。2、學(xué)習(xí)建議在學(xué)習(xí)開發(fā)OllyDbg插件的過程中,你也許會用到:Win32窗口程序開發(fā)的知識和經(jīng)驗OllyDbg功能的基本了解簡單的匯編語言知識現(xiàn)在假定你已經(jīng)具備了上述能力,下文的敘述將以此為基礎(chǔ)。OllyDbgPluginAPI手冊和實例源代碼。API手冊;最后,動手寫自己的插件。3、開發(fā)資源與環(huán)境為了開發(fā)OllyDbg插件,首先需要獲取插件開發(fā)包。下載地址是:\hhttp://www.ollydbg.de/plug110.zip這一開發(fā)包是針對OllyDbg1.10版的。雖然目前OllyDbg最新版是2.0,但作者已經(jīng)表明,1.10版是支持自主開發(fā)插件的最后一個版本。在這個開發(fā)包中,最重要的文件有三個:Plugins.hlp APIPlugin.h API定義的頭文件Ollydbg.lib 導(dǎo)入庫文件此外,作者還提供了兩個插件的代碼作為示范,一個是命令行插件,一個是書簽插件。我們將在第三部分仔細(xì)分析它們。接下來考慮開發(fā)環(huán)境。OllyDbgOlehBorlandC+5.5C++、Delpi、MASMBasic進(jìn)行開發(fā)。這里我們推薦使用VisualC++6.0進(jìn)行開發(fā)。理由如下:Win32APIC/C++,OllyDbgPluginAPIC++形式提供C/C++的,便于進(jìn)一步學(xué)習(xí)BorlandC++需要注意的是,在plug110.zip包中提供的Ollydbg.lib是無法直接用于VisualC++6.0的,原因是每個引出函數(shù)前面都多了一個下劃線[2]??梢栽谶@里下載到專為VisualC++6.0準(zhǔn)備的開發(fā)包:\h/showthread.php?t=31344或者你不想注冊的話,也可以到本文的更新頁面去看看:\h/2010/02/ollydbg_plugin/這個開發(fā)包并沒有對Ollydbg.lib進(jìn)行修改,但在Plugin.h中以#define#defineODBG_PlugindataODBG_Plugindata…… ……的方式使之能與Ollydbg.lib配合使用。4、必要的設(shè)置VisualC++中的設(shè)置Project→Addtoproject→FilesPlugin.hFileView→ResourceFilesAddFilesintoFolderOllydbg.libProject→Sttngs→/C+ProjetOptins/charunind類型,這是OllyDbg中的約定C++程序中的設(shè)置cpp文件中#include"Plugin.h"HINSTANCEg_hModule;BOOLAPIENTRYDllMain(HINSTANCEhModule,DWORDfdwReason,LPVOIDHINSTANCEg_hModule;BOOLAPIENTRYDllMain(HINSTANCEhModule,DWORDfdwReason,LPVOIDlpReserved){if(DLL_PROCESS_ATTACH==fdwReason){g_hModule=hModule;}returnTRUE;}也有的代碼中使用了這個入口點函數(shù):BOOLWINAPIDllEntryPoint(HINSTANCEhinstDLL,BOOLWINAPIDllEntryPoint(HINSTANCEhinstDLL,DWORDfdwReason,LPVOIDlpvReserved);它們的功能是一樣的。請確保它的存在,并將DLL模塊句柄保存到一個全局變量中,在后面將會用到。缺少此函數(shù)雖然能編譯通過,但會導(dǎo)致OllyDbg加載插件失敗。無他,惟手熟爾。二、常用函數(shù)1、回調(diào)函數(shù)回調(diào)函數(shù)(CallbackFunction)OllyDbg中OllyDbgOllyDbg管理插件的方式和途徑。ODBG_PluginOllyDbg使用的參數(shù)傳遞和堆棧cdecl,為了正常工作,所有回調(diào)函數(shù)在實現(xiàn)的時候,都需要申明這一方式。OllyDbg14212插件的具體需要有選擇地實現(xiàn)。必須的回調(diào)函數(shù)intODBG_Plugindata(char*shortname);intODBG_Plugindata(char*shortname);其中唯一的參數(shù)指向一個長度不超過31字節(jié)的已賦值字符串。Plugin.hv1.10110OllyDbgcharg_szPluginName[]="OurOllyDbgPlugin’sName";extcint_exportcdeclODBG_Plugindata(charshortname[32])charg_szPluginName[]="OurOllyDbgPlugin’sName";extcint_exportcdeclODBG_Plugindata(charshortname[32]){strcpy(shortname,g_szPluginName);returnPLUGIN_VERSION;}intODBG_Plugininit(intollydbgversion,HWNDhw,intODBG_Plugininit(intollydbgversion,HWNDhw,ulong*features);其中:ollydbgversion就是OllyDbg的版本號,用于與前面返回的PLUGIN_VERSION進(jìn)行比較;hw是OllyDbg主窗口的句柄,一般將其保存到一個全局變量中;features為將來的擴(kuò)展而保留,不使用它。HWNDg_hWndMain=NULL;extcint_exportcdeclODBG_Plugininit(intHWNDg_hWndMain=NULL;extcint_exportcdeclODBG_Plugininit(intollydbgversion,HWNDhw,ulong*features){if(ollydbgversion<PLUGIN_VERSION)return-1;g_hWndMain=hw;/*Dosomeinitializeworkshere.*//*Whenitfail,releaseresourcesandreturn-1*/Addtolist(0,0,”O(jiān)urplugin’sname.v1.00”);Addtolist(0,-1,”Copyright(C)2010Claud”)if(Plugingetvalue(VAL_RESTOREWINDOWPOS)!=0&&Pluginreadintfromini(hinst,//newline"RestoreOurPluginWindow",0)!=0)CreateOurPluginWindow();return0;}0102030405060708091011121314151617181920212223242526Registerpluginclass(ourwinclass,NULL,g_hModule,Ourwinproc)在12—Registerpluginclass(ourwinclass,NULL,g_hModule,Ourwinproc)Registerpluginclass()OllyDbgourwinclass返回類名,Ourwinproc是我們自己實現(xiàn)的類處理函數(shù)。這個函數(shù)失敗時返回一個負(fù)數(shù)值,此時應(yīng)該遵ODBG_Plugininit()的要求,以-1返回。1516Addtolist()函數(shù)將插件加載信息輸出到記錄窗口(logioOllDbgAlt+L0、1、-1分別表示正常顯示、高亮、低亮。OllyDbg所示兩行記錄格式,第一行說明插件名稱和版本,第二行說明版權(quán)信息。下面說明18—23行,它們不是必須存在的。23行,ifCreateOurPluginWindow(),這是一個我們自己定義的函數(shù),作用是創(chuàng)建插件的主窗口。ifollydbg.ini配置文件中是否有上一次插件關(guān)閉時加入的恢復(fù)插件窗口的標(biāo)記,它們的具體用法將在下一節(jié)“插件函數(shù)”中介紹。因此,18—23行的作用是重啟OllyDbg時根據(jù)設(shè)定恢復(fù)插件窗口??蛇x的回調(diào)函數(shù)12個可選的回調(diào)函數(shù)中,ODBG_Pluginmenu()ODBG_Pluginaction()往往也是需要定義的。intODBG_Pluginmenu(intorigin,chardata[4096],void*item);intODBG_Pluginmenu(intorigin,chardata[4096],void*item);OllyDbgorigin參數(shù)指明了創(chuàng)建菜單的命令來源于何處——插件菜單、反匯編窗口、斷點窗口等等。Plugin.hPM_API手冊中查詢。data指向一個最長為4096字節(jié)的字符串,它定義了菜單的項目和顯示格式。例如:strcpy(data,”0&Aaa,1&Bbb|2&Ccc”); 將創(chuàng)建三個菜單項Aaa、Bbb、Ccc,其中第二個和第三個之間有一條分欄線。而strcpy(data,”#A{0&Aaa,1&Bbb}”); 則創(chuàng)建一個彈出式菜單A,有兩個子項目。請注意這里的0、1、2等數(shù)字,它們并不會在菜單上顯示,而是作為項目的索引,將在ODBG_Pluginaction()中用到。它們的范圍應(yīng)在0—63之間。item過它,我們能更加細(xì)致地決定如何顯示菜單。最后,ODBG_Pluginmenu()成功時返回1,失敗時返回0。extcint_exportcdeclODBG_Pluginmenu(intorigin,extcint_exportcdeclODBG_Pluginmenu(intorigin,chardata[4096],void*item){if(origin!=PM_MAIN)return0;strcpy(data,"0&mainfunction|1&Help,2&About");return1;}extcint_exportcdeclextcint_exportcdeclODBG_Pluginmenu(intorigin,chardata[4096],void*item){t_dump*pd;switch(origin){casePM_MAIN:strcpy(data,"/*blahblahblah*/");return1;casePM_DISASM:pd=(t_dump*)item;if(NULL==pd)return0;if(/*pd->blahblahpd->blah*/){//sprintfblahblahblah}return1;caseblahblah:blah……return1;}return0;}voidODBG_Pluginaction(intvoidODBG_Pluginaction(intorigin,intaction,void*item);其中origin、item與ODBG_Pluginmenu()中相同。action就是上面定義項目時的那個索引數(shù)值。extcvoid_exportcdeclextcvoid_exportcdeclODBG_Pluginaction(intorigin,intaction,void*item){if(origin!=PM_MAIN)return;switch(action){{case0://mainfunctionbreak;case1://helpbreak;case2://aboutMessageBox(hwmain,"SomePluginv0.10\nWrittenbyClaud","About",MB_OK|MB_ICONINFORMATION);break;default:break;};}接下來我們簡單地看一看其他10個回調(diào)函數(shù)。voidODBG_Pluginmainloop(voidODBG_Pluginmainloop(DEBUG_EVENT*debugevent);在OllyDbg主窗口的每次窗口循環(huán)時,都會調(diào)用一下這個函數(shù)。因此可以把一些周期性的工作放在這里。但不推薦這樣做,因為這個調(diào)用并不是公平的,而且也會影響運行速度。其中參數(shù)dbgeet當(dāng)調(diào)試事件發(fā)生時,會指向事件的類型(參考N,否則為NULL。voidODBG_Pluginsaveudd(t_module*pmod,voidODBG_Pluginsaveudd(t_module*pmod,intismainmodule);這個函數(shù)用于將模塊或應(yīng)用程序相關(guān)的信息保存到相應(yīng)的.udd文件中去。請將這兩種情況區(qū)分開,分別存儲。intPluginsaverecord(ulongtag,ulongsize,void*data);其中pmod指向模塊描述符,intPluginsaverecord(ulongtag,ulongsize,void*data);tagOleh本人申請這一標(biāo)size(9dta既然我們可以向.udd文件寫入數(shù)據(jù),當(dāng)然也能讀取。下面這個函數(shù)就提供了這一功能。intODBG_Pluginuddrecord(t_module*pmod,intODBG_Pluginuddrecord(t_module*pmod,intismainmodule,ulongtag,ulongsize,void*data);事實上,OllyDbg在讀取.udd10,然后系統(tǒng)會將其傳遞給下一個插件。intODBG_Pluginshortcut(intorigin,intODBG_Pluginshortcut(intorigin,intctrl,intalt,intshift,intkey,void*item);OllyDbg10。extcint_exportcdeclextcint_exportcdeclODBG_Pluginshortcut(intorigin,intctrl,intalt,intshift,intkey,void*item){if(ctrl==0&&alt==1&&shift==0&&key==VK_F1){CreateOurPluginWindow();return1;}return0;}當(dāng)按下Alt+F1時,打開插件窗口。voidODBG_Pluginreset(void); 當(dāng)用戶打開一個新的程序調(diào)試,或者重新調(diào)試當(dāng)前的程序,OllyDbg會調(diào)用這個函數(shù)。可以在此重置插件的一些臨時數(shù)據(jù)。voidODBG_Pluginclose(void); OllyDbg時,OllyDbgWM_CLOSE消息還未00OllyDbgintPluginwriteinttoini(HINSTANCEdllinst,intPluginwriteinttoini(HINSTANCEdllinst,voidUnregisterpluginclass(char*classname);char*key,voidUnregisterpluginclass(char*classname);char*key,intvalue);來把關(guān)于插件的全局配置信息保存到ollydbg.ini文件中去,后者的具體用法將在下一部分說明。voidODBG_Plugindestroy(void);voidODBG_Plugindestroy(void);OllyDbgWM_DESTROYintODBG_Paused(intreason,t_reg*reg);intODBG_Paused(intreason,t_reg*reg);intODBG_Pausedex(intreason,intextdata,t_reg*reg,DEBUG_EVENT*debugevent);OllyDbg在調(diào)試暫停下來時調(diào)用它們。如果都定義了,后者的優(yōu)先級高于前者。intintODBG_Plugincmd(intreason,t_reg*reg,char*cmd);OllyDbg遇到條件記錄斷點時,將調(diào)用這個函數(shù),將命令傳遞給每個插件。插件必須回應(yīng)是否是傳給自己的,是則返回1,否則返回0。其中,reason是引起中斷的原因,reg指向引起中斷的寄存器或線程,cmd是要傳遞的命令。2、插件函數(shù)OllDbglginAPI函數(shù)是插件函數(shù)(PlugnFuntoOllDbg系統(tǒng)進(jìn)行交互。按功能將其分為四類。(1)注冊窗口類intRegisterpluginclass(char*classname,char*iconname,HINSTANCEdllinst,WNDPROCclassproc);intRegisterpluginclass(char*classname,char*iconname,HINSTANCEdllinst,WNDPROCclassproc);其中:classname32字節(jié)的字符串空間,在函數(shù)執(zhí)行后將返回類名;iconnameNULL時使用默認(rèn)的插件圖標(biāo);dllinstDllMain()中獲取;classproc是這個窗口類的窗口過程函數(shù),需要我們自己實現(xiàn)。0,失敗時返回-1。ODBG_Plugindestroy()ODBG_Plugindestroy()voidUnregisterpluginclass(char*classname); (2).ini文件交互OllyDbg使用ollydbg.ini文件來保存系統(tǒng)相關(guān)的設(shè)置,它提供了讀和寫該配置文件的接口。讀、寫都分為針對整數(shù)(int)和針對字符串(string)兩種類型,因此有四個函數(shù):intPluginwriteinttoini(HINSTANCEdllinst,char*key,intPluginwriteinttoini(HINSTANCEdllinst,char*key,intvalue);intPluginwritestringtoini(HINSTANCEdllinst,char*key,char*s);intPluginreadintfromini(HINSTANCEdllinst,char*key,intdef);intPluginreadstringfromini(HINSTANCEdllinst,char*key,char*s,char*def);其中,dllinst是插件實例句柄,key是要寫入或查詢的鍵名,value、s是要寫入的鍵值,def是默認(rèn)的值。對寫函數(shù),成功時返回1,失敗時返回0;對讀函數(shù),返回要讀取的值。(3)查詢系統(tǒng)信息OllyDbg提供了兩個函數(shù)用于獲取OllyDbg自身的信息。其中intPlugingetvalue(inttype); OllyDbgtype是要查閱的信息,有眾多的取值,具體含義在手冊[1]中有說明。另一個是t_statusGetstatus(void) 它返回正在被調(diào)試的進(jìn)程的狀態(tài)。返回值的含義如下:STAT_NONE 當(dāng)前沒有進(jìn)程被調(diào)試STAT_STOPPED進(jìn)程被掛起STAT_EVENT 正在處理調(diào)試時間,進(jìn)程暫停STAT_RUNNING進(jìn)程在運行STAT_FINISHED 進(jìn)程被終止STAT_CLOSINGTerminateProcess()被調(diào)用,等待確認(rèn)(4).udd文件交互intPluginsaverecord(ulongtag,ulongsize,void*data);OllyDbg使用.udd錄保存到d(前面已經(jīng)提到過intPluginsaverecord(ulongtag,ulongsize,void*data);這個函數(shù)僅當(dāng)位于回調(diào)函數(shù)ODBG_Pluginsaveudd()中時有效。3、其他函數(shù)除了回調(diào)函數(shù)和插件函數(shù),OllyDbg還提供了一百多個其他函數(shù)供插件開發(fā)使用,它們功能各異,是實現(xiàn)插件具體工作的重要組成。但出于以下原因,這里我們不再對它們一一進(jìn)行介紹:它們數(shù)量繁多,而且其中一部分并不常用到它們并不需要你理解或者記下來,而只需要要用的時候去查閱就可以了學(xué)習(xí)它們最好的方式不是講解,而是去讀他人的代碼或者自己動手去用我對它們的理解還不深,免得誤導(dǎo)大家但也有可能我會在本文檔的手續(xù)更新中加入對常用的函數(shù)的介紹。實踐出真知。三、實例分析和任何一種語言一樣,熟練地開發(fā)OllyDbg插件建立在大量的練習(xí)和閱讀他人源代碼的基礎(chǔ)之上。在本章,我們先自己寫一個Hello,world,然后分析兩份實例代碼。1、Hello,worldhello,worldinosHello,orl#include<windows.h>#include"Plugin.h"staticcharg_szPluginName[]="Hello,world!";staticHWNDg_hWndMain=NULL;staticHINSTANCEg_hModule=NULL;staticcharg_szHelloClass[32];staticHWNDCreateHelloWindow(void);LRESULTCALLBACKHelloWndProc(#include<windows.h>#include"Plugin.h"staticcharg_szPluginName[]="Hello,world!";staticHWNDg_hWndMain=NULL;staticHINSTANCEg_hModule=NULL;staticcharg_szHelloClass[32];staticHWNDCreateHelloWindow(void);LRESULTCALLBACKHelloWndProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam);BOOLAPIENTRYDllMain(HINSTANCEhModule,DWORDreason,LPVOIDlpReserved){if(DLL_PROCESS_ATTACH==reason){g_hModule=hModule;}returnTRUE;}001002003004005006007008009010011012013014015016017018019020021022023024025026027028 extcint_exportcdeclODBG_Plugindata(029 charshortname[32])030 {strcpy(shortname,g_szPluginName);returnPLUGIN_VERSION;033 }034035 extcint_exportcdeclODBG_Plugininit(036 intollydbgversion,HWNDhw,ulong*features)039 {040 intnRetCode;041042 if(ollydbgversion<PLUGIN_VERSION)043 return-1;044045 g_hWndMain=hw;046047 nRetCode=Registerpluginclass(048 g_szHelloClass,NULL,g_hModule,HelloWndProc);if(nRetCode<0)return-1;Addtolist(0,0,"Hello,World!v1.0");Addtolist(0,-1,"Copyright(C)2010Claud");return0;058 }059060 extcint_exportcdeclODBG_Pluginmenu(061 intorigin,chardata[4096],void*item)064 {065 if(PM_MAIN==origin)066 {strcpy(data,"0Hello|1About");return1;069 }070 return0;

}extcvoid_exportcdeclODBG_Pluginaction(intorigin,intaction,void*item){if(PM_MAIN==origin)switch(action){case0:CreateHelloWindow();break;case1:MessageBox(g_hWndMain,"WritenbyClaud",g_szPluginName,MB_OK);break;}}extcvoid_exportcdeclODBG_Plugindestroy(void){Unregisterpluginclass(g_szHelloClass);}LRESULTCALLBACKHelloWndProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam){RECTrc;PAINTSTRUCTps;HBRUSHhbr;HDCdc;switch(msg){caseWM_PAINT:dc=BeginPaint(hWnd,&ps);GetClientRect(hWnd,&rc);hbr=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));115116117FillRect(dc,&rc,hbr);TextOut(dc,100,60,//newline"Hello,world!",strlen("Hello,world!"));DeleteObject(hbr);118EndPaint(hWnd,&ps);119break;120default:121returnDefWindowProc(hWnd,msg,wParam,lParam);122}123return0;124}125126staticHWNDCreateHelloWindow(void)127{128HWNDhw;129hw=CreateWindow(130g_szHelloClass,131"Message",132WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,133400,400,300,200,134NULL,135NULL,136(HINSTANCE)Plugingetvalue(VAL_HINST),137NULL);138ShowWindow(hw,SW_SHOWNORMAL);139UpdateWindow(hw);140returnhw;141}—Registerpluginclass()將hbrBackground設(shè)為NULL了。2、CommandOllyDbgPluginCommandLineBookmarks(漢化版翻譯為“命令行”和“書簽。這一節(jié)和下一節(jié)我們就來分析它們。OllyDbg先熟悉一下它們的功能,這將會大大減少閱讀時理解的難度。Command.c和Cmdexec.cOllyDbg的交互,后者負(fù)責(zé)命令的解釋和執(zhí)行。這里我們只分析前者。不要被它的篇幅(九頁)API手冊吧。OllyDbg時,請保持大局觀。#defineSTRICT#include<windows.h>#include<stdio.h>#include"plugin.h"#defineVERSIONHI 1 //最高插件版本這兩行的定義非常奇#defineVERSIONLO 10 //最低插件版本而且似乎并沒有用到#defineDX370 //命令行窗口的寬#defineDY130 //命令行窗口的高//在.udd文件中記錄數(shù)據(jù)所需的插件唯一標(biāo)識符#defineTAG_CMDLINE 0x6C6D430AL#defineID_HWBOX 1001 //hwbox的標(biāo)識符#defineID_HWERR 1002 //hwerr的標(biāo)識符#defineNHIST 32 //歷史中最多記錄32條命staticHINSTANCEhinst; //DLL句柄staticHWND hwmain; //OllyDbg主窗口句柄staticHWND hwcmd; //命令行窗口staticHWND hwbox; //編輯和顯示歷史的下拉框staticHWND hwedit; //下拉框內(nèi)部的編輯控制staticWNDPROColdhweditproc;//hwedit原來的窗口過程staticHWND hwerr; //錯誤信息窗口staticchar cmdlinewinclass[32]; //命令行窗口類的名字staticint posx; //窗口的X坐標(biāo)staticint posy; //窗口的Y坐標(biāo)staticchar hist[NHIST][TEXTLEN]; //被保存的命令記staticint nhist; //歷史中現(xiàn)有命令記錄數(shù)量staticint poponstop;//暫停時將窗口前置//Execute()cmdexec.c中實現(xiàn),功能為解釋并執(zhí)行命令intExecute(char*text,char*answer);//將一行記錄插入到歷史的第一位,并刷新下拉框staticvoidAddline(char*text){inti;if(textNULL) //清除歷史{nhist=0;SetWindowText(hwerr,"");}elseif(text[0]!='\0'){for(i=nhist-1;i0i--) //移除歷史中重復(fù)的字符串{if(strcmp(hist[i],text)==0){}}//for

nhist--;if(i<nhist)memmove(hist[i],hist[i+1],(nhist-i)*TEXTLEN);if(nhistNHIST) //插入新的字符串nhist=NHIST-1;memmove(hist[1],hist[0],nhist*TEXTLEN);strcpy(hist[0],text);nhist++;}//endif(text[0]!='\0')if(hwcmd!=NULL)//將歷史記錄拷貝到下拉框{SendMessage(hwbox,CB_RESETCONTENT,0,0);for(i=0;i<nhist;i++)SendMessage(hwbox,CB_ADDSTRING,0,(LPARAM)hist[i]);if(text!=NULL&&nhist>0){SetWindowText(hwbox,text);SendMessage(hwbox,CB_SETEDITSEL,0,TEXTLEN);}}}//下拉框中編輯子窗口的窗口過程LRESULTCALLBACKEditsubclass(HWNDhw,UINTmsg,WPARAMwp,LPARAMlp){chars[TEXTLEN],answer[TEXTLEN];if(msg==WM_KEYDOWN){switch(wp){caseVK_RETURN:GetWindowText(hwbox,s,TEXTLEN);if(Execute(s,answer0) //命令被執(zhí)行Addline(s); //SetWindowText(hwerr,answer);SetForegroundWindow(hwcmd)//激活命令行窗口SetFocus(hwbox);return0;caseVK_ESCAPE:SetWindowText(hwbox //清除編輯框文本和信息SetWindowText(hwerr,"");return0;default:break;}//switch}//endif(msg==WM_KEYDOWN)returnCallWindowProc(oldhweditproc,hw,msg,wp,lp);//oldhweditproc處理}//命令行窗口的窗口過程LRESULTCALLBACKCmdlinewinproc(HWNDhw,UINTmsg,WPARAMwp,LPARAMlp){RECTrc;PAINTSTRUCTps;HBRUSHhbr;HDCdc;switch(msg){caseWM_DESTROY:hwcmd=NULL;break;caseWM_SETFOCUS:break;caseWM_CLOSE: //獲取命令行窗口的當(dāng)前位置并保存到.ini文件中GetWindowRect(hw,&rc);posx=rc.left;posy=rc.top;Pluginwriteinttoini(hinst,"CommandlinewindowX",rc.left);Pluginwriteinttoini(hinst,"CommandlinewindowY",rc.top);returnDefWindowProc(hw,msg,wp,lp);caseWM_PAINT: //將命令行窗口的背景用默認(rèn)按鈕顏色填充dc=BeginPaint(hw,&ps);GetClientRect(hw,&rc);hbr=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));FillRect(dc,&rc,hbr);DeleteObject(hbr);EndPaint(hw,&ps);break;default:returnDefWindowProc(hw,msg,wp,lp);}return0;}//創(chuàng)建命令行窗口。如果窗口已經(jīng)存在,將它提到前臺。staticHWNDCreatecmdlinewindow(void){HFONThf;RECTrc;POINTpt;if(hwcmd==NULL)//窗口還未出現(xiàn),創(chuàng)建之{hwcmd=CreateWindow(cmdlinewinclass,"Commandline",WS_POPUPWINDOW|WS_CAPTION|WS_VISIBLE|DS_3DLOOK,posx,posy,DX,DY,hwmain,NULL,(HINSTANCE)Plugingetvalue(VAL_HINST),NULL);if(hwcmd==NULL)returnNULL;GetClientRect(hwcmd,&rc);//創(chuàng)建包含歷史記錄的編輯子窗口hwbox=CreateWindow("COMBOBOX","",WS_CHILD|WS_TABSTOP|WS_BORDER|WS_VISIBLE|WS_VSCROLL|CBS_SIMPLE|CBS_HASSTRINGS|CBS_NOINTEGRALHEIGHT|CBS_AUTOHSCROLL|CBS_DISABLENOSCROLL,5,5,rc.right-10,rc.bottom-32,hwcmd,(HMENU)ID_HWBOX,(HINSTANCE)Plugingetvalue(VAL_HINST),NULL);//OllyDbg默認(rèn)字體,hf=((HFONT*)Plugingetvalue(VAL_FONTS))[Plugingetvalue(VAL_DEFFONT)];SendMessage(hwbox,WM_SETFONT,(WPARAM)hf,1);//OllyDbg默認(rèn)寬度SendMessage(hwbox,CB_LIMITTEXT,TEXTLEN-1,1);//為了攔截返回的鍵,將編輯子窗口作為下拉框里面的子類pt.x=pt.y=1;hwedit=ChildWindowFromPoint(hwbox,pt);oldhweditproc=hwedit,GWL_WNDPROC,(long)Editsubclass);//創(chuàng)建文本子窗口顯示錯誤信息hwerr=CreateWindow("STATIC","",WS_CHILD|WS_VISIBLE|SS_LEFT|SS_SUNKEN,5,rc.bottom-22,rc.right-10,17,hwcmd,(HMENU)ID_HWERR,(HINSTANCE)Plugingetvalue(VAL_HINST),NULL);hf=((HFONT*)Plugingetvalue(VAL_FONTS))[SYSFONT];SendMessage(hwerr,WM_SETFONT,(WPARAM)hf,1);Addline(""); //刷新下拉框}//函數(shù)起始處那個if//把窗口拉到前臺來SetForegroundWindow(hwcmd);SetFocus(hwbox);returnhwcmd;}BOOLWINAPIDllEntryPoint(HINSTANCEhi,DWORDreason,LPVOIDreserved){if(reason==DLL_PROCESS_ATTACH)hinst=hi;return1;}extcint_exportcdeclODBG_Plugindata(charshortname[32]){strcpy(shortname,"Commandline");returnPLUGIN_VERSION;}extcint_exportcdeclODBG_Plugininit(intollydbgversion,HWNDhw,ulong*features){intmaxx,maxy;if(ollydbgversion<PLUGIN_VERSION)return-1;hwmain=hw;if(Registerpluginclass(cmdlinewinclass,NULL,hinst,Cmdlinewinproc)<0)return-1;Addtolist(0,0,"Commandlinepluginv1.10");Addtolist(0,-1,"WrittenbyOlehYuschuk");//從.ini文件獲取命令行窗口最后的位置,并確認(rèn)窗口是完全可見的posx=Pluginreadintfromini(hinst,"CommandlinewindowX",CW_USEDEFAULT);posy=Pluginreadintfromini(hinst,"CommandlinewindowY",CW_USEDEFAULT);maxx=GetSystemMetrics(SM_CXSCREEN)-DX;if(posx>maxx)posx=maxx;if(posx<0)posx=0;maxy=GetSystemMetrics(SM_CYSCREEN)-DY;if(posy>maxy)posy=maxy;if(posy<0)posy=0;if(Plugingetvalue(VAL_RESTOREWINDOWPOS)!=0&&Pluginreadintfromini(hinst,"Restorecommandlinewindow",0)!=0)Createcmdlinewindow();return0;}//當(dāng)被調(diào)試的程序停止下來時,將命令行窗口置于前臺extcvoid_exportcdeclODBG_Pluginmainloop(DEBUG_EVENT*debugevent){t_statusstatus;if(hwcmd!=NULL){status=Getstatus();if(status==STAT_NONE||status==STAT_RUNNING)poponstop=1;elseif(poponstop!=0&&(status==STAT_STOPPED||status==STAT_FINISHED)){SetForegroundWindow(hwcmd);SetFocus(hwbox);poponstop=0;}}}//將命令歷史保存到.udd文件中extcvoid_exportcdeclODBG_Pluginsaveudd(t_module*pmod,intismainmodule){inti;if(ismainmodule==0)return; //僅將歷史保存在主文件中//從.udd文件中恢復(fù)數(shù)據(jù)時,最后保存的歷史條目將成為第一條for(i=nhist-1;i>=0;i--){Pluginsaverecord(TAG_CMDLINE,strlen(hist[i])+1,hist[i]);}}//從.udd文件中恢復(fù)數(shù)據(jù)extcint_exportcdeclODBG_Pluginuddrecord(t_module*pmod,intismainmodule,ulongtag,ulongsize,void*data){if(tag!=TAG_CMDLINE)return0;if(ismainmodule==0)return0;Addline((char*)data);return1;}extcint_exportcdeclODBG_Pluginmenu(intorigin,chardata[4096],void*item){if(origin!=PM_MAIN)return0;strcpy(data,"0&Commandline\tAlt+F1|1&Help,2&About");return1;}extcvoid_exportcdeclODBG_Pluginaction(intorigin,intaction,void*item){if(origin!=PM_MAIN)return;switch(action){case0: //"Commandline"Createcmdlinewindow();break;case1: //"Help"break;case2: //"About"MessageBox(hwmain,"Commandlinepluginv1.10\nWrittenbyOlehYuschuk","Commandline",MB_OK|MB_ICONINFORMATION);break;default:break;}}//命令行窗口識別全局快捷鍵Alt+F1extcint_exportcdeclODBG_Pluginshortcut(intorigin,intctrl,intalt,intshift,intkey,void*item){if(ctrl==0&&alt==1&&shift==0&&key==VK_F1){Createcmdlinewindow();return1;}return0;}//用戶打開新的程序或者重新調(diào)試當(dāng)前程序時,清除命令行歷史。extcvoid_exportcdeclODBG_Pluginreset(void){poponstop=1;Addline(NULL);}extcint_exportcdeclODBG_Pluginclose(void){RECTrc;//為了自動恢復(fù),在.ini文件中標(biāo)識命令行窗口是否被打開并保存坐標(biāo)Pluginwriteinttoini(hinst,"Restorecommandlinewindow",hwcmd!=NULL);if(hwcmdNULL){GetWindowRect(hwcmd,&rc);Pluginwriteinttoini(hinst,"CommandlinewindowX",rc.left);Pluginwriteinttoini(hinst,"CommandlinewindowY",rc.top);}return0;}extcvoid_exportcdeclODBG_Plugindestroy(void){Unregisterpluginclass(cmdlinewinclass);}extcint_exportcdeclODBG_Plugincmd(intreason,extcint_exportcdeclODBG_Plugincmd(intreason,t_reg*reg,char*cmd){charanswer[TEXTLEN];//命令行插件只接受以句點(.)開頭的命令if(cmd==NULL||cmd[0]!='.'||cmd[1]=='\0')return0;if(Execute(cmd+1,answer)==0) //命令被執(zhí)行Addline(cmd+1); //當(dāng)命令有效時,添加一行記if(hwmain!=NULL&&hwerr!=NULL)SetWindowText(hwerr,answer);return1;}3、Bookmark和Command相比,Bookmark更長了——因為所有功能都在這一個文件中實現(xiàn)。閱讀bookmark.c是很劃得來的,我們至少可以從中學(xué)到以下內(nèi)容:有序表的定義、構(gòu)造、操作、使用如何創(chuàng)建多種樣式的菜單以及與數(shù)據(jù)相關(guān)的菜單項CPU窗口交互更復(fù)雜但更接近于實際的消息處理過程OllyDbg中對窗口繪制的支持和簡化如何在內(nèi)存中讀取代碼并將其反匯編#include<windows.h>#include<stdio.h>#include<string.h>#include"plugin.h"HINSTANCE hinst;#include<windows.h>#include<stdio.h>#include<string.h>#include"plugin.h"HINSTANCE hinst;HWND hwmain;char bookmarkwinclass[32];//自己定義有序表//表中須有雙字型的address、size、typetypedefstructt_bookmark{ulongindex;//書簽的索引,0—9ulongsize;//索引大小,在這里始終為1ulongtype;//記錄類型,始終為0ulongaddr;//書簽的地址}t_bookmark;t_table bookmark; //有序表描述符intBookmarksortfunc(t_bookmark*b1,t_bookmark*b2,intsort);LRESULTCALLBACKBookmarkwinproc(HWNDhw,UINTmsg,WPARAMwp,LPARAMlp);intBookmarkgettext(char*s,char*mask,int*select,t_sortheader*ph,intcolumn);voidCreatebookmarkwindow(void);BOOLWINAPIDllEntryPoint(HINSTANCEhi,DWORDreason,LPVOIDreserved){if(reason==DLL_PROCESS_ATTACH)hinst=hi;return1;}extcint_exportcdeclODBG_Plugindata(charshortname[32]){strcpy(shortname,"Bookmarks");returnPLUGIN_VERSION;}extcint_exportcdeclODBG_Plugininit(intollydbgversion,HWNDhw,ulong*features){if(ollydbgversion<PLUGIN_VERSION)return-1;hwmain=hw;//初始化有序表描述符bookmarkif(if({}

Createsorteddata(&(bookmark.data), //有序數(shù)據(jù)的描述符"Bookmarks", //有序數(shù)據(jù)的名稱sizeof(t_bookmark), //表項大小10, //初始化表項數(shù)(SORTFUNC*)Bookmarksortfunc, //自定義的排序函數(shù)NULL //自定義的析構(gòu)函數(shù))!=0) //初始化失敗,未分配空間return-1; //因此直接返回,無需回收Registerpluginclass(bookmarkwinclass,NULL,hinst,Bookmarkwinproc0 //注冊窗口類失敗Destroysorteddata( //注銷有序表描述符&(bookmark.data)); //并釋放分配的內(nèi)存return-1;Addtolist(0,0,"Bookmarkssamplepluginv1.10(plugindemo)");Addtolist(0,-1,"Copyright(C)2001-2004OlehYuschuk");if(Plugingetvalue(VAL_RESTOREWINDOWPOS)!=0&&Pluginreadintfromini(hinst,"Restorebookmarkswindow",0)!=0)Createbookmarkwindow();return0;}//自定義的排序函數(shù)//b1b21;b1b20;b1b2,返回-1intBookmarksortfunc(t_bookmark*b1,t_bookmark*b2,intsort){inti=0;if(sort1)//addr排序{if(b1->addr<b2->addr)i=-1;elseif(b1->addr>b2->addr)i=1;}if(i0) //addrindex排序{if(b1->index<b2->index)i=-1;elseif(b1->index>b2->index)i=1;}returni;}//如果一個窗口用來顯示有序表,應(yīng)當(dāng)把它收到的//絕大部分消息傳遞給Tablefunction()先處理LRESULTCALLBACKBookmarkwinproc(HWNDhw,UINTmsg,WPARAMwp,LPARAMlp){inti,shiftkey,controlkey;HMENUmenu;t_bookmark*pb;switch(msg){//Windows消息caseWM_DESTROY:caseWM_MOUSEMOVE:caseWM_LBUTTONDOWN:caseWM_LBUTTONDBLCLK:caseWM_LBUTTONUP:caseWM_RBUTTONDOWN:caseWM_RBUTTONDBLCLK:caseWM_HSCROLL:caseWM_VSCROLL:caseWM_TIMER:caseWM_SYSKEYDOWN:Tablefunction(&bookmark,hw,msg,wp,lp);//只退出不返回,將消息再傳給最后的DefMDIChildProc()break;//滾動或選擇的消息caseWM_USER_SCR:caseWM_USER_VABS:caseWM_USER_VREL:caseWM_USER_VBYTE:caseWM_USER_STS:caseWM_USER_CNTS:caseWM_USER_CHGS://這些消息給Tablefunction()處理完就行了returnTablefunction(&bookmark,hw,msg,wp,lp);//MDIWM_WINDOWPOSCHANGED消息caseWM_WINDOWPOSCHANGED:returnTablefunction(&bookmark,hw,msg,wp,lp);caseWM_USER_MENU:menu=CreatePopupMenu();//定位被選的書簽,需使用Getsortedbyselection()//因為有序數(shù)據(jù)采用了特殊的排序索引表pb=(t_bookmark*)Getsortedbyselection(&(bookmark.data),bookmark.data.selected);if(menu!=NULL&&pbNULL) //構(gòu)建彈出菜單{AppendMenu(menu,MF_STRING,1,"&Follow\tEnter");AppendMenu(menu,MF_STRING,2,"&Delete\tDel");}//這里也要讓Tablefunction()先處理一下//它的返回值需要是依據(jù)消息類型而定的i=Tablefunction(&bookmark,hw,WM_USER_MENU,0,(LPARAM)menu);if(menu!=NULL)DestroyMenu(menu);if(i1) //選擇了跟隨//Setcpu()CPU窗口轉(zhuǎn)到指定的指令Setcpu(0,pb->addr,0,0,CPU_ASMHIST|CPU_ASMCENTER|CPU_ASMFOCUS);elseif(i==2)//選擇了刪除{Deletesorteddata(&(bookmark.data),pb->index);//需要自己更新窗口InvalidateRect(hw,NULL,FALSE);};return0;caseWM_KEYDOWN:shiftkey=GetKeyState(VK_SHIFT)&0x8000;controlkey=GetKeyState(VK_CONTROL)&0x8000;if(wp==VK_RETURN&&shiftkey==0&&controlkey==0){ //回車鍵,跟隨pb=(t_bookmark*)Getsortedbyselection(&(bookmark.data),bookmark.data.selected);if(pb!=NULL)Setcpu(0,pb->addr,0,0,CPU_ASMHIST|CPU_ASMCENTER|CPU_ASMFOCUS);}elseif(wp==VK_DELETE&&shiftkey==0&&controlkey==0){ //DEL鍵,刪除pb=(t_bookmark*)Getsortedbyselection(&(bookmark.data),bookmark.data.selected);if(pb!=NULL){Deletesorteddata(&(bookmark.data),pb->index);InvalidateRect(hw,NULL,FALSE);}}elseTablefunction(&bookmark,hw,msg,wp,lp);break;caseWM_USER_DBLCLK: //雙擊,跟隨pb=(t_bookmark*)Getsortedbyselection(&(bookmark.data),bookmark.data.selected);if(pb!=NULL)Setcpu(0,pb->addr,0,0,CPU_ASMHIST|CPU_ASMCENTER|CPU_ASMFOCUS);return1;caseWM_USER_CHALL:caseWM_USER_CHMEM://重繪窗口InvalidateRect(hw,NULL,FALSE);return0;caseWM_PAINT://OllyDbgPainttable()來繪制Painttable(hw,&bookmark,Bookmarkgettext);return0;default:break;}returnDefMDIChildProc(hw,msg,wp,lp);}extcvoid_exportcdeclODBG_Pluginmainloop(DEBUG_EVENT*debugevent){}#defineTAG_BOOKMARK 0x236D420ALextcvoid_exportcdeclODBG_Pluginsaveudd(t_module*pmod,intismainmodule){inti;ulongdata[2];t_bookmark*pb;if(ismainmodule==0)return;pb=(t_bookmark*)bookmark.data.data;for(i=0;i<bookmark.data.n;i++,pb++){data[0]=pb->index;data[1]=pb->addr;Pluginsaverecord(TAG_BOOKMARK,2*sizeof(ulong),data);}}extcint_exportcdeclODBG_Pluginuddrecord(t_module*pmod,intismainmodule,ulongtag,ulongsize,void*data){t_bookmarkmark;if(ismainmodule==0)return0;if(tag!=TAG_BOOKMARK)return0;mark.index=((ulong*)data)[0];mark.size=1;mark.type=0;mark.addr=((ulong*)data)[1];//將從.udd文件中讀取的記錄添加到列表中return1;}extcint_exportcdeclODBG_Pluginmenu(intorigin,chardata[4096],void*item){inti,n;t_bookmark*

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論