1. 程式人生 > >APC註入APCInject(DLL)

APC註入APCInject(DLL)

include mit over 路徑 dal inf todo als 動態

APC註入的原理是利用當線程被喚醒時APC中的註冊函數會被執行的機制,並以此去執行我們的DLL加載代碼,進而完成DLL註入的目的,其具體流程如下:
1)當EXE裏某個線程執行到SleepEx()或者WaitForSingleObjectEx()時,系統就會產生一個軟中斷(或者是Messagebox彈窗的時候不點OK的時候也能註入)。
2)當線程再次被喚醒時,此線程會首先執行APC隊列中的被註冊的函數。
3)利用QueueUserAPC()這個API可以在軟中斷時向線程的APC隊列插入一個函數指針,如果我們插入的是Loadlibrary()執行函數的話,就能達到註入DLL的目的。
// APCInject.h


#pragma once

// APCInject 對話框

class APCInject : public CDialogEx
{
    DECLARE_DYNAMIC(APCInject)

public:
    APCInject(CWnd* pParent = NULL);   // 標準構造函數
    virtual ~APCInject();

// 對話框數據
    enum { IDD = IDD_DIALOG5 };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

    DECLARE_MESSAGE_MAP()
public:
    CString m_strExePath;
    CString m_strDllPath;
    afx_msg void OnBnClickedButton3();
    afx_msg void OnBnClickedButton4();
    afx_msg void OnBnClickedInject();
};

// APCInject.cpp

// APCInject.cpp : 實現文件
//

#include "stdafx.h"
#include "MyInjectTool.h"
#include "APCInject.h"
#include "afxdialogex.h"

// APCInject 對話框

IMPLEMENT_DYNAMIC(APCInject, CDialogEx)

APCInject::APCInject(CWnd* pParent /*=NULL*/)
    : CDialogEx(APCInject::IDD, pParent)
    , m_strExePath(_T(""))
    , m_strDllPath(_T(""))
{

}

APCInject::~APCInject()
{
}

void APCInject::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT1, m_strExePath);
    DDX_Text(pDX, IDC_EDIT2, m_strDllPath);
}

BEGIN_MESSAGE_MAP(APCInject, CDialogEx)
    ON_BN_CLICKED(IDC_BUTTON3, &APCInject::OnBnClickedButton3)
    ON_BN_CLICKED(IDC_BUTTON4, &APCInject::OnBnClickedButton4)
    ON_BN_CLICKED(IDC_INJECT, &APCInject::OnBnClickedInject)
END_MESSAGE_MAP()

// APCInject 消息處理程序

void APCInject::OnBnClickedButton3()
{
    // TODO:  在此添加控件通知處理程序代碼
    char szFilter[] = "可執行程序|*.exe";
    CFileDialog fileDlg(TRUE, "exe", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
    UpdateData(TRUE);
    if (fileDlg.DoModal() == IDOK)
    {
        m_strExePath = fileDlg.GetPathName();
    }
    UpdateData(FALSE);
}

void APCInject::OnBnClickedButton4()
{
    // TODO:  在此添加控件通知處理程序代碼
    char szFilter[] = "動態鏈接庫|*.dll";
    CFileDialog fileDlg(TRUE, "dll", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
    UpdateData(TRUE);
    if (fileDlg.DoModal() == IDOK)
    {
        m_strDllPath = fileDlg.GetPathName();
    }
    UpdateData(FALSE);
}

void APCInject::OnBnClickedInject()
{
    // TODO:  在此添加控件通知處理程序代碼
    DWORD dwRet = 0;
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&pi, sizeof(pi));
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFO);

    //以掛起的方式創建進程
    dwRet = CreateProcess(m_strExePath.GetBuffer(0),
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_SUSPENDED,
        NULL,
        NULL,
        &si,
        &pi);

    if (!dwRet)
    {
        MessageBox("CreateProcess失敗!!");
        return;
    }

    PVOID lpDllName = VirtualAllocEx(pi.hProcess,
        NULL,
        m_strDllPath.GetLength(),
        MEM_COMMIT,
        PAGE_READWRITE);

    if (lpDllName)
    {
        //將DLL路徑寫入目標進程空間
        if (WriteProcessMemory(pi.hProcess, lpDllName, m_strDllPath.GetBuffer(0), m_strDllPath.GetLength(), NULL))
        {
            LPVOID nLoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
            //向遠程APC隊列插入LoadLibraryA
            if (!QueueUserAPC((PAPCFUNC)nLoadLibrary, pi.hThread, (DWORD)lpDllName))
            {
                MessageBox("QueueUserAPC失敗!!");
                return;
            }
        }
        else
        {
            MessageBox("WriteProcessMemory失敗!!");
            return;
        }
    }

    //恢復主線程
    ResumeThread(pi.hThread);
    MessageBox("APC註入成功");

}

APC註入APCInject(DLL)