APC注入APCInject(DLL)

https://github.com/haidragon/win10_UserApcInject
APC注入APCInject(DLL)
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注入成功");

}

转载于:https://blog.51cto.com/haidragon/2306937

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
APC(Asynchronous Procedure Call)注入是一种常见的DLL注入方法,可以用于向目标进程注入代码。下面是一个简单的C语言APC注入DLL的实现过程: 1. 打开目标进程(使用CreateProcess或OpenProcess函数)。 2. 在目标进程中申请内存空间(使用VirtualAllocEx函数),用于存放DLL路径字符串和LoadLibrary函数地址。 3. 将DLL路径字符串写入目标进程中申请的内存空间(使用WriteProcessMemory函数)。 4. 获取LoadLibrary函数的地址(使用GetModuleHandle和GetProcAddress函数)。 5. 使用CreateRemoteThreadEx函数创建一个远程线程,传入LoadLibrary函数地址和DLL路径字符串地址作为参数。 6. 使用QueueUserAPC函数将一个APC函数插入目标进程的线程中。该APC函数将执行LoadLibrary函数,并将DLL路径字符串作为参数传入。 7. 关闭目标进程句柄(使用CloseHandle函数)。 以下是一个简单的实现示例: ```c #include <stdio.h> #include <windows.h> int main() { // 目标进程ID DWORD pid = 1234; // DLL路径 const char* dllPath = "C:\\path\\to\\mydll.dll"; // 打开目标进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { printf("OpenProcess failed: %d\n", GetLastError()); return 1; } // 在目标进程中申请内存空间 LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE); if (remoteMem == NULL) { printf("VirtualAllocEx failed: %d\n", GetLastError()); CloseHandle(hProcess); return 1; } // 写入DLL路径字符串 if (!WriteProcessMemory(hProcess, remoteMem, dllPath, strlen(dllPath) + 1, NULL)) { printf("WriteProcessMemory failed: %d\n", GetLastError()); VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hProcess); return 1; } // 获取LoadLibrary函数地址 HMODULE hKernel32 = GetModuleHandle("kernel32.dll"); if (hKernel32 == NULL) { printf("GetModuleHandle failed: %d\n", GetLastError()); VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hProcess); return 1; } FARPROC pLoadLibrary = GetProcAddress(hKernel32, "LoadLibraryA"); if (pLoadLibrary == NULL) { printf("GetProcAddress failed: %d\n", GetLastError()); VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hProcess); return 1; } // 创建远程线程 HANDLE hThread = CreateRemoteThreadEx(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, remoteMem, 0, NULL, NULL); if (hThread == NULL) { printf("CreateRemoteThreadEx failed: %d\n", GetLastError()); VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hProcess); return 1; } // 插入APC函数 if (!QueueUserAPC((PAPCFUNC)pLoadLibrary, hThread, (ULONG_PTR)remoteMem)) { printf("QueueUserAPC failed: %d\n", GetLastError()); VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return 1; } // 等待远程线程执行结束 WaitForSingleObject(hThread, INFINITE); // 清理资源 VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return 0; } ``` 需要注意的是,APC注入存在一些局限性,例如无法向所有进程注入代码,只能向某些特定类型的进程注入。此外,由于APC函数的执行是异步的,因此无法保证注入DLL的时机和顺序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值