APC,即Asynchronous procedure call,异步程序调用
APC注入的原理是:
在一个进程中,当一个执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断,当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数,利用QueueUserAPC()这个API,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,

注入流程:
1.根据进程名称得进程ID
2.枚举该进程中的线程
3.将自己的函数插入到每个线程的APC队列中

#include "stdafx.h"
#include <windows.h>
#include <Tlhelp32.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h> using namespace std; typedef struct _THREADLIST
{
DWORD dwThreadId;
_THREADLIST *pNext;
}THREADLIST; int q = ; DWORD GetProcessID(const char *szProcessName);
int EnumThreadID(DWORD dwPID, THREADLIST * pdwTidList);
THREADLIST* InsertThreadId(THREADLIST *pdwTidListHead, DWORD dwTid);
DWORD Inject(HANDLE hProcess, THREADLIST *pThreadIdList); int main()
{
THREADLIST *pThreadIdHead = NULL;
pThreadIdHead = (THREADLIST *)malloc(sizeof(THREADLIST));
if (pThreadIdHead == NULL)
{
printf("申请失败");
return ;
} //ZeroMemory是美国微软公司的软件开发包SDK中的一个宏。 其作用是用0来填充一块内存区域
ZeroMemory(pThreadIdHead, sizeof(THREADLIST)); DWORD dwProcessID = ; if ((dwProcessID = GetProcessID("explorer.exe")) == )
{
printf("进程ID获取失败!\n");
return ;
} EnumThreadID(dwProcessID, pThreadIdHead); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); if (hProcess == NULL)
{
printf("打开进程失败");
return ;
} Inject(hProcess, pThreadIdHead);
cout<<q;
getchar();
getchar();
return ;
} DWORD GetProcessID(const char *szProcessName)
{
//PROCESSENTRY32这个宏在<Tlhelp32.h>中
PROCESSENTRY32 pe32 = { };
pe32.dwSize = sizeof(PROCESSENTRY32);
//创建线程快照
HANDLE SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, ); if (SnapshotHandle == INVALID_HANDLE_VALUE)
{
return ;
} if (!Process32First(SnapshotHandle, &pe32))
{
return ;
} do
{
if (!_strnicmp(szProcessName, pe32.szExeFile, strlen(szProcessName)))
{
printf("%s的PID是:%d\n", pe32.szExeFile, pe32.th32ProcessID);
return pe32.th32ProcessID;
}
//Process32Next是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后, 我们可以利用Process32Next函数来获得下一个进程的句柄
} while (Process32Next(SnapshotHandle, &pe32)); return ;
} int EnumThreadID(DWORD dwPID, THREADLIST * pdwTidList)
{
int i = ; THREADENTRY32 te32 = { };
te32.dwSize = sizeof(THREADENTRY32); HANDLE SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID); if (SnapshotHandle != INVALID_HANDLE_VALUE)
{
if (Thread32First(SnapshotHandle, &te32))
{
do
{
if (te32.th32OwnerProcessID == dwPID)
{
if (pdwTidList->dwThreadId == )
{
pdwTidList->dwThreadId = te32.th32ThreadID;
}
else
{
if (NULL == InsertThreadId(pdwTidList, te32.th32ThreadID))
{
printf("插入失败!\n");
return ;
}
} }
} while (Thread32Next(SnapshotHandle, &te32));
}
} return ;
} THREADLIST* InsertThreadId(THREADLIST *pdwTidListHead, DWORD dwTid)
{
THREADLIST *pCurrent = NULL;
THREADLIST *pNewMember = NULL; if (pdwTidListHead == NULL)
{
return NULL;
}
pCurrent = pdwTidListHead; while (pCurrent != NULL)
{ if (pCurrent->pNext == NULL)
{
// 定位到链表最后一个元素
pNewMember = (THREADLIST *)malloc(sizeof(THREADLIST)); if (pNewMember != NULL)
{
pNewMember->dwThreadId = dwTid;
pNewMember->pNext = NULL;
pCurrent->pNext = pNewMember;
return pNewMember;
}
else
{
return NULL;
}
}
pCurrent = pCurrent->pNext;
} return NULL;
} DWORD Inject(HANDLE hProcess, THREADLIST *pThreadIdList)
{
THREADLIST *pCurrentThreadId = pThreadIdList; const char szInjectModName[] = "需要加载的自己的动态库路径";
DWORD dwLen = strlen(szInjectModName) + ; PVOID param = VirtualAllocEx(hProcess,
NULL, dwLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); UINT_PTR LoadLibraryAAddress = (UINT_PTR)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA"); if (param != NULL)
{
SIZE_T dwRet;
if (WriteProcessMemory(hProcess, param, (LPVOID)szInjectModName, dwLen, &dwRet))
{
while (pCurrentThreadId)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, pCurrentThreadId->dwThreadId); if (hThread != NULL)
{
//注入DLL到指定进程
QueueUserAPC((PAPCFUNC)LoadLibraryAAddress, hThread, (ULONG_PTR)param);
printf("OK\r\n"); q++; } printf("ThreadID:%d\n", pCurrentThreadId->dwThreadId);
pCurrentThreadId = pCurrentThreadId->pNext;
}
}
}
return ;
}

如果OpenProce或者OpenThread失败,可以尝试提权,或者给UAC,以管理员身份启动。

不过我个人觉得,这个方法不是每次都能成功,只有线程多的进程,才比较容易成功。win7 测试成功,Win10不是每次成功。

另外没有提供删除APC队列中函数的方法,所以不能反复注入。

Dll注入:Ring3 层 APC注入的更多相关文章

  1. Dll注入技术之APC注入

    APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:     1)当EXE里某个线程执行到SleepEx( ...

  2. 注入理解之APC注入

    近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ...

  3. Windows x86/ x64 Ring3层注入Dll总结

    欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ...

  4. 分析恶意驱动(进程启动apc注入dll)

    一.前言  用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向. 今天记录一下sudami曾经逆向过的fuck.sys.第一遍自己走的时候漏掉了 ...

  5. DLL注入-APC注入

    APC注入 APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:     1)当EXE里某个线程执行到Sl ...

  6. APC注入

    0X01 注入原理 当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的 具体的流程: 1 当EXE里的某个线程执行到sleepEX(),或者waitF ...

  7. 常见注入手法第二讲,APC注入

    常见注入手法第二讲,APC注入 转载注明出处 首先,我们要了解下什么是APC APC 是一个简称,具体名字叫做异步过程调用,我们看下MSDN中的解释,异步过程调用,属于是同步对象中的函数,所以去同步对 ...

  8. DEDECMS数据库执行原理、CMS代码层SQL注入防御思路

    我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...

  9. Dll注入:注册表注入

    在系统中每一个进程加载User32.dll时,会受到DLL_PROCESS_ATTACH通知,当User32.dll对其进行处理时,会取得注册表键值HKEY_LOCAL_MACHINE\Softwar ...

随机推荐

  1. HN669打包工具--游戏对接

    一. 将游戏工程拖入到工具的HN669Ploy目录下,如下图: 二. xCode打开游戏工程,将Core目录下的HN669SDKCore工程添加入游戏工程,并引用库,如图:   三.调用API 1.A ...

  2. cf873F(xjb+二分)

    题目链接:http://codeforces.com/problemset/problem/837/F 题意:给出一个大小为 n 的数组 a 和一个数 k,每次操作后的到一个 a' 数组,a'i 为 ...

  3. 洛谷P4707 重返现世(扩展MinMax容斥+dp)

    传送门 我永远讨厌\(dp.jpg\) 前置姿势 扩展\(Min-Max\)容斥 题解 看纳尔博客去→_→ 咱现在还没搞懂为啥初值要设为\(-1\)-- //minamoto #include< ...

  4. 《权限系列shiro+cas》---封装公共验证模块

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 我们现在可以将任意属性传递给每个顶点的顶点着色器使用.但是 ...

  5. php使用百度地图API

    首先注册百度开发者平台账号,创建应用获取AK 不同的应用功能不同,一定要注意,没有的功能调用会提示APP被禁用 根据开发文档使用 给出例子:百度地图WEB api http://lbsyun.baid ...

  6. JMeter - 如何测试REST API / 微服务

    概述: 有许多方法和工具可用于测试REST API.当我需要测试REST API时,在查看了各种工具和选项之后,由于以下原因,我选择了JMeter. JMeter是免费和开源的. JMeter可以从C ...

  7. CodeForces - 186A-Comparing Strings

    Some dwarves that are finishing the StUDY (State University for Dwarven Youngsters) Bachelor courses ...

  8. fastJson Gson对比及java序列化问题

    一个案例 POJO没有set方法, 造成反序列化时出现NPE问题.实际场景:POJO是第三方提供的,final public class XJSONTest { public static void ...

  9. CSU 1453: 平衡序列 学会线段树后必做

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1453. 题目:给定一个大小为100000的数组,里面的数字最大也是100000.现在叫你求出一段子 ...

  10. Java面向对象_对象一一对应关系和this关键字

    一.打个比方,一个人有一个身份证号,一个身份证号对应一个人.一个英雄对应一把武器,一把武器对应一个英雄.生活中很多对象都存在一一对应关系,那么一一对应关系在代码中是如何实现的呢?举个例子,英雄和武器一 ...