亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

利用DelayLoad來優化應用程序的性能,攔截API

2019-11-17 05:35:05
字體:
來源:轉載
供稿:網友
    在 1998年12月的MSJ出版刊物中, Jeffrey和我寫了關于 在 vc6中使用DelayLoad 功能的專欄.最終結果,是證實了它是多么cool.但是,不幸的是,還有很多人不了解DelayLoad,他們以為這個新特點是 最新版本的WINNT才有的.
    在開始的時候,讓我重申一遍:DelayLoad不是最新的操作系統帶的特有功能,它可以在任何win32系統中起作用.我將寫一個簡單例子來說明. DelayLoadPRofile, 實現了一個很小功能,很多程序都可以得益于它.


預覽:
    通常的,當調用一個dll中的函數時,連接器會將dll和函數加入你的可執行文件.最后,所有引用的函數會放在imports段中.  當加載該程序的時候,win32程序加載器會掃描所有imports段的每個dll.加載,和重新定位imports段的所有函數,將信息寫入 引入地址表(ImportAddress Table, IAT).簡單說來,IAT就是一個函數指針的表.調用該 引入函數的時候,就到IAT中去找.  那么,DelayLoad的機理是什么呢?當你為一個Dll進行"DelayLoad"的時候,連接器不將原來的值放入imports段,相反,它為每個DelayLoad的引入函數的名稱和地址,生成一個小的根區, 備份下來。第一次引用的時候,它調用LoadLibrary加載Dll,然后,它調用GetProcAddress取得該函數的地址。最后,改寫自己在IAT的值,以便以后的程序可以直接調用.
    上面的是簡化的步驟.實際上,根區是一小段代碼,它以靜態的方式連接到可執行文件中.代碼在delayimp.lib中,必須被 連接程序引用.并且,該代碼要足夠智能,當一個函數第一次被引用的時候,要調用LoadLibrary,以后調用就不用引用了.  和引用Dll相比,DelayLoad不會加太多的時間和空間,這種方式 調用LoadLibrary只會引起稍微一點點的性能損失.每次程序啟動,在針對引入表的函數地址定位的時候,依次對DelayLoad引入的調用GetProcAddress,相對于Win32加載器來說,所損失的性能也可以忽略不記.
    然而,DelayLoad帶來的好處也是不可比擬的.例如:假如你的程序從來沒有 從Delay調用引入的函數,Dll的第一次是不會被加載的。有時候,這個情況的出現頻率出乎你想象。假如,你的程序中,包含打印的代碼,毫無疑問,即使用戶沒有使用打印功能,你的程序也一定要加載winspool.drv。在這種情況下,使用DelayLoad,你就不必加載和初始化Winspool.drv.
    另外一個好處就是:DelayLoad可以避免調用某些目標平臺不存在的API。例如,假如你的程序需要調用AnimateWindow,這個API在Win2000和Win98中存在,但是在Win95和WinNT4中,就不存在,假如你用常規的方式調用AnimateWindow,那么,你的程序將不能再早期的平臺中運行。然而,你可以用DelayLoad進行對AnimateWindow的加載檢查。這樣,你就不必改寫你的代碼為LoadLibrary和GetProcAddress的方式了。
    DelayLoad是很輕易使用的。當你決定哪個dll你想使用DelayLoad,只需要簡單的增加/DELAYLOAD:DLLNAME。其中,DLLNAME是相關的DLL文件名。你還需要增加DELAYIMP.LIB到連接庫中,你也需要原來的LIB,例如,SHELL32.LIB。把全部放到一塊,連接的命令就如下: SHELL32.LIB /DELAYLOAD:SHELL32.DLL DELAYIMP.LIB  很不幸,Visual Studio 6.0 IDE 不提供一個簡單的方法去實現一個Dll的DelayLoad。所以,你必須手工加入:/DELAYLOAD:XXX 命令行到 "Project settings"->"Link"->"Project Options"中。
   
什么時候需要DelayLoad:
    當你有小的工程,它調用了多個dll,就是一個好的DelayLoad候選例子。然而,工程可能在以后由于其它開發者的加入而變大,很輕易丟失調用dll的跟蹤。我通常用sdk中的depends.exe。一個只有少數函數要引入的dll就是一個好的開始。
    然而,我想找到一個簡單的,自動的方法來跟蹤。于是,出來了DelayLoadProfile程序。它是一個exe,可以監視你的exe文件對dll的調用,直到你的exe結束。它打印出dll被調用的情況的匯總,包括多少個dll被調用,每個dll有多少個函數被引入。
    我在這里強調:DelayLoadProfile只是針對exe有效,當它涵蓋你的程序所關聯的所有dll的時候,有時會造成一點點復雜。DelayLoadProfile只給你哪個dll可以用DelayLoad開關的暗示,你最好在不確定的時候,使用原來的處理方法。

DelayLoadProfile:具體描述
    其實DelayLoadProfile的原理很簡單:重定向 exe中,IAT的函數的指針到一段根區。根區簡單的標志一下,引入的函數被調用了。然后,跳入原來的Win32加載提供的IAT地址。只是,難的是如何實現。
    第一,你必須決定,要在哪里運行你的代碼,實現對exe的IAT入口的更改,把他們指定到那段根區去。這些都是在進程外完成。這樣可以避免你的代碼牽涉到目的exe進程中。這個可以用遍歷所有的數據結構,定位和修改IAT結構的方法。我在這里利用了很多ReadProcessMemory調用。

    接著的艱苦工作是要在和目的exe相同的進程空間里完成。幾乎是很瑣碎的工作:遍歷所有的數據結構,建立根區,從定向IAT入口,然后在完成的時候,匯總結果。然而,為了完成進程空間的工作,在exe進程運行的時候,一些 DelayLoadProfile代碼必須被加載到目的exe的進程空間。這個是我要做的。
    當確認到需要在目的進程中,加載我的代碼的時候,下個問題就是如何把我的代碼加入到目的進程中。其中一個選擇就是,要求用戶連接我的DelayLoadProfile庫,這個會造成用戶的很大量的對他們源代碼工程,或者Makefile的更改,所以,我不能采用,現在需要一個完全自動化的方法。
    在這點上,我想到了加載程序,然后,插入我的DelayLoadProfiledll進去,一個技術就是用CreateRemoteThread,在目標進程,創建一個LoadLibrary的線程。我放棄了這個,因為,win9x中,不提供CreateRemoteThread.
    很久以前的MSJ讀者可能記得我5年前寫的一個叫APISPY32的程序。它加載一個進程,插入一個dll來記錄API的調用。那個有點像我今天的DelayLoadProfile工作。然而,我在Win200中,調用那個dll失敗。有一點點問題。我覺得現在是時候要重讀那段代碼,并且改正那個錯誤了。
   
繼續深入:
    重新溫習一下,DelayLoadProfile包含2部分,一,是進程加載功能,它會注射一個dll到你的進程的地址空間。然后,那個dll掃描你的所有的exe IAT,重新定向他們到dll創建的根區中。當你的程序完成后,注射的dll會掃描所有的根區,統計出多少dll和函數它調用的。假如你曾經用過APIMON的相關部件,你將認出類似的技術細節。
    完成所有的工作,包括 監視 一個程序的引入的dll,叫DelayLoadProfileDLL.(看Figure 1).它用到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH來初始化2個主要的工作。
    當DllMain獲得DLL_PROCESS_ATTACH的消息的時候,DelayLoadProfileDLL調用PrepareToProfile(),在PrepareToProfile中,代碼加載目的EXE的IAT,對于每個它發現的引用的DLL,代碼還檢測是否安全的重定向IAT。通過IsModuleOKToHook函數來檢測,大多數情況下,是安全的,因此,PrepareToProfile包括了RedirectIAT函數。
    RedirectIAT是比較復雜的函數。假如你理解了 winini.h中的引入相關數據結構,你將得到很大的幫助。首先,函數定位IAT和相關的引入名字表,然后,計算有多少個IAT入口,掃描所有的IAT,查找NULL的指針。得到了數目后,程序將創建一個DLPD_IAT_STUB根區,每個根區對應一個IAT入口。
    最后,代碼重新掃描IAT,獲取每個IAT入口的地址,用根區的一個包含JMP指令的地址,替換IAT入口。它還掃描下一個IATDLPD_IAT_STUB根區。我在后面將還會繼續解析。
    在重定向IAT入口的根區中,有2個值得提起:1,IAT經常被放到EXE的只讀段,通常,嘗試改寫只讀段,會引起訪問違規,幸運的,VirtualProtect答應你更改一個目的地址的屬性。現在必須更改iat的屬性為讀/寫。完成后,代碼要恢復IAT段原來的屬性。
    另外一個要注重的地方,就是在重定向IAT的時候,有數據引入的問題。雖然程序員們很少這樣做,但是,很輕易用增加的代碼去導入數據。vc++運行庫DLL(MSVCRT.DLL)有數據導出。假如重定向一個數據IAT的入口,會導致問題。
    那么,如何判定一個IAT是數據呢?一個商業的軟件,應該用準確的算法來判定一個IAT入口的類型。但是,我在這里用了一個快捷方法。就是IsBadWritePtr。假如IAT包含的指針是可寫的,那么,很可能是一個數據指針。假如是只讀的,那么,應該是一段代碼。這個測試合適嗎?不,但是,它對DelayLoadProfile是足夠了。
    現在看一下根區,在DelayLoadProfileDLL.h中定義的DLPD_IAT_STUB結構包含著代碼和數據。簡單來說,就是如下:
  CALL DelayLoadProfileDLL_UpdateCount
  JMP xxxxxxxx //original IAT 地址
  DWord count
  DWORD pssNameOrOrdinal

    當exe調用其中一個重定向的函數時,控制權被轉到根區的CALL指令中,調用DelayLoadProfileDLL.CPP

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美床上激情在线观看| 欧美在线激情视频| 国产精品免费一区豆花| 国产精品视频免费在线观看| 成人在线激情视频| 国产aⅴ夜夜欢一区二区三区| 热99在线视频| 亚洲国产一区二区三区四区| 亚洲人成网站777色婷婷| 久久伊人精品天天| 超薄丝袜一区二区| 亚洲国产天堂久久国产91| 青青草一区二区| 国产ts人妖一区二区三区| 久久亚洲精品毛片| 日韩精品视频三区| 91wwwcom在线观看| 欧美日韩亚洲国产一区| 国产精品久久久久一区二区| 日韩精品极品在线观看播放免费视频| 最新国产成人av网站网址麻豆| 亚洲精品有码在线| 亚洲午夜精品久久久久久久久久久久| 欧美重口另类videos人妖| 国产精品热视频| 18性欧美xxxⅹ性满足| 国产精品网站视频| 久久99亚洲热视| 欧美大秀在线观看| 亚洲精品中文字幕女同| 亚洲国产精品久久| www.日韩视频| 欧美大成色www永久网站婷| 国产在线拍偷自揄拍精品| 亚洲视频自拍偷拍| 日韩欧美高清在线视频| 777国产偷窥盗摄精品视频| 91精品视频在线看| 久久久久久91香蕉国产| 国产精品亚洲美女av网站| 日韩在线免费视频| 一本色道久久88综合日韩精品| 日韩成人在线网站| 亚洲精品综合久久中文字幕| 欧美午夜精品在线| 久久久在线免费观看| 国产成人亚洲精品| 亚洲人成欧美中文字幕| 久久夜色精品国产欧美乱| 国产精品国产福利国产秒拍| 日本三级久久久| 国产欧美精品va在线观看| 97视频免费观看| 一本大道香蕉久在线播放29| 九九精品视频在线观看| www.日韩不卡电影av| 久久黄色av网站| 亚洲久久久久久久久久| 成人黄色中文字幕| 国产精品夜色7777狼人| 久久久噜噜噜久久| 日韩女优人人人人射在线视频| 高跟丝袜欧美一区| 日产精品久久久一区二区福利| 日韩av影院在线观看| 久久成年人视频| 欧美人与物videos| 最近2019年中文视频免费在线观看| 日韩电影免费观看在线| 一区二区三区高清国产| 91在线观看欧美日韩| 91大神福利视频在线| 韩国19禁主播vip福利视频| 国产日韩中文在线| 欧美激情亚洲视频| 午夜伦理精品一区| 97在线免费观看| 国产精品99久久久久久久久| 国产高清视频一区三区| 在线视频日本亚洲性| 久久久久久午夜| 欧美丰满少妇xxxx| 久久久久久久久久国产精品| 国产精品久久久久av免费| 国产精品久久色| 色综合久久88色综合天天看泰| 亚洲奶大毛多的老太婆| 亚洲人成人99网站| 欧美日韩ab片| 欧美精品18videos性欧| 久久久久久久av| 亚洲欧美日韩中文在线| 精品国产精品自拍| 亚洲成年人在线| 欧美精品电影免费在线观看| 欧美制服第一页| 亚洲区一区二区| 国产成人在线视频| 国内精品久久久久影院优| 亚洲视频在线观看网站| 2025国产精品视频| 国产91九色视频| 亚洲精品在线看| 欧美电影第一页| 日韩欧美视频一区二区三区| 国产精品成人一区二区| 麻豆精品精华液| 国产视频自拍一区| 国产日本欧美一区二区三区| 97视频在线观看视频免费视频| 色婷婷久久av| 亚洲第一区第二区| 成人在线播放av| 欧美日韩一区二区三区在线免费观看| 日韩电影免费观看在线观看| 欧美激情伊人电影| 欧美性感美女h网站在线观看免费| 成人做爰www免费看视频网站| 国产福利精品在线| 欧美www在线| 欧美乱妇高清无乱码| 成人久久18免费网站图片| 日韩精品免费一线在线观看| 色偷偷av一区二区三区乱| 久久久久久久爱| 97在线日本国产| 日韩av在线免费播放| 91麻豆国产语对白在线观看| 精品久久久久久中文字幕大豆网| 91色中文字幕| 97在线精品国自产拍中文| 欧美尤物巨大精品爽| 国产主播精品在线| 欧美猛男性生活免费| 色综合天天狠天天透天天伊人| 国产精品久久久久国产a级| 成人看片人aa| 亚洲一区二区在线| 91中文字幕在线| 欧美国产一区二区三区| 国产精品高潮呻吟久久av黑人| 亚洲伊人成综合成人网| 精品久久久久久电影| 国产精品三级在线| 精品久久久久久久久久ntr影视| 欧洲s码亚洲m码精品一区| 久久亚洲精品一区二区| 中文字幕精品久久久久| 综合激情国产一区| 高清视频欧美一级| 亚洲美女自拍视频| 日韩小视频网址| 国产精品一区二区三区久久| 国产精品狠色婷| 亚洲男人的天堂在线播放| 成人激情视频免费在线| 国产一区二区三区免费视频| 亚洲欧美在线看| 欧美超级乱淫片喷水| 4444欧美成人kkkk| 九九热r在线视频精品| 欧美极品欧美精品欧美视频| 国产亚洲精品久久久久久777| 91精品中文在线|