2016-09-22 70 views
0

我正在使用高級代碼注入代碼在遠程進程上啓動.dll。 你可以在這裏找到,例如如何工作/一小段代碼片段:使用代碼注入在遠程進程中執行功能

https://sourceforge.net/p/diagnostic/svn/HEAD/tree/src/RemoteInit.cpp

我注意到一些應用中,這種方法是行不通的 - 它崩潰主機應用程序。主要問題似乎是特殊的3-第三方軟件,如ConEmuHk64.dll,通過提供它攔截kernel32.dll GetProcAddress自己的鉤子函數 - 那我得到的函數指針像這樣經過:

*((FARPROC*) &info.pfuncGetProcAddress) = GetProcAddress(hKernel32, "GetProcAddress"); 

但不是我越來越指針功能位於ConEmuHk64.dll中。

在我自己的進程中調用該函數是可以接受的,但是當嘗試在遠程進程中執行相同的操作時 - 它崩潰,因爲ConEmuHk64.dll不一定在那裏可用。

我已經弄清楚機制如何通過手動走在DOS/NE其他標頭功能的自動探測正確的地址 - 這裏是代碼片段:

// 
// We use GetProcAddress as a base function, with exception to when GetProcAddress itself is hooked by 3-rd party 
// software and pointer to function returned to us is incorrect - then we try to locate function manually by 
// ourselfes. 
// 
FARPROC GetProcAddress2(HMODULE hDll, char* funcName) 
{ 
    FARPROC p = GetProcAddress(hDll, funcName); 

    if(!p) 
     return NULL; 

    IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER *) hDll; 

    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) 
     return p; 

    IMAGE_NT_HEADERS* pNtHeaders = (IMAGE_NT_HEADERS *) (((char*) pDosHeader) + pDosHeader->e_lfanew); 

    if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) 
     return p; 

    IMAGE_OPTIONAL_HEADER* pOptionalHeader = &pNtHeaders->OptionalHeader; 

    if((char*) p >= (char*)hDll && (char*) p <= ((char*)hDll) + pOptionalHeader->SizeOfCode) 
     // Sounds like valid address. 
     return p; 

    // Does not sounds right, may be someone hooked given function ? (ConEmuHk64.dll or ConEmuHk.dll) 
    IMAGE_DATA_DIRECTORY* pDataDirectory = &pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 
    IMAGE_EXPORT_DIRECTORY* pExp = (IMAGE_EXPORT_DIRECTORY *) ((size_t) pDosHeader + pDataDirectory->VirtualAddress); 

    ULONG* addrofnames = (ULONG *) ((BYTE*) hDll + pExp->AddressOfNames); 
    ULONG* funcaddr = (ULONG*) ((BYTE*) hDll + pExp->AddressOfFunctions); 

    for (DWORD i = 0; i < pExp->NumberOfNames; i++) 
    { 
     char* funcname = (char*) ((BYTE*) hDll + addrofnames[i]); 

     if (strcmp(funcname, funcName) == 0) 
     { 
      void* p2 = (void*) ((BYTE*) hDll + funcaddr[i]); 
      return (FARPROC) p2; 
     } 
    } //for 

    return p; 
} //GetProcAddress2 

這似乎是工作GetProcAddress - 我可以檢測鉤住的函數並覆蓋它的行爲。但是 - 這種方法不是通用的。我嘗試了其他方法的類似函數調用,例如FreeLibrary/AddDllDirectory/RemoveDllDirectory - 這些函數指針指出dll邊界 - GetProcAddress返回DOS標頭之前的地址。

我懷疑是由DLL /代碼大小範圍比較是不正確的一個:

if((char*) p >= (char*)hDll && (char*) p <= ((char*)hDll) + pOptionalHeader->SizeOfCode) 

,但沒有線索公式可以如何改進。

你能否推薦我如何完全修復這個問題 - 所以任何第三方軟件都可以攔截任何功能,而且我可以在沒有崩潰的情況下繼續使用它?

回答

1

如果使用「導出的函數轉發」功能指針解析不正確(可以用該術語搜索)。

一個正確的函數解析可以這樣寫:(你在上面看到的是某個論壇的一些複製粘貼函數)。

// 
// We use GetProcAddress as a base function, with exception to when GetProcAddress itself is hooked by 3-rd party 
// software and pointer to function returned to us is incorrect - then we try to locate function manually by 
// ourselfes. 
// 
FARPROC GetProcAddress2(HMODULE hDll, char* funcName) 
{ 
    FARPROC p = GetProcAddress(hDll, funcName); 

    if(!p) 
     return NULL; 

    IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER *) hDll; 

    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) 
     return p; 

    IMAGE_NT_HEADERS* pNtHeaders = (IMAGE_NT_HEADERS *) (((char*) pDosHeader) + pDosHeader->e_lfanew); 

    if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) 
     return p; 

    IMAGE_OPTIONAL_HEADER* pOptionalHeader = &pNtHeaders->OptionalHeader; 

    if((char*) p >= (char*)hDll && (char*) p <= ((char*)hDll) + pOptionalHeader->SizeOfCode) 
     // Sounds like valid address. 
     return p; 

    // Does not sounds right, may be someone hooked given function ? (ConEmuHk64.dll or ConEmuHk.dll) 
    IMAGE_DATA_DIRECTORY* pDataDirectory = &pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 
    IMAGE_EXPORT_DIRECTORY* pExp = (IMAGE_EXPORT_DIRECTORY *) ((size_t) pDosHeader + pDataDirectory->VirtualAddress); 

    ULONG* addrofnames = (ULONG *) ((BYTE*) hDll + pExp->AddressOfNames); 
    ULONG* funcaddr = (ULONG*) ((BYTE*) hDll + pExp->AddressOfFunctions); 

    for (DWORD i = 0; i < pExp->NumberOfNames; i++) 
    { 
     char* funcname = (char*) ((BYTE*) hDll + addrofnames[i]); 

     if (strcmp(funcname, funcName) == 0) 
     { 
      ULONG addressOfFunction = funcaddr[i]; 
      void* p2 = (void*) ((BYTE*) hDll + addressOfFunction); 

      if(addressOfFunction >= pDataDirectory->VirtualAddress && addressOfFunction < pDataDirectory->VirtualAddress + pDataDirectory->Size) 
      { 
       // "Exported function forward" - address of function can be found in another module. 
       // Actually for example AddDllDirectory is truly located in KernelBase.dll (alias api-ms-win-core-libraryloader-l1-1-0.dll ?) 
       char* dll_func = (char*) p2; 
       char* pdot = strchr(dll_func, '.'); 
       if(!pdot) pdot = dll_func + strlen(dll_func); 
       CStringA dllName(dll_func, (int)(pdot - dll_func)); 
       dllName += ".dll"; 

       HMODULE hDll2 = GetModuleHandleA(dllName); 
       if(hDll2 == NULL) 
        return p; 

       return GetProcAddress2(hDll2, pdot + 1); 
      } 

      return (FARPROC) p2; 
     } 
    } //for 

    return p; 
} //GetProcAddress2 

除此之外它可能仍然獲得.dll文件在不同的地址被加載,但是這並不KERNEL32.DLL或kernelbase.dll發生。

但如果.dll文件墊底之際,一個問題 - 解決方法之一是使用EasyHook的方法 - 可以在這裏位於:

https://github.com/EasyHook/EasyHook/blob/b8b2e37cfe1c269eea7042420bde305eb127c973/EasyHookDll/RemoteHook/thread.c

見功能GetRemoteFuncAddress。