中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++?DLL注入怎么實現

發布時間:2022-02-08 11:24:10 來源:億速云 閱讀:191 作者:iii 欄目:開發技術

這篇文章主要介紹“C++ DLL注入怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C++ DLL注入怎么實現”文章能幫助大家解決問題。

先上源碼:

#include "Inject_Main.h"
#include "resource.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <string>
#include <TCHAR.H>

using namespace std;


/// <summary>
/// 通過進程名稱獲取該進程句柄
/// </summary>
/// <param name="processName"></param>
/// <returns>成功返回 DWORD,失敗返回 0</returns>
DWORD GetProcessByName(CONST TCHAR* processName) {
    // 獲取到整個系統的進程
    HANDLE processALL = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    // 定義一個容器,該容器用來接收,進程信息
    PROCESSENTRY32W processInfo = { 0 };
    processInfo.dwSize = sizeof(PROCESSENTRY32W);

    // 根據進程名稱,循環判斷是否是指定的進程
    do
    {
        if (_tcscmp(processInfo.szExeFile, processName) == 0)
        {
            // 釋放進程快照,防止內存泄露
            CloseHandle(processALL);
            // 如果是返回指定進程句柄
            return processInfo.th42ProcessID;
        }
        // 一個迭代函數
    } while (Process32Next(processALL, &processInfo));
    // 釋放進程快照,防止內存泄露
    CloseHandle(processALL);
    return 0;
}

/// <summary>
/// 獲取指定 DLL 的內存地址
/// </summary>
/// <param name="pid"></param>
/// <param name="moduleName"></param>
/// <returns></returns>
HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) {
    MODULEENTRY32 moduleEntry;
    HANDLE handle = NULL;
    handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (!handle) {
        CloseHandle(handle);
        return NULL;
    }
    ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
    moduleEntry.dwSize = sizeof(MODULEENTRY32);
    if (!Module32First(handle, &moduleEntry)) {
        CloseHandle(handle);
        return NULL;
    }
    do {
        if (_tcscmp(moduleEntry.szModule, moduleName) == 0) {
            // 釋放進程快照,防止內存泄露
            CloseHandle(handle);
            return moduleEntry.hModule;
        }
    } while (Module32Next(handle, &moduleEntry));
    CloseHandle(handle);
    return 0;
}

/// <summary>
/// 把指定DLL注入到指定進程中
/// </summary>
/// <param name="processName">processName 進程名稱</param>
/// <param name="dllPath">dllPath dll路徑</param>
void InjectDll(const wchar_t* processName, const char* dllPath) {
    // 獲取指定進程的句柄
    DWORD dword = GetProcessByName(processName);
    if (dword == 0)
    {
        MessageBox(NULL, TEXT("沒有找到指定進程"), TEXT("錯誤"), 0);
        return;
    }
    // 打開指定進程
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dword);
    if (hProcess == NULL)
    {
        MessageBox(NULL, TEXT("指定進程打開失敗"), TEXT("錯誤"), 0);
        return;
    }
    /*
        在指定進程的地址,開辟一塊內存空間,用來保存 DLL的路徑信息
        LPVOID VirtualAllocEx(
        [in]           HANDLE hProcess, 在那個進程中開辟內存
        [in, optional] LPVOID lpAddress, 開辟內存的起始地址 (NULL,不需要控制起始位置)
        [in]           SIZE_T dwSize,  開辟內存的大小(當前保存的內容是 DLL的路徑)
        [in]           DWORD  flAllocationType, 內存分配的類型。(開辟內存)
        [in]           DWORD  flProtect,設置內存的權限 (可讀可寫)
        );
     */
    LPVOID DLLAddress = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_COMMIT, PAGE_READWRITE);
    /*
        把DLL的路徑,寫入到剛開辟出來的內存中
        BOOL WriteProcessMemory(
        [in]  HANDLE  hProcess, // 指定的進程
        [in]  LPVOID  lpBaseAddress, // DLL路徑字符串,寫入的基址
        [in]  LPCVOID lpBuffer, // DLL路徑字符串,的指針
        [in]  SIZE_T  nSize, // 需要寫入內存的字節長度
        [out] SIZE_T  *lpNumberOfBytesWritten // [out] 返回一個指針,不需要,NULL
        );
    */

    if (WriteProcessMemory(hProcess, DLLAddress, dllPath, strlen(dllPath), NULL) == 0)
    {
        MessageBox(NULL, TEXT("路徑寫入失敗"), TEXT("錯誤"), 0);
        return;
    }

    // 獲取 Kernel32.dll 這個模塊
    HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll"));
    // 在 Kernel32.dll 模塊中找到 LoadLibrary 這個函數的內存地址
    LPVOID loadADD = GetProcAddress(k32, "LoadLibraryA");
    /*
        在指定進程中,創建一個線程
        并通過這個線程,調用 LoadLibrary 函數
        通過 LoadLibrary 函數,把 DLL 載入到目標進程中
        HANDLE CreateRemoteThread(
        [in]  HANDLE                 hProcess, // 指定進程
        [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes, // 設置線程安全屬性,表示線程是否可以繼承,NULL就夠了
        [in]  SIZE_T                 dwStackSize, // 堆棧的初始大小,0 表示使用可執行文件的默認大小
        [in]  LPTHREAD_START_ROUTINE lpStartAddress, // 遠程進程中,需要執行的那個函數的指針
        [in]  LPVOID                 lpParameter, // 目前進程中 DLL路徑的指針
        [in]  DWORD                  dwCreationFlags, // 0 線程在創建后立即運行。
        [out] LPDWORD                lpThreadId // [out] 當前不需要這個返回值
        );
    */
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadADD, DLLAddress, 0, NULL);


    // 釋放指定的模塊
    CloseHandle(hThread);
    CloseHandle(hProcess);

}

/// <summary>
/// 把指定進程中的DLL卸載掉
/// </summary>
/// <param name="processName"></param>
/// <param name="dllPath"></param>
void UnInjectDll(const wchar_t* processName) {
    // 通過進程名稱獲取該進程句柄
    DWORD dword = GetProcessByName(processName);
    if (dword == 0)
    {
        MessageBox(NULL, TEXT("沒有找到指定進程"), TEXT("錯誤"), 0);
        return;
    }
    // 獲取指定進程中指定模塊的內存地址
    HMODULE hmodule = GetProcessModuleHandle(dword, L"WX_Read_Write.dll");

    // 打開指定進程
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dword);
    if (hProcess == NULL)
    {
        MessageBox(NULL, TEXT("指定進程打開失敗"), TEXT("錯誤"), 0);
        return;
    }

    // 獲取 Kernel32.dll 這個模塊
    HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll"));
    // 在 Kernel32.dll 模塊中找到 LoadLibrary 這個函數的內存地址
    LPVOID loadADD = GetProcAddress(k32, "FreeLibrary");

    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadADD, (LPVOID)hmodule, 0, NULL);

    // 釋放指定的模塊
    CloseHandle(hThread);
    CloseHandle(hProcess);
}


/// <summary>
/// 
/// </summary>
/// <param name="hwndDlg"></param>
/// <param name="uMsg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
INT_PTR CALLBACK dialogProc(_In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    wchar_t processName[100] = L"WeChat.exe";
    char dllPath[400] = { "C://Users//qiaoas//documents//visual studio 2015//Projects//ConsoleApplication1//Debug//WX_Read_Write.dll" };
    switch (uMsg)
    {
    case WM_INITDIALOG:
        break;
    case WM_CLOSE:
        EndDialog(hwndDlg, 0); // 關閉窗體
        break;
    case WM_COMMAND:
        /*GetDlgItemText(hwndDlg, Text_ProcessName, processName, sizeof(processName));
        GetDlgItemText(hwndDlg, Text_DLLPath, (LPWSTR)dllPath, sizeof(dllPath));*/

        if (wParam == Btn_Inject_DLL)
        {
            if (sizeof(processName) == 0)
            {
                MessageBox(NULL, TEXT("進程名稱不能為空"), TEXT("錯誤"), 0);
            }
            if (sizeof(dllPath) == 0)
            {
                MessageBox(NULL, TEXT("DLL路徑不能為空"), TEXT("錯誤"), 0);
            }
            InjectDll(processName, dllPath); // 注入DLL
        }
        if (wParam == Btn_unInject_DLL)
        {
            UnInjectDll(processName); // 卸載DLL
        }
        break;
    default:
        break;
    }
    return FALSE;
}


/// <summary>
/// 初始化
/// </summary>
/// <param name="hInstance"></param>
/// <param name="hPrevInstance"></param>
/// <param name="lpCmdLine"></param>
/// <param name="nCmdShow"></param>
/// <returns></returns>
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR    lpCmdLine,
    _In_ int       nCmdShow)
{
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, &dialogProc);
    return 0;
}

初學C++,代碼可能有些地方寫的不夠好,但是注入卸載是完全沒問題的。

注入邏輯解釋:

使用CreateRemoteThread 函數可以為目標進程創建一個新的線程。

在一個進程為另一個進程創建的線程就是遠程線程。

使用 LoadLibrary 函數把指定的DLL加載到進程中

因此就可以在創建遠程線程的同時調用 LoadLibrary 函數,把指定的DLL加載到目標進程中。

為什么創建遠程線程的時候調用 LoadLibrary 函數就能把 DLL 注入到目標進程中?

  • LoadLibrary  函數是 Kernel32.dll 中的一個成員

  • Kernel32.dll 這個DLL是創建進程必須的一個DLL,并且所有進程在內存中指向的 Kernel32.dll 是同一個地址

  • 所以只要獲取到當前進程中 LoadLibrary 函數的地址就夠了

為什么要在目標進程中開辟一塊內存,再把DLL路徑寫入到塊內存中?

  • LoadLibrary 函數需要一個參數,就是DLL的路徑

  • 把當前進程中的一個地址傳到另一個進程中,鬼知道另一個進程獲取這個地址中的數據時,讀取到的是否是我們想要的。

  • 因此需要把DLL的路徑直接寫入到目標進程中。

  • VirtualAllocEx 函數,在目標進程中開辟一塊空間,用來存放DLL路徑

  • WriteProcessMemory 函數,把DLL的路徑寫入進去

  • GetModuleHandle 獲取 Kernel32.dll 模塊

  • GetProcAddress 獲取 LoadLibraryA 函數在內存中的地址

  • CreateRemoteThread 創建遠程線程,并調用 LoadLibraryA 函數

LoadLibraryLoadLibraryALoadLibraryW 這三者的區別。

LoadLibrary 是一個宏,可以根據字符集的不同,自動決定是使用 LoadLibraryA 還是 LoadLibraryW

LoadLibrary 宏定義的源碼:

WINBASEAPI
_Ret_maybenull_
HMODULE
WINAPI
LoadLibraryA(
    _In_ LPCSTR lpLibFileName
    );

WINBASEAPI
_Ret_maybenull_
HMODULE
WINAPI
LoadLibraryW(
    _In_ LPCWSTR lpLibFileName
    );

#ifdef UNICODE
#define LoadLibrary  LoadLibraryW
#else
#define LoadLibrary  LoadLibraryA
#endif // !UNICODE

卸載邏輯:

使用 CreateRemoteThread 函數創建一個遠程線程

調用 FreeLibrary 函數,卸載DLL

FreeLibrary 函數在 Kernel32.dll 模塊中,邏輯同上

FreeLibrary 函數需要 DLL 的內存地址

遍歷進程快照可以獲取到指定模塊的內存地址

卸載和注入的思路都是一樣的

確認DLL是否注入到目標進程中:

方式一:使用 procexp

C++?DLL注入怎么實現

方式二:Cheat Engine

C++?DLL注入怎么實現

C++?DLL注入怎么實現

C++?DLL注入怎么實現

確認 Kernel32.dll 中的 FreeLibrary 和 LoadLibraryA 在多個進程中是否指向同一塊內存地址:

C++?DLL注入怎么實現

可以通過CE查看多個進程中  Kernel32.dll 的內存地址是否相同

再通過  Kernel32.dll 中函數的內存地址,確認 FreeLibrary 和 LoadLibraryA 這兩個函數

關于“C++ DLL注入怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

丹凤县| 巨野县| 金秀| 河津市| 中阳县| 平湖市| 永顺县| 吴江市| 沁水县| 三台县| 昌黎县| 惠东县| 台中县| 南昌市| 富顺县| 巴马| 时尚| 永定县| 博爱县| 安国市| 都昌县| 老河口市| 龙胜| 同心县| 碌曲县| 礼泉县| 亚东县| 苍溪县| 辽源市| 西城区| 白玉县| 东乡县| 山西省| 榆林市| 桂东县| 福建省| 久治县| 岳西县| 永清县| 武冈市| 天峻县|