




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
PAGEPAGE43OllyDbg插件開發(fā)入門0.11版目 錄前言 2一、前期準備 31、OllyDbg插件工作原理 3從OllyDbg的角度 3從插件的角度 32、學習建議 43、開發(fā)資源與環(huán)境 44、必要的設置 5C++中的設置 5C++程序中的設置 5二、常用函數 61、回調函數 6必須的回調函數 6可選的回調函數 82、插件函數 12(1)注冊窗口類 12(2).ini文件交互 13(3)查詢系統信息 13(4).udd文件交互 143、其他函數 14三、實例分析 151、Hello,world 152、Command 183、Bookmark 28參考文獻 43好的開始,是成功的一半。一、前期準備1、OllyDbg插件工作原理OllyDbg還具有良好的擴展結構,允許用戶自行開發(fā)插件完成特定的工作。在開發(fā)插件之前,需要大致了解插件在OllyDbg中工作的方式。(DLL)OllyDbg使用。在OllyDbg主菜單plugin(請注意,如果這里的值是形如./plugin/)OllyDbg與插件是如何交互完成工作的?可以從兩個方面來看這個問題。OllyDbg的角度在OllyDbg的啟動過程中,有一步是檢查插件路徑下是否存在DLL文件。如果存在,逐一進行如下掃描:DLL文件,找到其入口點通過回調函數,獲取插件名稱、版本等信息通過回調函數,對插件進行初始化,包括申請資源、恢復全局參數等如果某個DLL文件無法順利執(zhí)行這三步,OllyDbg的啟動將失敗、報錯并退出。OllyDbg啟動以后,會一直維護插件的隊列,并在以下情況(但不僅限于這些情況)出現時向該隊列發(fā)送消息,或者直接調用插件中定義的函數:用戶通過插件菜單或快捷鍵主動執(zhí)行插件某功能正在調試的程序狀態(tài)發(fā)生改變,例如載入、運行、暫停、結束、重啟等系統自身的啟動、關閉系統收到無法識別的消息(比如組合鍵)系統在配置文件中發(fā)現無法識別的數據最后,當OllyDbg被關閉時,還會調用插件中的回調函數,釋放插件申請到的資源,并將需要保存的參數、配置和附加信息分別予以保存。從插件的角度插件的工作可以分為以下幾類:搜集和整理調試過程中的信息供用戶參考增加一些輔助信息讓調試更加方便直接參與調試通過加載腳本程序,將一部分行為自動化OllyDbgOllyDbgOllyDbgPluginAPI來做到這些。WindowsOllyDbgOllyDbg加清晰。2、學習建議在學習開發(fā)OllyDbg插件的過程中,你也許會用到:Win32窗口程序開發(fā)的知識和經驗OllyDbg功能的基本了解簡單的匯編語言知識現在假定你已經具備了上述能力,下文的敘述將以此為基礎。OllyDbgPluginAPI手冊和實例源代碼。API手冊;最后,動手寫自己的插件。3、開發(fā)資源與環(huán)境為了開發(fā)OllyDbg插件,首先需要獲取插件開發(fā)包。下載地址是:\hhttp://www.ollydbg.de/plug110.zip這一開發(fā)包是針對OllyDbg1.10版的。雖然目前OllyDbg最新版是2.0,但作者已經表明,1.10版是支持自主開發(fā)插件的最后一個版本。在這個開發(fā)包中,最重要的文件有三個:Plugins.hlp APIPlugin.h API定義的頭文件Ollydbg.lib 導入庫文件此外,作者還提供了兩個插件的代碼作為示范,一個是命令行插件,一個是書簽插件。我們將在第三部分仔細分析它們。接下來考慮開發(fā)環(huán)境。OllyDbgOlehBorlandC+5.5C++、Delpi、MASMBasic進行開發(fā)。這里我們推薦使用VisualC++6.0進行開發(fā)。理由如下:Win32APIC/C++,OllyDbgPluginAPIC++形式提供C/C++的,便于進一步學習BorlandC++需要注意的是,在plug110.zip包中提供的Ollydbg.lib是無法直接用于VisualC++6.0的,原因是每個引出函數前面都多了一個下劃線[2]。可以在這里下載到專為VisualC++6.0準備的開發(fā)包:\h/showthread.php?t=31344或者你不想注冊的話,也可以到本文的更新頁面去看看:\h/2010/02/ollydbg_plugin/這個開發(fā)包并沒有對Ollydbg.lib進行修改,但在Plugin.h中以#define#defineODBG_PlugindataODBG_Plugindata…… ……的方式使之能與Ollydbg.lib配合使用。4、必要的設置VisualC++中的設置Project→Addtoproject→FilesPlugin.hFileView→ResourceFilesAddFilesintoFolderOllydbg.libProject→Sttngs→/C+ProjetOptins/charunind類型,這是OllyDbg中的約定C++程序中的設置cpp文件中#include"Plugin.h"HINSTANCEg_hModule;BOOLAPIENTRYDllMain(HINSTANCEhModule,DWORDfdwReason,LPVOIDHINSTANCEg_hModule;BOOLAPIENTRYDllMain(HINSTANCEhModule,DWORDfdwReason,LPVOIDlpReserved){if(DLL_PROCESS_ATTACH==fdwReason){g_hModule=hModule;}returnTRUE;}也有的代碼中使用了這個入口點函數:BOOLWINAPIDllEntryPoint(HINSTANCEhinstDLL,BOOLWINAPIDllEntryPoint(HINSTANCEhinstDLL,DWORDfdwReason,LPVOIDlpvReserved);它們的功能是一樣的。請確保它的存在,并將DLL模塊句柄保存到一個全局變量中,在后面將會用到。缺少此函數雖然能編譯通過,但會導致OllyDbg加載插件失敗。無他,惟手熟爾。二、常用函數1、回調函數回調函數(CallbackFunction)OllyDbg中OllyDbgOllyDbg管理插件的方式和途徑。ODBG_PluginOllyDbg使用的參數傳遞和堆棧cdecl,為了正常工作,所有回調函數在實現的時候,都需要申明這一方式。OllyDbg14212插件的具體需要有選擇地實現。必須的回調函數intODBG_Plugindata(char*shortname);intODBG_Plugindata(char*shortname);其中唯一的參數指向一個長度不超過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進行比較;hw是OllyDbg主窗口的句柄,一般將其保存到一個全局變量中;features為將來的擴展而保留,不使用它。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是我們自己實現的類處理函數。這個函數失敗時返回一個負數值,此時應該遵ODBG_Plugininit()的要求,以-1返回。1516Addtolist()函數將插件加載信息輸出到記錄窗口(logioOllDbgAlt+L0、1、-1分別表示正常顯示、高亮、低亮。OllyDbg所示兩行記錄格式,第一行說明插件名稱和版本,第二行說明版權信息。下面說明18—23行,它們不是必須存在的。23行,ifCreateOurPluginWindow(),這是一個我們自己定義的函數,作用是創(chuàng)建插件的主窗口。ifollydbg.ini配置文件中是否有上一次插件關閉時加入的恢復插件窗口的標記,它們的具體用法將在下一節(jié)“插件函數”中介紹。因此,18—23行的作用是重啟OllyDbg時根據設定恢復插件窗口??蛇x的回調函數12個可選的回調函數中,ODBG_Pluginmenu()ODBG_Pluginaction()往往也是需要定義的。intODBG_Pluginmenu(intorigin,chardata[4096],void*item);intODBG_Pluginmenu(intorigin,chardata[4096],void*item);OllyDbgorigin參數指明了創(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等數字,它們并不會在菜單上顯示,而是作為項目的索引,將在ODBG_Pluginaction()中用到。它們的范圍應在0—63之間。item過它,我們能更加細致地決定如何顯示菜單。最后,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就是上面定義項目時的那個索引數值。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個回調函數。voidODBG_Pluginmainloop(voidODBG_Pluginmainloop(DEBUG_EVENT*debugevent);在OllyDbg主窗口的每次窗口循環(huán)時,都會調用一下這個函數。因此可以把一些周期性的工作放在這里。但不推薦這樣做,因為這個調用并不是公平的,而且也會影響運行速度。其中參數dbgeet當調試事件發(fā)生時,會指向事件的類型(參考N,否則為NULL。voidODBG_Pluginsaveudd(t_module*pmod,voidODBG_Pluginsaveudd(t_module*pmod,intismainmodule);這個函數用于將模塊或應用程序相關的信息保存到相應的.udd文件中去。請將這兩種情況區(qū)分開,分別存儲。intPluginsaverecord(ulongtag,ulongsize,void*data);其中pmod指向模塊描述符,intPluginsaverecord(ulongtag,ulongsize,void*data);tagOleh本人申請這一標size(9dta既然我們可以向.udd文件寫入數據,當然也能讀取。下面這個函數就提供了這一功能。intODBG_Pluginuddrecord(t_module*pmod,intODBG_Pluginuddrecord(t_module*pmod,intismainmodule,ulongtag,ulongsize,void*data);事實上,OllyDbg在讀取.udd10,然后系統會將其傳遞給下一個插件。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;}當按下Alt+F1時,打開插件窗口。voidODBG_Pluginreset(void); 當用戶打開一個新的程序調試,或者重新調試當前的程序,OllyDbg會調用這個函數??梢栽诖酥刂貌寮囊恍┡R時數據。voidODBG_Pluginclose(void); OllyDbg時,OllyDbgWM_CLOSE消息還未00OllyDbgintPluginwriteinttoini(HINSTANCEdllinst,intPluginwriteinttoini(HINSTANCEdllinst,voidUnregisterpluginclass(char*classname);char*key,voidUnregisterpluginclass(char*classname);char*key,intvalue);來把關于插件的全局配置信息保存到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在調試暫停下來時調用它們。如果都定義了,后者的優(yōu)先級高于前者。intintODBG_Plugincmd(intreason,t_reg*reg,char*cmd);OllyDbg遇到條件記錄斷點時,將調用這個函數,將命令傳遞給每個插件。插件必須回應是否是傳給自己的,是則返回1,否則返回0。其中,reason是引起中斷的原因,reg指向引起中斷的寄存器或線程,cmd是要傳遞的命令。2、插件函數OllDbglginAPI函數是插件函數(PlugnFuntoOllDbg系統進行交互。按功能將其分為四類。(1)注冊窗口類intRegisterpluginclass(char*classname,char*iconname,HINSTANCEdllinst,WNDPROCclassproc);intRegisterpluginclass(char*classname,char*iconname,HINSTANCEdllinst,WNDPROCclassproc);其中:classname32字節(jié)的字符串空間,在函數執(zhí)行后將返回類名;iconnameNULL時使用默認的插件圖標;dllinstDllMain()中獲?。籧lassproc是這個窗口類的窗口過程函數,需要我們自己實現。0,失敗時返回-1。ODBG_Plugindestroy()ODBG_Plugindestroy()voidUnregisterpluginclass(char*classname); (2).ini文件交互OllyDbg使用ollydbg.ini文件來保存系統相關的設置,它提供了讀和寫該配置文件的接口。讀、寫都分為針對整數(int)和針對字符串(string)兩種類型,因此有四個函數: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是默認的值。對寫函數,成功時返回1,失敗時返回0;對讀函數,返回要讀取的值。(3)查詢系統信息OllyDbg提供了兩個函數用于獲取OllyDbg自身的信息。其中intPlugingetvalue(inttype); OllyDbgtype是要查閱的信息,有眾多的取值,具體含義在手冊[1]中有說明。另一個是t_statusGetstatus(void) 它返回正在被調試的進程的狀態(tài)。返回值的含義如下:STAT_NONE 當前沒有進程被調試STAT_STOPPED進程被掛起STAT_EVENT 正在處理調試時間,進程暫停STAT_RUNNING進程在運行STAT_FINISHED 進程被終止STAT_CLOSINGTerminateProcess()被調用,等待確認(4).udd文件交互intPluginsaverecord(ulongtag,ulongsize,void*data);OllyDbg使用.udd錄保存到d(前面已經提到過intPluginsaverecord(ulongtag,ulongsize,void*data);這個函數僅當位于回調函數ODBG_Pluginsaveudd()中時有效。3、其他函數除了回調函數和插件函數,OllyDbg還提供了一百多個其他函數供插件開發(fā)使用,它們功能各異,是實現插件具體工作的重要組成。但出于以下原因,這里我們不再對它們一一進行介紹:它們數量繁多,而且其中一部分并不常用到它們并不需要你理解或者記下來,而只需要要用的時候去查閱就可以了學習它們最好的方式不是講解,而是去讀他人的代碼或者自己動手去用我對它們的理解還不深,免得誤導大家但也有可能我會在本文檔的手續(xù)更新中加入對常用的函數的介紹。實踐出真知。三、實例分析和任何一種語言一樣,熟練地開發(fā)OllyDbg插件建立在大量的練習和閱讀他人源代碼的基礎之上。在本章,我們先自己寫一個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設為NULL了。2、CommandOllyDbgPluginCommandLineBookmarks(漢化版翻譯為“命令行”和“書簽。這一節(jié)和下一節(jié)我們就來分析它們。OllyDbg先熟悉一下它們的功能,這將會大大減少閱讀時理解的難度。Command.c和Cmdexec.cOllyDbg的交互,后者負責命令的解釋和執(zhí)行。這里我們只分析前者。不要被它的篇幅(九頁)API手冊吧。OllyDbg時,請保持大局觀。#defineSTRICT#include<windows.h>#include<stdio.h>#include"plugin.h"#defineVERSIONHI 1 //最高插件版本這兩行的定義非常奇#defineVERSIONLO 10 //最低插件版本而且似乎并沒有用到#defineDX370 //命令行窗口的寬#defineDY130 //命令行窗口的高//在.udd文件中記錄數據所需的插件唯一標識符#defineTAG_CMDLINE 0x6C6D430AL#defineID_HWBOX 1001 //hwbox的標識符#defineID_HWERR 1002 //hwerr的標識符#defineNHIST 32 //歷史中最多記錄32條命staticHINSTANCEhinst; //DLL句柄staticHWND hwmain; //OllyDbg主窗口句柄staticHWND hwcmd; //命令行窗口staticHWND hwbox; //編輯和顯示歷史的下拉框staticHWND hwedit; //下拉框內部的編輯控制staticWNDPROColdhweditproc;//hwedit原來的窗口過程staticHWND hwerr; //錯誤信息窗口staticchar cmdlinewinclass[32]; //命令行窗口類的名字staticint posx; //窗口的X坐標staticint posy; //窗口的Y坐標staticchar hist[NHIST][TEXTLEN]; //被保存的命令記staticint nhist; //歷史中現有命令記錄數量staticint poponstop;//暫停時將窗口前置//Execute()cmdexec.c中實現,功能為解釋并執(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--) //移除歷史中重復的字符串{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: //獲取命令行窗口的當前位置并保存到.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: //將命令行窗口的背景用默認按鈕顏色填充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)建命令行窗口。如果窗口已經存在,將它提到前臺。staticHWNDCreatecmdlinewindow(void){HFONThf;RECTrc;POINTpt;if(hwcmd==NULL)//窗口還未出現,創(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默認字體,hf=((HFONT*)Plugingetvalue(VAL_FONTS))[Plugingetvalue(VAL_DEFFONT)];SendMessage(hwbox,WM_SETFONT,(WPARAM)hf,1);//OllyDbg默認寬度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(""); //刷新下拉框}//函數起始處那個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文件獲取命令行窗口最后的位置,并確認窗口是完全可見的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;}//當被調試的程序停止下來時,將命令行窗口置于前臺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文件中恢復數據時,最后保存的歷史條目將成為第一條for(i=nhist-1;i>=0;i--){Pluginsaverecord(TAG_CMDLINE,strlen(hist[i])+1,hist[i]);}}//從.udd文件中恢復數據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;}//用戶打開新的程序或者重新調試當前程序時,清除命令行歷史。extcvoid_exportcdeclODBG_Pluginreset(void){poponstop=1;Addline(NULL);}extcint_exportcdeclODBG_Pluginclose(void){RECTrc;//為了自動恢復,在.ini文件中標識命令行窗口是否被打開并保存坐標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); //當命令有效時,添加一行記if(hwmain!=NULL&&hwerr!=NULL)SetWindowText(hwerr,answer);return1;}3、Bookmark和Command相比,Bookmark更長了——因為所有功能都在這一個文件中實現。閱讀bookmark.c是很劃得來的,我們至少可以從中學到以下內容:有序表的定義、構造、操作、使用如何創(chuàng)建多種樣式的菜單以及與數據相關的菜單項CPU窗口交互更復雜但更接近于實際的消息處理過程OllyDbg中對窗口繪制的支持和簡化如何在內存中讀取代碼并將其反匯編#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), //有序數據的描述符"Bookmarks", //有序數據的名稱sizeof(t_bookmark), //表項大小10, //初始化表項數(SORTFUNC*)Bookmarksortfunc, //自定義的排序函數NULL //自定義的析構函數)!=0) //初始化失敗,未分配空間return-1; //因此直接返回,無需回收Registerpluginclass(bookmarkwinclass,NULL,hinst,Bookmarkwinproc0 //注冊窗口類失敗Destroysorteddata( //注銷有序表描述符&(bookmark.data)); //并釋放分配的內存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;}//自定義的排序函數//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;}//如果一個窗口用來顯示有序表,應當把它收到的//絕大部分消息傳遞給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()//因為有序數據采用了特殊的排序索引表pb=(t_bookmark*)Getsortedbyselection(&(bookmark.data),bookmark.data.selected);if(menu!=NULL&&pbNULL) //構建彈出菜單{AppendMenu(menu,MF_STRING,1,"&Follow\tEnter");AppendMenu(menu,MF_STRING,2,"&Delete\tDel");}//這里也要讓Tablefunction()先處理一下//它的返回值需要是依據消息類型而定的i=Tablefunction(&bookmark,hw,WM_USER_MENU,0,(LPARAM)menu);if(menu!=NULL)DestroyMenu(menu);if(i1) //選擇了跟隨//Setcpu()CPU窗口轉到指定的指令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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 共享自習室項目實施方案
- 貴州省六盤水市水城區(qū)2023-2024學年高一上學期12月月考歷史含解析
- 2025年開展安全生產月活動實施方案 (3份)
- 江西工業(yè)貿易職業(yè)技術學院《納米材料表征方法》2023-2024學年第二學期期末試卷
- 廣西英華國際職業(yè)學院《籃球四》2023-2024學年第二學期期末試卷
- 安徽理工大學《電工電子綜合實踐》2023-2024學年第二學期期末試卷
- 濮陽石油化工職業(yè)技術學院《工業(yè)催化》2023-2024學年第二學期期末試卷
- 甘肅機電職業(yè)技術學院《計算機應用綜合性設計》2023-2024學年第二學期期末試卷
- 廣東海洋大學《大數據技術開源架構》2023-2024學年第二學期期末試卷
- 武漢科技大學《環(huán)境生態(tài)學俄》2023-2024學年第二學期期末試卷
- 湖南省邵陽市2024年中考物理試卷(解析版)
- 2025年中考語文復習之小題狂練300題(選擇題):語法知識(20題)
- 天津中考英語2020-2024年5年真題匯編-教師版-專題07 完成句子
- 關于建筑設計優(yōu)化合理化建議書
- 無處不在-傳染病知到智慧樹章節(jié)測試課后答案2024年秋南昌大學
- 風電場道路施工安全管理方案
- 車間現場定置管理制度
- 國家電網招聘考試試題及答案
- 中國產業(yè)地圖
- 危險化學品目錄(2024版)
- 精密測量技術
評論
0/150
提交評論