逆向工程核心原理6:进程注入

**************************************************DLL注入**************************************************
介绍 : 以DLL的方式通过向正在运行的进程注入代码, DLL在进程运行的时候按需加载
注入方法 :
    原理分析 : 
        打开进程OpenProcess
        在进程中申请存储dll路径的内存空间
        将dll路径写入到进程内存空间
        执行远程调用让进程加载该dll
        卸载类似

    1、创建远程线程 :  CreateRemoteThread() API
         //########################inject.exe#######################
        #include "stdafx.h"
        #include <windows.h>  
        #include <tchar.h>
        #include "tlhelp32.h"

        BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
        {
            HANDLE hProcess = NULL;
            HANDLE hThread = NULL;
            HMODULE hMod = NULL;
            LPVOID pRemoteBuf = NULL;  // 存储在目标进程申请的内存地址  
            DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);  // 存储DLL文件路径所需的内存空间大小  
            LPTHREAD_START_ROUTINE pThreadProc;

            if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) {
                _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
                return FALSE;
            }

            pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);  // 在目标进程空间中申请内存  

            WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);  // 向在目标进程申请的内存空间中写入DLL文件的路径

            hMod = GetModuleHandle(L"kernel32.dll");
            pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");  // 获得LoadLibrary()函数的地址

            hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);

            WaitForSingleObject(hThread, INFINITE);
            CloseHandle(hThread);
            CloseHandle(hProcess);

            return TRUE;
        }


        BOOL UnInjectDll(DWORD dwPID, LPCTSTR szDllName)
        {
            BOOL bMore = FALSE, bFound = FALSE;
            HANDLE hSnapshot = NULL;
            HANDLE hProcess = NULL;
            HANDLE hThread = NULL;
            HMODULE hModule = NULL;
            MODULEENTRY32 me = { sizeof(me) };
            LPTHREAD_START_ROUTINE pThreadProc;

            //获得进程的快照,查找有没有对应的dll,以便卸载掉
            hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
            bMore = Module32First(hSnapshot, &me);
            for (; bMore; bMore = Module32Next(hSnapshot, &me))
            {
                if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
                    !_tcsicmp((LPCTSTR)me.szExePath, szDllName))
                {
                    bFound = TRUE;
                    break;
                }
            }

            if (!bFound)
            {
                CloseHandle(hSnapshot);
                return FALSE;
            }

            if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
            {
                _tprintf(L"OpenProcess(%d) failed!!", dwPID);
                CloseHandle(hSnapshot);
                return FALSE;
            }

            hModule = GetModuleHandle(L"kernel32.dll");
            pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");  // 获得LoadLibrary()函数的地址
            hThread = CreateRemoteThread(hProcess, NULL, 0,
                                        pThreadProc, me.modBaseAddr,
                                        0, NULL);

            WaitForSingleObject(hThread, INFINITE);
            CloseHandle(hThread);
            CloseHandle(hProcess);
            return TRUE;
        }
        int _tmain(int argc, TCHAR *argv[])
        {
            if (argc != 4) {
                _tprintf(L"USAGE : %s i/u pid dll_path\n", argv[0]);
                return 1;
            }

            
            if (argv[1][0] == 'i')
            {
                if (InjectDll((DWORD)_tstol(argv[2]), argv[3]))
                    _tprintf(L"InjectDll(\"%s\") success!!!\n", argv[2]);
                else
                    _tprintf(L"InjectDll(\"%s\") failed!!!\n", argv[2]);
            }
            else if (argv[1][0] == 'u')
            {
                if (UnInjectDll((DWORD)_tstol(argv[2]), argv[3]))
                    _tprintf(L"UnInjectDll(\"%s\") success!!!\n", argv[3]);
                else
                    _tprintf(L"UnInjectDll(\"%s\") failed!!!\n", argv[3]);
            }

            return 0;
        }


        //################################inject.dll##################################
        #include "stdafx.h"
        #include <windows.h>  
        #include <tchar.h>  
        #include <winuser.h>

        BOOL APIENTRY DllMain( HMODULE hModule,
                               DWORD  ul_reason_for_call,
                               LPVOID lpReserved
                             )
        {
            switch (ul_reason_for_call)
            {
            case DLL_PROCESS_ATTACH:
                MessageBox(NULL, TEXT("Dll Inject Success!!!"), TEXT("info"), MB_OK);  // 被进程加载时弹出MessageBox("Dll Inject Success!!!")  
                break;
            case DLL_THREAD_ATTACH:
            case DLL_THREAD_DETACH:
            case DLL_PROCESS_DETACH:
                MessageBox(NULL, TEXT("Dll unInject Ok!!!"), TEXT("info"), MB_OK);  // 被进程卸载时弹出MessageBox("Dll unInject Ok!!!")  
                break;
                break;
            }
            return TRUE;
        }



    2、使用注册表 : AppInit_DLLs 值
            HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
                AppInit_DLLs : dll路径
                LoadAppInit_DLLs : 设置为1, PC重启后, 所有进程都将被注入AppInit_DLLs
                

    3、消息钩取 : SetWindowsHookEx() API



4代码注入
    原理分析 : 
        打开进程
        将函数地址保存到结构体中param中
        在进程中申请内存将param写入
        远程调用执行对应的函数         

        #include "stdafx.h"
        #include <windows.h>  
        #include <tchar.h>
        #include "tlhelp32.h"

        //LoadLibraryA
        typedef HMODULE(WINAPI *FPLOADLIBRARYA)
        (
            LPCSTR pLibFileName
        );

        //GetProcAddress()
        typedef FARPROC (WINAPI *FPGETPROCADDRESS)
        (
            HMODULE hModule,
            LPCSTR lpProcName
        );

        //MessageBoxA()
        typedef int (WINAPI *PFMESSAGEBOXA)
        (
            HWND hWnd,
            LPCSTR lpText,
            LPCSTR lpCaption,
            UINT uType
        );

        typedef struct _THREAD_PARAM
        {
            FARPROC pFunc[2];
            char szBuf[4][128];
        }THREAD_PARAM, *PTHREAD_PARAM;

        DWORD WINAPI ThreadProc(LPVOID lParam)
        {
            PTHREAD_PARAM     pParam = (PTHREAD_PARAM)lParam;
            HMODULE         hMod = NULL;
            FARPROC            pFunc = NULL;

            hMod = ((FPLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);
            pFunc = (FARPROC)((FPGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);

            ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
            return 0;
        }

        BOOL InjectCode(DWORD dwPID)
        {
            HMODULE    hMod = NULL;
            THREAD_PARAM param = { 0 };
            HANDLE    hProcess = NULL;
            HANDLE hThread = NULL;
            LPVOID    pRemoteBuf[2] = { 0 };
            DWORD    dwSize = 0;

            hMod = GetModuleHandleA("kernel32.dll");
            param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
            param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
            strcpy_s(param.szBuf[0], "user32.dll");
            strcpy_s(param.szBuf[1], "MessageBoxA");
            strcpy_s(param.szBuf[2], "xxxxxxxx");
            strcpy_s(param.szBuf[3], "eeeeeeeeee");

            if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) {
                _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
                return FALSE;
            }

            dwSize = sizeof(THREAD_PARAM);
            pRemoteBuf[0] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
            WriteProcessMemory(hProcess, pRemoteBuf[0], (LPVOID)&param, dwSize, NULL);

            dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
            pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            WriteProcessMemory(hProcess, pRemoteBuf[1],    (LPVOID)ThreadProc,    dwSize,    NULL);

            hThread = CreateRemoteThread(hProcess, NULL, 0,
                (LPTHREAD_START_ROUTINE)pRemoteBuf[1],    pRemoteBuf[0],    0,    NULL);

            WaitForSingleObject(hThread, INFINITE);
            CloseHandle(hThread);
            CloseHandle(hProcess);

            return TRUE;
        }

        int _tmain(int argc, TCHAR *argv[])
        {
            if (argc != 2) {
                _tprintf(L"USAGE : %s pid \n", argv[0]);
                return 1;
            }

            if (InjectCode((DWORD)_tstol(argv[1])))
                _tprintf(L"InjectCode success!!!\n");
            else
                _tprintf(L"InjectCode failed!!!\n");
            
            return 0;
        }


API钩子

可执行文件注入(PE注入)

 进程hollow(又名进程替换和RunPE)

 线程执行劫持(又名挂起、注入并恢复)

 通过SetWindowsHookEx钩子注入

APC注入和AtomBombing

 通过SetWindowLong的窗口内存注入(EWMI)

使用Shims注入

IAT hook和Inline hook(应用层rootkit)

猜你喜欢

转载自blog.csdn.net/dengshengli123/article/details/80893646