遠程線程注入DLL


0x00 原理介紹:

上一篇文章介紹了在Windows下如何在其他進程創建一個遠程線程:https://www.cnblogs.com/DarkBright/p/10820582.html

調用 CreateRemoteThread 創建遠程線程所需要的過程函數的標准形式為:

DWORD WINAPI ThreadProc(
  _In_ LPVOID lpParameter
);

Win32編程加載DLL的API為:

HMODULE WINAPI LoadLibrary(
  _In_ LPCTSTR lpFileName
);

觀察發現 ThreadProc 與 LoadLibrary 函數類型是一致的,所以可以通過 CreateRemoteThread 在其他的進程中創建一個線程調用 LoadLibrary 加載我們准備的DLL

系統啟動后,kernel32.dll 的加載基址在各個進程中是相同的,因此導出函數(LoadLibrary)的地址也相同,即自己程序空間的LoadLibrary函數地址和其他進程空間的LoadLibrary函數地址相同

1

0x01 目標程序:

目標程序與上一篇文章(https://www.cnblogs.com/DarkBright/p/10820582.html)中的一致:

#include <windows.h>
#include <stdio.h>

void Fun(void)
{
     for(size_t i = 0; i < 10; i++)
         printf("%s addr:0x%p\r\n", __FUNCTION__, Fun);
}

int main(int argc, char* argv[])
{
     Fun();
     //MessageBox(NULL, TEXT("執行完成!"), TEXT("提示"), MB_OK);

    getchar();
     return 0;
}

編譯生成 Project1.exe

0x02 要注入的DLL:

在DLL成功注入到目標進程之后彈出一個信息框,代碼如下:

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注入成功!"), TEXT("提示"), MB_OK);
     case DLL_THREAD_ATTACH:
     case DLL_THREAD_DETACH:
     case DLL_PROCESS_DETACH:
         break;
     }
     return TRUE;
}

將生成的TestDLL.dll拷貝至桌面

0x03 注入程序:

注入程序編寫流程大致如下:

1、 獲取目標進程的句柄

2、 向目標進程中申請一片內存,要能夠容納 DLL路徑信息字符串 的長度

3、 將 DLL路徑信息字符串 寫入到步驟2申請的內存中

4、 獲取注入程序中 LoadLibraryA 的函數地址(前面已經說明該地址在目標程序中同樣適用)

5、 調用 CreateRemoteThread 在目標進程中創建一個線程,該線程調用 LoadLibraryA 加載我們准備的DLL

具體實現代碼如下:

#include <windows.h>
#include <string.h>
#include "Process.h"

#define        NAME    L"Project1.exe"
#define        DLL_NAME    "C:\\Users\\DarkBright\\Desktop\\TestDLL.dll"
//#define  DLL_NAME    "TestDLL.dll"

int main(int argc, char* argv[])
{
     Process* pProcess = new Process(NAME, FALSE);
     if (pProcess->hProcess == NULL) {
         OutputDebugString(TEXT("未找到目標進程!\r\n"));
         DWORD ret = GetLastError();
         exit(-1);
     }
     //OutputDebugString(TEXT("已找到目標進程!\r\n"));
     PVOID pDllName = VirtualAllocEx(pProcess->hProcess, NULL, strlen(DLL_NAME)+1,
                                     MEM_COMMIT, PAGE_READWRITE);
     if(pDllName == NULL){
         delete pProcess;
         OutputDebugString(TEXT("分配空間失敗!\r\n"));
         exit(-1);
     }
     pProcess->WriteByteArray(pDllName, (BYTE *)DLL_NAME, strlen(DLL_NAME) + 1);
     HMODULE hModule = GetModuleHandle(TEXT("Kernel32.dll"));
     if(hModule == NULL){
         VirtualFreeEx(pProcess->hProcess, pDllName, 0, MEM_RELEASE);
         delete pProcess;
         OutputDebugString(TEXT("GetModuleHandle失敗!\r\n"));
         exit(-1);
     }
     FARPROC pfnLoadLibraryA = GetProcAddress(hModule, "LoadLibraryA");
     HANDLE hThread = CreateRemoteThread(pProcess->hProcess, NULL, 0,
                                         (LPTHREAD_START_ROUTINE)pfnLoadLibraryA,
                                         pDllName, 0, NULL);
     if(hThread == NULL){
         VirtualFreeEx(pProcess->hProcess, pDllName, 0, MEM_RELEASE);
         delete pProcess;
         OutputDebugString(TEXT("CreateRemoteThread失敗!\r\n"));
         exit(-1);
     }
     CloseHandle(hThread);

    delete pProcess;
     return 0;
}

#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )

其中 Process 類的相關內容參考:https://www.cnblogs.com/DarkBright/p/10809092.html

最后一行:#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" ) 表示隱藏控制台

運行 Project1.exe 並且適用調試器附加(注意是附加,不要直接用調試器打開程序):

2

將 TestDLL.dll 拷貝至桌面后運行注入程序:

3

彈框提示注入成功,並且在調試器的模塊列表中也可以發現新注入的DLL


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM