使用CreateRemoteThread把代碼遠程注入指定exe執行


由於本人也是新手,如果有朋友不懂windows api相關知識,我相信查閱書籍或者百度會比我說有幫助的多,下面就我所做簡單復述一下過程,歡迎指正缺點。

效果圖示如下:

做的這個例子首先是創建了一個MFC 對話框程序,然后自己創建了一個 帶有導出函數 (簡單的減法) 的DLL , 這個Calc按鍵就是調用自己DLL里面的減法函數 計算1 - 1, 其次創建一個擁有能夠修改進程中某函數的入口代碼功能的DLL(為什么是DLL,網上有大量詳細的資料,), 然后我們還創建一個windows控制台程序 也就是 調用CreateRemoteThread  讓Calc 加載我們准備好的DLL(修改函數入口代碼), 因為DLL被加載時我們可以在DLLMain中指定要執行的代碼。

未注入代碼之前:

 

執行我的 注入程序createremotethread.exe 之后 如下圖:

 

可以看到注入成功了, 注入的是什么呢? 這就是 CreateRemoteThread的作用了, 我們向Calc.exe 注入了一個線程,然后這個線程執行了LoadLibrary 函數,

我告訴Calc 要Load 我指定的 DLL, 為什么呢? 因為 我指定的這個DLL 是我們自己創建的, 它里面的函數代碼能找到Calc進程中 原來sub函數的地址,然后並

修改sub函數地址處的入口代碼,也就是改成 jmp xxx 使Calc 執行我們指定的代碼。

 

最重要的CreateRemoteThread:

   HANDLE hThread;
    char szLibPath[_MAX_PATH] = "E:\\vs2010project\\InjectDll\\Release\\InjectDll.dll"; //指定注入之后目標進程要加載的DLL

    DWORD hLibModule;

    HANDLE hProcess = NULL;
    hProcess = GetProcessByName("Calc.exe");
    DWORD ERRO = GetLastError();

    if(hProcess == NULL)
        return 0;

    HMODULE modHandle = GetModuleHandle(_T("Kernel32")); //因為kernel32 每一個windows程序進程空間中都有 所以讓他調用LOADLIBRARY不成問題

  void* pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    LPTHREAD_START_ROUTINE addr = (LPTHREAD_START_ROUTINE)GetProcAddress(modHandle, "LoadLibraryA");
    WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL);
 
    hThread = CreateRemoteThread(hProcess, NULL, 0,
                                addr,
                                pLibRemote,
                                0,
                                NULL);
    
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);

 

 

根據進程名字獲取進程句柄也是本例子非常關鍵的部分,可以通過微軟提供的api 拍攝進程列表快照, 然后再遍歷尋找,代碼如下:

HANDLE GetProcessByName(const char* name)
{
    EnableDebugPriv();
    DWORD pid = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);
    if (Process32First(snapshot, &process))
    {
        do
        {
            if( stricmp(UnicodeToAnsi(process.szExeFile), name) == 0)
            {
                pid = process.th32ProcessID;
                break;
            }
        }while(Process32Next(snapshot, &process));
    }
    CloseHandle(snapshot);
    
    if(pid != 0)
    {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);        
        return hProcess;
    }

    return NULL;
    
}

 

 

其中 關於 CreateRemoteThread 部分的核心代碼有許多需要注意的事情 主要有 執行OPENPROCESS之前需要開啟特權 代碼如下:

 1 void EnableDebugPriv()
 2 {
 3     HANDLE hToken;
 4     LUID luid;
 5     TOKEN_PRIVILEGES tkp;
 6 
 7     OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
 8 
 9     LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
10 
11     tkp.PrivilegeCount = 1;
12     tkp.Privileges[0].Luid = luid;
13     tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
14 
15     AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
16 
17     CloseHandle(hToken); 
18 }

接下來我們就可以調用openprocess 打開目標進程 進行進一步的操作(調用CreateRemoteThread)達到使目標進程加載我們指定DLL,進而指定DLL被加載時能執行指定代碼。

 

最后 關於修改進程中 導入 dll 中的函數的入口處代碼 的代碼如下:

BYTE NewCode[5]; //用來替換原入口代碼的字節 (jmp xxxx)

typedef int (_cdecl* getsub)(int x,int y);    //typedef 比較少的用法 能定一個函數指針類型 即getsub 
getsub mySub = NULL; //用新定義的類型定義一個變量
FARPROC pfar_sub;   //指向mySub函數的遠指針

HANDLE hProcess = NULL; //所處進程的句柄
DWORD pid;    //所處進程ID


//
修改mySub入口處代碼 void modify() { assert(hProcess != NULL); DWORD dwTemp=0; DWORD dwOldProtect; VirtualProtectEx(hProcess, pfar_sub, 5, PAGE_READWRITE, &dwOldProtect); //將內存保護模式改為可讀寫,原保護模式保存入dwOldProtect WriteProcessMemory(hProcess, pfar_sub, NewCode, 5, 0); VirtualProtectEx(hProcess, pfar_sub, 5, dwOldProtect, &dwTemp); //恢復內存保護模式 } int new_sub(int x,int y) { return 1; } int inject() { DWORD dwPid = ::GetCurrentProcessId(); hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid); int addr_farpointer = 0; //獲取My_sub()函數地址 HMODULE hmod = ::LoadLibrary(_T("E:\\vs2010project\\My_Sub\\Debug\\My_Sub.dll")); mySub = (getsub)::GetProcAddress(hmod, "mySub"); pfar_sub=(FARPROC)mySub; addr_farpointer = (int)pfar_sub; if (pfar_sub == NULL) { MessageBox(NULL, TEXT("locate mySub failed!!"), TEXT("info"), MB_OK); return FALSE; } NewCode[0] = 0xe9;//0xe9 == jmp _asm { lea eax, new_sub mov ebx, pfar_sub sub eax, ebx sub eax, 5 mov dword ptr [NewCode + 1],eax } modify(); MessageBox(NULL, TEXT("Modified SUCCESSFULLY!!"), TEXT("info"), MB_OK); return TRUE; }

 

 

整體流程清楚了實踐應該沒啥問題(還是需要折騰的, 折騰也是進步的過程)。

附上主要工程文件鏈接 http://pan.baidu.com/s/1dD4WhZN


免責聲明!

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



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