APC注入APCInject(DLL)
阿新 • • 發佈:2018-11-08
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注入成功"); }