2016-09-22 6 views
0

リモートプロセスで.dllを起動するための高度なコードインジェクションコードを使用しています。あなたは、これは、ここから例えば/コードsnipetをどのように機能するかを見つけることができます :コードインジェクションを使用したリモートプロセスでの機能の実行

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

私はいくつかのアプリケーションで、このアプローチは動作しないことに気付きました - それは、ホストアプリケーションがクラッシュします。主な問題は、それが自分のフック関数です提供することで、kernel32.dll GetProcAddressをインターセプトConEmuHk64.dllのような特別な種類の3 - サードパーティのソフトウェアのようです - その後私はこのような関数ポインタを取得しています:

*((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ヘッダの前にアドレスを返します。

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

をしかし、数式を向上させることができるかの手掛かりを持っていない:

は、私は、DLL /コードのサイズ範囲での比較が正しいものではないと思われます。

この修正プログラムを完全に作成する方法をお勧めしますか?第三者のソフトウェアが機能を傍受でき、クラッシュせずに生き残ることができますか?

答えて

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。

関連する問題