遠程線程DLL注入64位進程


 1 int main()
 2 {
 3     BOOL bFlag = FALSE;
 4 
 5     char *szDllName = "MSGDLL.dll";
 6     //bFlag = EnablePrivilege(SE_DEBUG_NAME);    //返回值為1時代表成功
 7 
 8 
 9     //得到目標進程句柄
10     HANDLE hDestProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 7084);
11 
12     LPTHREAD_START_ROUTINE dwAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
13 
14     //在目標進程的地址空間內分配一個內存塊
15     LPVOID pRemoteSpace = VirtualAllocEx(hDestProcess, NULL, strlen(szDllName) + 1, MEM_COMMIT,
16         PAGE_READWRITE);
17 
18     //向上一步的內存塊中寫入數據,就是要加載的DLL名字
19     bFlag = WriteProcessMemory(hDestProcess, pRemoteSpace, szDllName, strlen(szDllName) + 1, 0);
20 
21     //在目標進程內創建線程,線程的入口函數就是LoadLibraryA, 參數就是Dll名字
22     HANDLE hThread = CreateRemoteThread(hDestProcess, NULL, 0, dwAddr, pRemoteSpace,
23         NULL, 0
24     );      //前面都是成功的,就到了這一步,返回的錯誤是5,Access denied,權限不夠
25             //本來以為我的VS是以管理員權限啟動的,那么我這個進程應該權限就都夠了,
26             //看來不行,必須程序提權
27             //我提權了之后,發現還是不行,之后上網查了
28             //發現是32位注入到64位中會有問題,所以我換了個x64,然后顯然線程運行成功了,
29             //但是現在遠程進程卻崩潰了,估計是DLL是32的,我換個DLL編譯方式再試試
30             //我編譯了64位的DLL,然后還是崩潰的,之后我發現了應該是我函數地址傳的有問題
31             //因為32位的LoadLibraryA地址是DWORD,但64位卻是ULONGLONG,所以僅僅改變編譯方式還不夠
32             //必須用一個足夠容納8個字節地址的類型來保存,這樣就夠了
33 
34             //另外一個需要注意的問題就是,為什么我在我這個進程中得到的LoadLibrary在遠程進程中也可以用
35             //答案就是,系統DLL在各個進程中的映射地址都是一樣的,不過具體情況具體分析,至少這個函數看來是一樣的。
36 
37             //在我完成了之后,我把EnablePrivileges這行注釋掉了,但仍然注入成功,看來我用管理員權限運行VS2015之后就夠了
38             
39             //然后我又發現了一個問題,就是對同一個進程,加載dll只能一次,第二次就不會彈了
40             //原因,我目測是,DLL已經被加載了,所以第二次就不加載了,也就不執行DllMain那個函數了
41             //除非我創建一個線程再UnLoad那個LIB,之后再LOAD,這樣應該就可以了
42             //也可以換個Dll名字,再LOAD, 反正方法很多。
43 
44     DWORD dwErr = GetLastError();
45 
46     return 0;
47 }
 //DLL的代碼,用DLL方式生成一下,拉到前面EXE目錄,或者系統目錄都行,跟前面代碼中DLL名字有沒有加絕對路徑有關
//這代碼是書上的代碼,直接復制了
/* ************************************
*《精通Windows API》
* 示例代碼
* msg.c                  
* 6.5  動態鏈接庫
**************************************/
/* 頭文件 */
#include <Windows.h>
#include <Psapi.h>
/* 鏈接 */
#pragma comment (lib, "Psapi.lib") 
/* 函數聲明 */

// 使用__declspec(dllexport)聲明導出函數
__declspec(dllexport) DWORD ExportExample(LPSTR szMsg, DWORD dwCode);

/*************************************
* DllMain
**************************************/
BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // DLL模塊的句柄
    DWORD fdwReason,     // 調用的情況
    LPVOID lpReserved)  // reserved
{
    // 在不同的情況下都會調用DllMain函數,分別處理
    switch (fdwReason)
    {
        // 加載Dll
        case DLL_PROCESS_ATTACH:
            {
                CHAR lpMainMoudleName[MAX_PATH];
                CHAR lpMessage[MAX_PATH + 64];
                // 獲取PID 和主模塊名,將彈出消息框
                DWORD dwPID = GetCurrentProcessId();
                GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);
                wsprintf(lpMessage, "Process name: %s, PID: %u ", lpMainMoudleName, dwPID);
                MessageBox(NULL, lpMessage, "msg.dll", MB_OK);
                break;
            }
            // 新建線程
        case DLL_THREAD_ATTACH:
            break;
            // 線程退出
        case DLL_THREAD_DETACH:
            break;
            // 釋放Dll
        case DLL_PROCESS_DETACH:

            break;
    }
    return TRUE;
}

/*************************************
* DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
* 功能    導出函數,顯示消息
*
* 參數    LPSTR szMsg    字符串; DWORD dwCode 整形
**************************************/
DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
{
    LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), 0, lstrlen(szMsg) + 100);
    wsprintf((LPSTR)lpShowOut, "%s,%d", szMsg, dwCode);
    MessageBox(NULL, (LPSTR)lpShowOut, "由導出函數彈出的消息!", MB_OK);
    HeapFree(GetProcessHeap(), 0, lpShowOut);
    return 0;
}

需要注意的點都在那一大串注釋中

64位進程,就得用64位的EXE來CreateRemoteThread, 另外DLL也應該是64位

32位進程,就得用32位的EXE來CreateRemoteThread, 另外DLL也應該是32位

 

把CreateRemoteThread的入口點函數設為LoadLibraryA(W),線程的那個參數設為DLL路徑指針(在目標進程中,所以得把DLL路徑拷到目標進程 中, 用VirtualAllocEx在目標進程中分配塊空間,然后WriteProcessMemory).

這樣可行的原因:

  線程的函數原型DWORD ThreadProc(LPVOID lpParam)

  LoadLibrary的函數原型HMODULE LoadLibrary(LPCTSTR lpFileName);

其實是一樣的,指針都是同樣大小,都只有一個參數,返回值無所謂..

另外在目標進程和本進程中LoadLibraryA(W)的虛擬地址是一樣的..

 


免責聲明!

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



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