2009-08-03 78 views
0

如何在運行時將Win32可執行文件的文本段中的偏移量轉換爲指針?如何在運行時將Win32可執行文件的文本段中的偏移量轉換爲指針?

當使用反彙編程序時,我可以看到相對地址。但是如何在運行時將它們轉換爲絕對地址?

例如:

.text:402BE620 

哪些地址是在運行時?我如何將該數字轉換爲指針?

一些背景:我必須修復生命週期結束DLL中的錯誤,並且我們無法訪問源代碼。爲此我想掛鉤一個特定的函數並在運行時覆蓋它。

(它包含WaitForSingleObject調用其中MsgWaitForMultipleObjects必須使用,因爲它不能被固定用十六進制編輯器中的附加參數)

編輯:謝謝你的建議,但我加那些關於鉤子的東西只是爲了給你一些背景。 我不需要鉤子框架!。我有一個很好的鉤子框架,可以完成所有繁重的工作 - 至少現在 - 我不需要任何關於鉤子本身的更多信息。

我只需提供函數的地址來掛鉤我的鉤子框架,並且我必須知道如何計算它,我不知道如何確定它。

編輯2:我已經使用了兩個不同的反彙編程序,都顯示上述地址。有點奇怪:如果我使用他們的「goto」功能,兩者都拒絕「402BE620」作爲偏移量。我必須輸入偏移量作爲「2BE620」以使其工作...

回答

0

我不知道你的具體問題的答案,但即使我這樣做了,但我認爲你的計劃不會奏效。我認爲你打算通過調用(或跳轉)動態修補函數調用到你自己的代碼中?但是,如果包含修補程序的頁面被操作系統丟棄並在稍後重新加載(從DLL磁盤映像),會發生什麼情況?你將如何檢測這個並重新修補它?

只是一個想法....

+2

沒有,這將工作。更改可執行頁面將觸發寫入時複製,因此運行過程將永久使用修補後的代碼。 – 2009-08-06 02:19:57

0

爲了做這樣的事,你通常會使用detours
它允許你創建一個正在運行的進程和鉤線程在它/替換任何功能。
通常它通過查找符號來工作,但不應該有一個原因,它不會使用偏移量。

要專門回答你的問題,在dll文件中你通常會找到相對地址。相對於文件的開始。當一個PE(dll,exe)被加載到內存中時,所有的相對地址都被使用加載PE的基地址的絕對地址替換。您可以使用GetModuleHandle()
402BE620來查看特定DLL的基地址。根本看起來不像是相對地址。它確實看起來像一個絕對的地址,所以你最好確定反彙編器顯示你的東西。相對地址不能大於它們所在的DLL文件的大小。
您可能會發現有用的另一個提示 - 將調試器附加到進程時,通常會列出所有的DLL及其基址。

0

這對API Interception via DLL Redirection(PDF)milw0rm紙
討論了幾種方式,應該給你一個想法,你的冒險。

雖然有幾種方法可以用來實現我們的目標,但本教程將僅討論DLL35重定向的 。選擇這種方法有以下幾個原因:

  1. 它的實現相對簡單。
  2. 它允許我們查看和修改傳遞給API函數的參數,更改該函數的返回值以及運行我們期望的任何其他代碼。
  3. 儘管大多數其他方法需要將代碼注入到目標進程或從外部應用程序運行,但DLL重定向只需要對目標應用程序的 工作目錄執行寫入訪問。
  4. 我們可以在不修改目標(在磁盤或內存中)或任何系統文件的情況下攔截任何API調用。

一旦我們將程序重定向到加載我們的DLL,我們需要具有它所需要的所有功能 正在尋找。假設我們要攔截Internet Explorer對 MessageBox進行的每個呼叫。 MessageBox位於user32.dll中,因此我們需要創建一個名爲user32.dll的DLL,其中包含一個名爲MessageBox的可導出函數,創建iexplore.exe.manifest文件,並將 放置到我們新創建的user32.dll和iexplore中。在C:\ Program Files \ Internet Explorer目錄中的exe.manifest文件。現在,當IE導入其API函數時,它將從我們的 user32.dll文件加載MessageBox;那麼,無論何時IE調用MessageBox函數,我們放置在我們的MessageBox函數上的代碼都會被執行。

問題在於MessageBox不是從user32.dll導入的唯一函數。 可能有數百個IE會在user32.dll中查找的函數,如果其中任何一個是 丟失,那麼IE將無法加載。因爲我們不想重新編寫所有的USER32 DLL函數,我們 將簡單的功能,其餘轉發給其原始User32.dll文件

0

我不知道從偏移.text段,但在調試器中查看您想要的地址並從中減去模塊加載偏移量。即使基地址是明確設置的,它也可能每次都在不同的地址加載。

替代運行時修補可能只是簡單地修補dll本身。 OllyDbg是一款優秀的免費彙編級調試器和代碼分析工具,可讓您輕鬆修補二進制文件。

編輯:

只是爲了好玩這是我用來使用擴展二進制補丁了一些功能我沒有在一個應用程序像一些示例代碼 - 在運行時。我做了一些簡化,沒有重新編譯和測試,但你應該明白。

(我有二進制被週期性地更新的複雜化,因此,附加的工作模式匹配的小範圍從已知偏移之內。)

void MyCrazyPatch() 
{ 
    static bool patched = false; 

    if (!patched) 
    { 
     patched = true; 

     DWORD dwPatchOffsetStart = 0x5310; 
     DWORD dwPatchLength = 22; 

     BYTE rgPatchMatch[] = { 0xab, 0x07, 0x37, 0x56, 0x50, 0xe8, 0x92, 0xfb, 0xff, 0xff, 0x83, 
           0xf8, 0x01, 0x89, 0xb5, 0xfc, 0x0f, 0x85, 0xb2, 0xaa, 0x00, 0x00, 0x8b }; 

     HMODULE hmod = GetModuleHandle(L"mybinary.dll"); 
     if (hmod != NULL 
     { 
      MODULEINFO modInfo; 
      if (GetModuleInformation(GetCurrentProcess(), 
            hmod, 
            &modInfo, 
            sizeof(modInfo))) 
      { 
       DWORD dwIncrement = 0; 
       dwPatchOffsetStart += (DWORD)modInfo.lpBaseOfDll; 

       while (dwIncrement < 0x200 && 
         memcmp((void*)(dwPatchOffsetStart + dwIncrement), 
           rgPatchMatch, 
           sizeof(rgPatchMatch)) != 0) 
       { 
        dwIncrement++; 
       } 

       // Sanity check then add nop's to stomp out the offending code. 
       if (dwIncrement < 0x200 && 
        memcmp((void*)(dwPatchOffsetStart + dwIncrement), 
          rgPatchMatch, 
          sizeof(rgPatchMatch)) == 0) 
       { 
        DWORD dwOldProtect = 0; 

        VirtualProtect((void*)(dwPatchOffsetStart + dwIncrement), 
            dwPatchLength, 
            PAGE_EXECUTE_READWRITE, 
            &dwOldProtect); 
        memset((void*)(dwPatchOffsetStart + dwIncrement), 0x90, dwPatchLength); 

        VirtualProtect((void*)(dwPatchOffsetStart + dwIncrement), 
            dwPatchLength, 
            dwOldProtect, 
            NULL); 
       } 
      } 
     } 
    } 
} 
相關問題