zoukankan      html  css  js  c++  java
  • 动态库注入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;
      }
  • 相关阅读:
    laravel使用redis报错
    PHP新特性W3Cschool
    【python】跳过验证直接登陆-cookie已经知道需要部分直接注入
    【python】显示等待
    【python】pymysql库的简单使用
    【python】UI自动化优化浏览器重复打开和跑脚本时电脑无法做其他工作的问题
    【python】seleniumwire和selenium的区别
    【python】UI自动化-新版
    【python】UI自动化获取输入框的值
    【python】UI自动化多窗口处理
  • 原文地址:https://www.cnblogs.com/banchen/p/6682804.html
Copyright © 2011-2022 走看看