[逆向工程]C++實現DLL注入:原理、實現與防御全解析(二十五)

[逆向工程]C++實現DLL注入:原理、實現與防御全解析(二十五)

引言

DLL注入(DLL Injection)是Windows系統下實現進程間通信、功能擴展、監控調試的核心技術之一。本文將從原理分析、代碼實現、實戰調試到防御方案,全方位講解如何用C++實現DLL注入,并提供可直接編譯的完整項目代碼。

一、資源準備

1.資源準備

gmp.exe 被注入的程序

injector.exe 注入器

mandaohook.dll 需注入的dll

2.任務目標

將編寫好的mandaohook.dll通過injector.exe注入器注入到gmp.exe可運行程序中。gmp.exe是一個密碼學工具箱。

二、DLL注入的核心原理

DLL注入的本質是強制目標進程加載指定的DLL文件,其核心流程為:

  1. 獲取目標進程句柄:通過進程ID或進程名定位目標
  2. 在目標進程中分配內存:用于存儲DLL路徑
  3. 寫入DLL路徑:將DLL的完整路徑寫入目標內存
  4. 創建遠程線程:通過LoadLibrary加載DLL

三、關鍵API函數解析

API函數作用描述關鍵參數說明
OpenProcess打開目標進程dwProcessId:目標進程ID
VirtualAllocEx在目標進程分配內存lpAddress:分配內存地址
WriteProcessMemory向目標內存寫入數據lpBaseAddress:目標內存地址
CreateRemoteThread在目標進程創建遠程線程lpStartAddress:線程入口點
GetProcAddress獲取LoadLibrary函數地址lpProcName:函數名

四、完整C++實現代碼

1. 注入器代碼(Injector.cpp)
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <memory>// 自動釋放資源模板
template<typename T>
struct HandleDeleter {void operator()(T* handle) const {if (handle) CloseHandle(handle);}
};
using UniqueHandle = std::unique_ptr<void, HandleDeleter<void>>;// 查找進程ID(優化版)
DWORD FindProcessId(const wchar_t* processName) {PROCESSENTRY32W pe = { sizeof(pe) };UniqueHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));if (!snapshot.get()) return 0;if (Process32FirstW(snapshot.get(), &pe)) {do {if (_wcsicmp(processName, pe.szExeFile) == 0) {return pe.th32ProcessID;}} while (Process32NextW(snapshot.get(), &pe));}return 0;
}// 注入主函數
int main() {// 1. 查找進程const DWORD pid = FindProcessId(L"gmp.exe");if (!pid) {std::wcerr << L"錯誤:未找到進程!" << std::endl;return EXIT_FAILURE;}// 2. 打開進程UniqueHandle hProcess(OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,FALSE, pid));if (!hProcess) {std::wcerr << L"打開進程失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 3. 獲取DLL路徑wchar_t dllPath[MAX_PATH];if (!GetFullPathNameW(L"mandaohook.dll", MAX_PATH, dllPath, nullptr)) {std::wcerr << L"獲取路徑失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 4. 分配內存const size_t pathSize = (wcslen(dllPath) + 1) * sizeof(wchar_t);UniqueHandle pRemoteMem(VirtualAllocEx(hProcess.get(), nullptr, pathSize, MEM_COMMIT, PAGE_READWRITE));if (!pRemoteMem) {std::wcerr << L"內存分配失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 5. 寫入路徑if (!WriteProcessMemory(hProcess.get(), pRemoteMem.get(), dllPath, pathSize, nullptr)) {std::wcerr << L"寫入內存失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 6. 獲取LoadLibrary地址const auto pLoadLibrary = reinterpret_cast<LPTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"));if (!pLoadLibrary) {std::wcerr << L"獲取函數地址失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 7. 創建遠程線程UniqueHandle hThread(CreateRemoteThread(hProcess.get(), nullptr, 0,pLoadLibrary, pRemoteMem.get(), 0, nullptr));if (!hThread) {std::wcerr << L"創建線程失敗(代碼:" << GetLastError() << L")" << std::endl;return EXIT_FAILURE;}// 8. 等待注入完成WaitForSingleObject(hThread.get(), INFINITE);std::wcout << L"注入成功!" << std::endl;return EXIT_SUCCESS; 
}

編譯:

g++ -shared -o mandaohook.dll mandaohook.cpp -luser32 -lgdi32 -Wall

在這里插入圖片描述

2.目標DLL頭文件(mandaohook.h)
#pragma once
#include <Windows.h>LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam);
3. 目標DLL代碼(mandaohook.cpp)
/*********************** myhook.cpp ***********************/
#include "mandaohook.h"// 全局變量
HHOOK g_hHook = NULL;
HWND g_hNotepadppWnd = NULL;// 前向聲明線程函數
DWORD WINAPI ThreadProc(LPVOID lpParameter);//-----------------------------------------------------------------------------
// DLL入口函數
//-----------------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:// 創建線程避免阻塞DllMainCreateThread(nullptr, 0, ThreadProc, hModule, 0, nullptr);break;case DLL_PROCESS_DETACH:if (g_hHook) {UnhookWindowsHookEx(g_hHook);g_hHook = nullptr;}break;}return TRUE;
}// 線程處理函數
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{HMODULE hModule = (HMODULE)lpParameter;// 使用 OutputDebugStringW 輸出調試信息OutputDebugStringW(L"DLL成功注入gmp.exe!");MessageBoxW(nullptr, L"DLL成功注入gmp.exe!", L"提示", MB_OK);g_hNotepadppWnd = FindWindowExW(nullptr, nullptr, L"gmp.exe", nullptr);if (g_hNotepadppWnd) {g_hHook = SetWindowsHookExW(WH_KEYBOARD_LL,HookProc,hModule,0);}return 0;
}//-----------------------------------------------------------------------------
// 鉤子處理函數
//-----------------------------------------------------------------------------
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{if (code == HC_ACTION) {const auto* pKbd = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);if (pKbd->vkCode == VK_F12 && (pKbd->flags & LLKHF_UP)) {MessageBoxW(g_hNotepadppWnd, L"安全提示:F12功能已被攔截!", L"安全防護", MB_ICONWARNING | MB_OK);return 1;}}return CallNextHookEx(g_hHook, code, wParam, lParam);
}

編譯:

g++ -shared -o mandaohook.dll mandaohook.cpp -luser32 -lwininet -Wall -municode

在這里插入圖片描述

五、測試結果

gmp.exe injector.exe mandaohook.dll放入同一個文件夾下:

在這里插入圖片描述

1.先打開gmp.exe 工具

2.再打開DebugView

3.執行injector.exe 注入器注入

4.查看注入信息

可以先查看下gmp.exe PID
在這里插入圖片描述
在這里插入圖片描述

查看DebugView已注入。

六、技術難點與解決方案

1. 權限問題
  • 癥狀OpenProcess返回ERROR_ACCESS_DENIED
  • 解決:以管理員權限運行注入器
  • 代碼實現
    #include <ShellAPI.h>
    ShellExecuteW(nullptr, L"runas", L"Injector.exe", nullptr, nullptr, SW_SHOW);
    
2. 路徑轉換問題
  • 癥狀:DLL路徑包含中文字符導致寫入失敗
  • 解決:使用寬字符API并驗證路徑
    if (!PathFileExistsW(dllPath)) {// 處理路徑不存在的情況
    }
    
3. 64/32位進程兼容
  • 癥狀:跨架構注入失敗(如64位注入器操作32位進程)
  • 解決:使用Wow64DisableWow64FsRedirection
    PVOID oldValue = nullptr;
    Wow64DisableWow64FsRedirection(&oldValue);
    // 執行文件操作
    Wow64RevertWow64FsRedirection(oldValue);
    

七、防御DLL注入方案

  1. 進程保護:調用SetProcessMitigationPolicy
    PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY policy = {};
    policy.MicrosoftSignedOnly = 1;
    SetProcessMitigationPolicy(ProcessSignaturePolicy, &policy, sizeof(policy));
    
  2. 鉤子檢測:定期檢查LoadLibrary調用棧
  3. 內存保護:啟用DEP和ASLR
    #pragma comment(linker, "/DYNAMICBASE:YES")
    #pragma comment(linker, "/NXCOMPAT")
    

八、實戰調試技巧

  1. 調試輸出:使用OutputDebugStringW
    OutputDebugStringW(L"[DEBUG] DLL已加載");
    
  2. 日志文件:寫入臨時文件監控行為
    FILE* f = _wfopen(L"C:\\inject_log.txt", L"a+");
    fwprintf(f, L"PID:%d 已注入\n", GetCurrentProcessId());
    fclose(f);
    
  3. Process Monitor:監控進程的DLL加載事件

如果本教程對您有幫助,請點贊??收藏?關注支持!歡迎在評論區留言交流技術細節!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81224.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81224.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81224.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ROS2實戰】在中國地區 Ubuntu 22.04 上安裝 ROS 2 Humble 教程

本文介紹如何在中國大陸環境下順利安裝 ROS 2 Humble&#xff0c;包括使用清華鏡像源、解決 locale 和 GPG 密鑰問題、安裝 ROS 軟件包以及配置自動環境加載。 &#x1f31f; ROS 2 版本簡介 ROS 2 是機器人操作系統的第二代版本&#xff0c;目前主要有兩個長期支持&#xff0…

嵌入式學習筆記 - STM32 ADC 模塊工作模式總結

ADC 模式總結&#xff1a; 一 單ADC模式&#xff08;是指ADC1,ADC2,ADC3中只有一個ADC被使用&#xff09; ①單通道&#xff1a; 非連續模式&#xff1a;非連續的意思就是單次&#xff0c;一次轉換完成后就停止轉換&#xff0c;除非再次被軟件或者被外部觸發啟動&#xff1b…

Python訓練打卡Day26

函數專題1&#xff1a;函數定義與參數 知識點回顧&#xff1a; 函數的定義變量作用域&#xff1a;局部變量和全局變量函數的參數類型&#xff1a;位置參數、默認參數、不定參數傳遞參數的手段&#xff1a;關鍵詞參數傳遞參數的順序&#xff1a;同時出現三種參數類型時 到目前為…

使用Docker部署Nacos

sudo systemctl start docker sudo systemctl enable docker docker --version 步驟 2: 拉取 Nacos Docker 鏡像 拉取 Nacos 鏡像&#xff1a; 你可以從 Docker Hub 上拉取官方的 Nacos 鏡像&#xff0c;使用以下命令&#xff1a; docker pull nacos/nacos-server 這會從 …

Ubuntu 添加系統調用

實驗內容 通過內核編譯法添加一個不用傳遞參數的系統調用&#xff0c;其功能可自定義。 &#xff08;1&#xff09;添加系統調用號&#xff0c;系統會根據這個號找到syscall_table中的相應表項。具體做法是在syscall_64.tbl文件中添加系統調用號和調用函數的對應關系。 &#…

Javascript:WebAPI

獲取網頁元素 queryselector queryselector是 JavaScript 中用于選擇 DOM 元素的重要方法&#xff0c;它允許使用 CSS 選擇器語法來查找頁面中的元素。 一般queryselector獲取的元素都是html中第一個選擇器的元素 支持選擇器類型&#xff1a;類選擇器(.class) &#xff0c…

十二、Hive 函數

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月1日 專欄&#xff1a;Hive教程 在數據處理的廣闊天地中&#xff0c;我們常常需要對數據進行轉換、計算、清洗或提取特定信息。Hive 提供了強大的內置運算符和豐富的內置函數庫&#xff0c;它們就像魔法師手中的魔法棒&…

Linux之Nginx安裝及配置原理篇(一)

Nginx安裝及配置 前情回顧 首先針對Nginx進程模型&#xff0c;我們回顧一下它的原理機制&#xff0c;我們知道它是通過Master通過fork分發任務節點給予work節點&#xff0c;然后work節點觸發了event事件&#xff0c;之后通過一個access_muttex互斥鎖&#xff0c;來單線程調用我…

嵌入式培訓之數據結構學習(五)棧與隊列

一、棧 &#xff08;一&#xff09;棧的基本概念 1、棧的定義&#xff1a; 注&#xff1a;線性表中的棧在堆區&#xff08;因為是malloc來的&#xff09;&#xff1b;系統中的棧區存儲局部變量、函數形參、函數返回值地址。 2、棧頂和棧底&#xff1a; 允許插入和刪除的一端…

深度學習---知識蒸餾(Knowledge Distillation, KD)

一、知識蒸餾的本質與起源 定義&#xff1a; 知識蒸餾是一種模型壓縮與遷移技術&#xff0c;通過將復雜高性能的教師模型&#xff08;Teacher Model&#xff09;所學的“知識”遷移到輕量級的學生模型&#xff08;Student Model&#xff09;&#xff0c;使學生模型在參數量和計…

ARP Detection MAC-Address Static

一、ARP Detection&#xff08;ARP檢測&#xff09; ? 定義&#xff1a; ARP檢測是一種防止ARP欺騙攻擊的安全機制。它通過監控或驗證網絡中的ARP報文&#xff0c;來判斷是否存在偽造的ARP信息。 &#x1f50d; 工作原理&#xff1a; 網絡設備&#xff08;如交換機&#xf…

基于 Python 的界面程序復現:標準干涉槽型設計計算及仿真

基于 Python 的界面程序復現&#xff1a;標準干涉槽型設計計算及仿真 在工業設計與制造領域&#xff0c;刀具的設計與優化是提高生產效率和產品質量的關鍵環節之一。本文將介紹如何使用 Python 復現一個用于標準干涉槽型設計計算及仿真的界面程序&#xff0c;旨在幫助工程師和…

Python繪制南丁格爾玫瑰圖:從入門到實戰

Python繪制南丁格爾玫瑰圖&#xff1a;從入門到實戰 引言 南丁格爾玫瑰圖&#xff08;Nightingale Rose Chart&#xff09;&#xff0c;也被稱為極區圖&#xff08;Polar Area Chart&#xff09;&#xff0c;是一種獨特的數據可視化方式。這種圖表由弗洛倫斯南丁格爾&#xff…

計算機操作系統概要

不謀萬世者&#xff0c;不?謀?時。不謀全局者 &#xff0c;足謀?域 。 ——陳澹然《寤?》《遷都建藩議》 操作系統 一.對文件簡單操作的常用基礎指令 ls ls 選項 目錄或?件名:羅列當前?錄下的?件 -l&#xff1a;以長格式顯示?件和?錄的詳細信息 -a 或 --all&…

<PLC><視覺><機器人>基于海康威視視覺檢測和UR機械臂,如何實現N點標定?

前言 本系列是關于PLC相關的博文,包括PLC編程、PLC與上位機通訊、PLC與下位驅動、儀器儀表等通訊、PLC指令解析等相關內容。 PLC品牌包括但不限于西門子、三菱等國外品牌,匯川、信捷等國內品牌。 除了PLC為主要內容外,相關設備如觸摸屏(HMI)、交換機等工控產品,如果有…

從專家編碼到神經網絡學習:DTM 的符號操作新范式

1st author: Paul Soulos paper: Differentiable Tree Operations Promote Compositional Generalization ICML 2023 code: psoulos/dtm: Differentiable Tree Machine 1. 問題與思路 現代深度學習在連續向量空間中取得了巨大成功&#xff0c;然而在處理具有顯式結構&#x…

微信小程序第三方代開發模式技術調研與實踐總結

?? 微信小程序第三方代開發模式技術調研與實踐總結 ?? 前言 隨著企業對私有化品牌運營訴求的增加,許多大型客戶希望將原本由 SaaS 平臺統一提供的小程序遷移至自有主體(AppID)下運行,同時又希望繼續沿用 SaaS 平臺的業務服務與數據托管方式。微信開放平臺提供的“小程…

開啟智能未來:DeepSeek賦能行業變革之路

前言 在人工智能重構生產關系的2025年&#xff0c;DeepSeek以其革命性的推理能力和Python生態的技術延展性&#xff0c;正在重塑內容創作與數據智能的邊界。本書以"工具迭代思維升維"為雙輪驅動&#xff0c;構建從認知突破到商業落地的完整知識圖譜。 DeepSeek的崛…

常見三維引擎坐標軸 webgl threejs cesium blender unity ue 左手坐標系、右手坐標系、坐標軸方向

平臺 / 引擎坐標系類型Up&#xff08;上&#xff09;方向Forward&#xff08;前進&#xff09;方向前進方向依據說明Unity左手坐標系YZtransform.forward 是 Z 軸正方向&#xff0c;默認攝像機朝 Z 看。Unreal Engine左手坐標系ZXUE 的角色面朝 X&#xff0c;默認使用 GetActor…

Cold Diffusion: Inverting Arbitrary Image Transforms Without Noise論文閱讀

冷擴散&#xff1a;無需噪聲的任意圖像變換反轉 摘要 標準擴散模型通常涉及兩個核心步驟&#xff1a;圖像降質 &#xff08;添加高斯噪聲&#xff09;和圖像恢復 &#xff08;去噪操作&#xff09;。本文發現&#xff0c;擴散模型的生成能力并不強烈依賴于噪聲的選擇&#xf…