使用代码注入

时间:2016-09-22 21:05:31

标签: c++ hook ipc openprocess

我正在使用高级代码注入代码在远程进程上启动.dll。 你可以在这里找到它的工作原理/代码snipet:

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

我注意到,对于某些应用程序,这种方法不起作用 - 它会导致主机应用程序崩溃。主要问题似乎是特殊的第三方软件,如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 个答案:

答案 0 :(得分:1)

如果使用“导出的函数转发”,则函数指针解析不正确(可以用该术语进行搜索)。

正确的功能解析可以这样写:(你在上面看到的是一些论坛中的一些复制粘贴功能)。

position: relative;

除此之外,仍然可以将.dll加载到不同的地址,但这不会发生在kernel32.dll或kernelbase.dll上。

但是如果.dll变基作为一个问题 - 一种解决方法就是使用EasyHook方法 - 可以在这里找到:

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

参见GetRemoteFuncAddress函数。