APC註入APCInject(DLL)
阿新 • • 發佈:2018-10-21
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
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)