2016-09-22 44 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。