DLL injection practices

Dll extensive use as a Windows system component reuse, the application module will implement the functions dll split. DLL injection technique is to insert its own DLL to process a running process.

Window code injection under

Common Windows code injection method is as follows:

  • Registry injected
    AppInit_DLLs option to compile the registry, those who use the GUI process, reads the AppInit_DLLs content, load the Dll.

  • Windows Hook injection
    use SetWindowsHookEx, UnHkkkWindowsHookEx to install hooks for the target process, monitor the target process messages in the dll injection.

  • Remote thread injection

    Use CreateRemoteThread function to create a thread in the target process, injection dll loaded in the thread.

  • DLL function Forwarding

    Dll used to replace certain forged dll, dll two identical symbols derived in custom DLL, the first function using the forwarder will forward the request to the real dll, followed by some of their own process.

In this article, we introduce the Windows Hook injected this way. Before specific description, first introduced Dll loading sequence, loading process.

DLL load order

Before the search system to load the specified DLL, check-ups in the following order:

  1. If the same name as the DLL is loaded in memory, is used directly
  2. DLL if the DLL in the system list, the system copies the direct use of known DLL
  3. If the DLL dependent on other DLL, the system will search by name and load-dependent DLL, DLL to be loaded before loading the dependence itself.

DLL system known in the registry list configuration HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLsoptions, the contents of the machine is as follows:

The system DLL list .jpg

Standard DLL search order depends on system security DLL search mode, which is enabled by default. Search in the following order DLL:

  1. Process corresponding to the application directory, can GetModuleFileName available, the program starts a fixed value.
  2. Windows system directory, typically C: \ Windows \ system32
  3. Windows directory, usually C: \ Windows
  4. The current process directory by GetCurrentDirectory get, the program can SetCurrentDirectory be modified.
  5. PATH environment variable directory

DLL loading process

DLL is loaded into loading implicitly loaded and displayed.

Implicit load both for the increase in the import library compile and link options, store dll to be loaded at run directory. Double-clicking the program starts, loading the corresponding dll into the process space by the system loader according exe in the import table, if dll has to rely on other dll is, recursively loading until loading all necessary dll, then import function address relocation the exe so the export function can call the dll.

Load refers to the display by the application loaded on demand, specifically for the call LoadLibrary, FreeLibraryand GetProcAddressthe three API functions, export functions to load and get the address dll.

Loader execution process

  1. Create a virtual address space for the process
  2. The executable module mapped into the process address space
  3. Importing segment examination executable module, according to the rules DLL search, find and load the required DLL. As at this stage, we did not find the required dll, pop-up "failed to start because of the lack XXX.dll computer"
  4. Check dll import table (IAT), if the dll also rely on other dll, then continue to locate and load the desired dll.
  5. Fix your imports symbol symbol references. Specifically, lead-in section traversing all the modules, for each imported symbol, the loader checks whether there is a symbol introduced in the exported segment matching, if present, is derived taking RVA symbols, the base address plus the corresponding dll obtain export the real address of the symbol, the corresponding fill import table. As at this stage the corresponding export symbols not found, the pop-up "XXX can not locate the entry point to the DLL xxx.dll"
  6. If you call during an executable module to run a dll export functions, you'll jump to the IAT, get the address of the exported function, and then make the call.

Use CreateRemoteThread injected DLL

Use CreateRemoteThread can make the current process creates a thread, but to load the dll injection, requires the virtual address space of the target thread application memory, save for the name of the target dll through GetProcAddress function remote thread kernel32.dll module LoadLibrary function address, a remote thread entry function, the main process is as follows:

  1. Obtain the address of LoadLibrary function
  2. Call VirtualAllocEx function for the period of virtual memory in the remote process
  3. dll name calling will be loaded WriteProcessMemory written to the virtual memory address of the process of reading and writing content ReadProcessMemory
  4. CreateRemoteThread remote thread creation call, a callback function LoadLibrary, parameters corresponding string address
  5. Call VirtualFreeEx release remote virtual memory

After the completion of the implementation of their functions, will remotely uninstall dll, ideas and inject similar function becomes FreeLibrary, to handle incoming parameters corresponding to the dll.
Acquisition module handles loaded (by EnumProcessModule achieve)

Code sample injection:


// 获得指定进程名称的进程PID
int GetProcessId(const char* pName)
{
    PROCESSENTRY32 pe;
    DWORD id = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    pe.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe))
        return 0;

    while (1)
    {
        pe.dwSize = sizeof(PROCESSENTRY32);
        if (Process32Next(hSnapshot, &pe) == FALSE)
            break;

        if (strcmp(pe.szExeFile, pName) == 0)
        {
            id = pe.th32ProcessID;
            break;
        }
    }

    CloseHandle(hSnapshot);
    return id;
}

//利用远程线程来注入dll
bool RemoteThreadDllInject()
{
    ////提权代码,在Windows Vista 及以上的版本需要将进程的权限提升,否则打开进程会失败
    if (!SetDebugPrivilege(TRUE))
    {
        printf("提升权限失败\n");
        return false;
    }

    int nPid = GetProcessId(INJECT_EXE_NAME);

    // 打开目标进程
    HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nPid);
    if (NULL == hRemoteProcess)
    {
        printf("OpenProcess failed! %d", GetLastError());
        return false;
    }
    
    // 获得 LoadLibraryW 在 kernel32.dll 中的地址
    typedef HMODULE(WINAPI *pfnLoadLibrary)(LPCWSTR);
    // 这里注意要载入宽字节版本还是普通版本的 LoadLibrary  
    pfnLoadLibrary pfnThreadRtn2 = (pfnLoadLibrary)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "LoadLibraryA");
    // 在远程进程中申请内存空间,用于保存远程线程的参数
    LPVOID lpRemoteMemory = VirtualAllocEx(hRemoteProcess, 0, MAX_PATH, MEM_COMMIT, PAGE_READWRITE);

    string strInjectDllName(INJECT_DLL_NAME);
    DWORD nWritten = 0;
    BOOL bRet = WriteProcessMemory(hRemoteProcess, lpRemoteMemory, strInjectDllName.c_str(), strInjectDllName.length() + 1, &nWritten);

    HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pfnThreadRtn2, lpRemoteMemory, 0, NULL);
    WaitForSingleObject(hRemoteThread, INFINITE);
    VirtualFreeEx(hRemoteProcess, lpRemoteMemory, 0, MEM_RELEASE);

    CloseHandle(hRemoteThread);
    CloseHandle(hRemoteProcess);

    return true;
}

Remote unload dll sample code:

// 获得指定进程内指定模块信息
bool GetProcessModule(DWORD dwPid, string strModuleName, LPMODULEENTRY32 lpMe32, DWORD cbMe32)
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
    if (INVALID_HANDLE_VALUE == hSnapshot)
    {
        printf("CreateToolhelp32Snapshot Error");
        return false;
    }

    bool bFind = false;
    MODULEENTRY32 moduleInfo = {0};
    moduleInfo.dwSize = sizeof(MODULEENTRY32);
    if (Module32First(hSnapshot, &moduleInfo))
    {
        do 
        {
            if (strModuleName == string(moduleInfo.szModule))
            {
                memcpy(lpMe32, &moduleInfo, cbMe32);
                bFind = true;
                break;
            }
        } while (!bFind && Module32Next(hSnapshot, &moduleInfo));
    }
    
    CloseHandle(hSnapshot);

    return bFind;
}


bool RemoteDllUnLoad()
{
    //在远程线程执行结束后,注入的 dll 仍然存在与目标进程中,我们需要再次使用 CreateRemoteThread,执行 FreeLibrary ,将之前注入的 dll 卸载掉
    // 实现思路:枚举进程的模块,根据模块名称找到对应模块的句柄。
    int nPid = GetProcessId(INJECT_EXE_NAME);

    ////提权代码,在Windows Vista 及以上的版本需要将进程的权限提升,否则打开进程会失败
    if (!SetDebugPrivilege(TRUE))
    {
        printf("提升权限失败\n");
        return false;
    }

    MODULEENTRY32 moduleInfo = {0};
    if (!GetProcessModule(nPid, INJECT_DLL_NAME, &moduleInfo, sizeof(moduleInfo)))
    {
        printf("can't find %s dll in %s", INJECT_DLL_NAME, INJECT_EXE_NAME);
        return false;
    }
    
    typedef BOOL(*pfnFreeLibrary)(HMODULE);
    pfnFreeLibrary pFreeLibrary = (pfnFreeLibrary)GetProcAddress(GetModuleHandle("kernel32.dll"), "FreeLibrary");

    HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nPid);
    if (hRemoteProcess == NULL)
    {
        printf("OpenProcess Error");
        return false;
    }

    HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFreeLibrary, moduleInfo.hModule, 0, NULL);
    WaitForSingleObject(hRemoteThread, INFINITE);

    CloseHandle(hRemoteThread);
    CloseHandle(hRemoteProcess);
    return true;
}

Precautions :

  • Remote process may compile in Unicode encoding, it may be MBSC coded compiler, therefore, to distinguish between LoadLibraryW or LoadLibraryA version of the function, FreeLibrary functions without the need to distinguish between different versions.
  • When you get the handle of the target process, the need to provide the right to process its own program operation. General needs of the current logged in user belongs to Administrator group members have the ability to elevate privileges to debug. Administrator group members access token will contain some process can perform system-level operation, note that non-members of the Administrator group can not be created to escalate its privileges. If the authority fails to mention, it is recommended to open the VS development environment through the management of rights.
  • When injected, it needs to be injected dll placed in the same directory as the remote process.
  • Validation implantation, by loading and unloading branch box prompts dllMain shot function, you can also procexp64.exe to view information about the program currently loaded dll program.

Engineering Practice

How do you get during the operation does not meet the expectations of dll

  1. Exe by reading the PE header for a list dependency dll, dll dependent dll traverse read, obtain a set of
  2. The program is running, call EnumProcessModules get the current load all dll, get a set of 2
  3. 1 excluded set of content, generates a set of obtained 3, i.e. does not match the expected dll from set 2.

In general, the input method (skin component PicFace.dll Sogou input method, resource components Resource.dll etc.), dll monitoring software will automatically load the dll into all processes go.

Module base relocation

Each module (exe and dll) at the output of the compiler, there is a preferred base address, which indicates the loader module is mapped to the process address space in the preferred location, the base address of general exe set to 0x00400000, 0x10000000 DLL module while when a plurality exe dependent dll, a first dll is correctly loaded onto 0x10000000, subsequent dll can not be loaded onto 0x10000000, a loader dll will subsequently be base relocation, put it elsewhere. Base relocation program initialization time will increase, so if multiple modules loaded in the same process space, you can specify different modules of different base address. In the VS development environment, Base configuration: DLL project Configuration Properties -> Linker -> Advanced -> base address.

After all dll compiled using the Rebase.exetools, all modules need to be loaded in the process address space of the base relocation, the result is written back to the dll file.

Once a module dll base address is known, it can be calculated directly using the real address exe export function of the DLL. This advance will depend exe and dll bound approach can improve the startup speed applications.

VS provides Bind.exeprovides the capability to bind the executable file and the dll. Working principle, RVA read base address and all symbol dll is derived, is filled into the executable file import table after calculation.

Reference documents: a variety of DLL injection technique introduces the principle of

Guess you like

Origin www.cnblogs.com/cherishui/p/11205377.html