动态库注入--APC注入

  • APC(异步过程调用)  

       1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时(此时该线程处于可警惕状态),系统就会产生一个软中断。
       2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。
       3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我b们插入的是Loadlirary()执行函数的话,就能达到注入DLL的目的。

  • APC注入DLL流程

     a根据进程ID得到进程句柄

     b枚举进程的线程

     c在目标进程中申请内存(用来储存动态库的绝对地址)

     d调用WriteProcessMemory在申请的内存处写入动态库地址

     e调用QueueUserAPC为每个线程提交APC到APC队列

  • 代码实现
    // InjectByAPC.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #define _WIN32_WINNT 0x0400
    #define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料
    #include<Windows.h>
    #include <iostream>
    #include <Tlhelp32.h>
    using namespace std;
    
    typedef struct _THREADID_LIST_
    {
        DWORD ThreadID;
        _THREADID_LIST_ *pNext;
    }THREADIDLIST,*PTHREADIDLIST;
    DWORD GetProcessID(const TCHAR* szProcessName);
    PTHREADIDLIST InsertTid(PTHREADIDLIST ThreadIDList, DWORD ThreadId);
    int EnumThreadID(DWORD ProcessID, PTHREADIDLIST ThreadIDList);
    DWORD EnumThread(HANDLE ProcessHandle, PTHREADIDLIST ThreadIDList);
    
    
    int main()
    {
        
        PTHREADIDLIST ThreadIDList = (PTHREADIDLIST)malloc(sizeof(THREADIDLIST));
    
        if (ThreadIDList == NULL)
        {
            return 0;
        }
        RtlZeroMemory(ThreadIDList, sizeof(THREADIDLIST));
    
        DWORD ProcessID = 0;
        if ((ProcessID = GetProcessID("explorer.exe")) == 0xFFFFFFFF)
        {
            printf("进程ID获取失败!\n");
            return 0;
        }
        
        EnumThreadID(ProcessID, ThreadIDList);
    
        HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
    
        if (ProcessHandle == NULL)
        {
            return 0;
        }
        EnumThread(ProcessHandle, ThreadIDList);
        getchar();
        getchar();
        return 0;
    }
    
    DWORD GetProcessID(const TCHAR* szProcessName)
    {
        PROCESSENTRY32 pe32 = { 0 };
        pe32.dwSize = sizeof(PROCESSENTRY32);
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    
        if (hSnapshot == INVALID_HANDLE_VALUE)
        {
            return -1;
        }
    
        if (!Process32First(hSnapshot, &pe32))
        {
            return -1;
        }
    
        do
        {
            if (!_strnicmp(szProcessName, pe32.szExeFile, strlen(szProcessName)))
            {
                printf("%s的PID是:%d\n", pe32.szExeFile, pe32.th32ProcessID);
                return pe32.th32ProcessID;
            }
        } while (Process32Next(hSnapshot, &pe32));
    
        return -1;
    }
    // 枚举线程ID
    int EnumThreadID(DWORD ProcessID, PTHREADIDLIST ThreadIDList)
    {
        int i = 0;
    
        THREADENTRY32 te32 = { 0 };
        te32.dwSize = sizeof(THREADENTRY32);
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, ProcessID);
    
        if (hSnapshot != INVALID_HANDLE_VALUE)
        {
            if (Thread32First(hSnapshot, &te32))
            {
                do
                {
                    if (te32.th32OwnerProcessID == ProcessID)
                    {
                        if (ThreadIDList->ThreadID == 0)
                        {
                            ThreadIDList->ThreadID = te32.th32ThreadID;
                        }
                        else
                        {
                            if (NULL == InsertTid(ThreadIDList, te32.th32ThreadID))
                            {
                                printf("插入失败!\n");
                                return 0;
                            }
                        }
    
                    }
                } while (Thread32Next(hSnapshot, &te32));
            }
        }
        return 1;
    }
    PTHREADIDLIST InsertTid(PTHREADIDLIST ThreadIDList, DWORD ThreadId)
    {
        PTHREADIDLIST pCurrent = NULL;
        PTHREADIDLIST pNewMember = NULL;
    
        if (ThreadIDList == NULL)
        {
            return NULL;
        }
        pCurrent = ThreadIDList;
    
        while (pCurrent != NULL)
        {
    
            if (pCurrent->pNext == NULL)
            {
                //
                // 定位到链表最后一个元素
                //
                pNewMember = (PTHREADIDLIST )malloc(sizeof(THREADIDLIST));
    
                if (pNewMember != NULL)
                {
                    pNewMember->ThreadID = ThreadId;
                    pNewMember->pNext = NULL;
                    pCurrent->pNext = pNewMember;
                    return pNewMember;
                }
                else
                {
                    return NULL;
                }
            }
            pCurrent = pCurrent->pNext;
        }
    
        return NULL;
    }
    
    DWORD EnumThread(HANDLE ProcessHandle, PTHREADIDLIST ThreadIDList)
    {
        //默认第一个?
        PTHREADIDLIST CurrentThreadID = ThreadIDList;
    
        const char szInjectModName[] = "J:\\注入\\InjectByAPC\\x64\\Debug\\DLL.dll";
        DWORD Length = strlen(szInjectModName);
    
        PVOID Address = VirtualAllocEx(ProcessHandle,
            NULL, Length, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
    
        if (Address != NULL)
        {
            SIZE_T ReturnLength;
            //
            //将动态库的地址写进去
            //
            if (WriteProcessMemory(ProcessHandle, Address, (LPVOID)szInjectModName, Length, &ReturnLength))
            {
                while (CurrentThreadID)
                {
                    HANDLE ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, CurrentThreadID->ThreadID);
    
                    if (ThreadHandle != NULL)
                    {
                        //
                        // 注入DLL到指定进程
                        //Address LoadLibraryA 参数
                        //
                        QueueUserAPC((PAPCFUNC)LoadLibraryA, ThreadHandle, (ULONG_PTR)Address);
                    }
    
                    printf("TID:%d\n", CurrentThreadID->ThreadID);
                    CurrentThreadID = CurrentThreadID->pNext;
                }
            }
        }
        return 0;
    }

     

posted @ 2017-04-08 19:50  _小北  阅读(595)  评论(1编辑  收藏  举报