系统产生一个软中断,当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数,利用QueueUserAPC()这个API,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,

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


  1 // APCInject(Ring3).cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <windows.h>
#include <TlHelp32.h>
#include <ntstatus.h>
#include <vector>
#include <iostream> using namespace std;
/*
Win7下成功 Win10不一定成功(编译对应的位数,管理员身份运行)
Win7要将倒着插入!!
要将DLL拷到.cpp的文件夹中
尽量选择线程多的exe 另外没有提供删除APC队列中函数的方法,所以不能反复注入。
*/ WCHAR __DllFullPath[MAX_PATH] = { };
PVOID __DllFullPathBufferData = NULL;
UINT_PTR __LoadLibraryWAddress = ; //typedef void(*pfnSub_110)(); BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID);
BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector);
BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID);
BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable); int main()
{
if (DebugPrivilege(SE_DEBUG_NAME, TRUE)==FALSE)
{
printf("DebugPrivilege Error\r\n");
} GetCurrentDirectory(MAX_PATH, __DllFullPath); wcscat(__DllFullPath, L"\\Dll.dll"); UINT ProcessID = ; if (GetProcessIDByProcessImageName(
L"taskmgr.exe", &ProcessID) == FALSE)
{ return ;
} vector<UINT32> ThreadIDVector; if (GetThreadIDByProcessID(ProcessID, ThreadIDVector) == FALSE)
{
return ;
} size_t ThreadCount = ThreadIDVector.size();
//每一个线程
/*
win7下得倒着注入
*/
for (INT_PTR i = ThreadCount - ; i >= ; i--)
{
UINT32 ThreadID = ThreadIDVector[i];
InjectDllByApc(ProcessID, ThreadID);
} printf("Input Any Key to Exit\r\n");
getchar();
getchar(); return ;
} BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID)
{
HANDLE ThreadHandle = NULL;
HANDLE ProcessHandle = OpenProcess(
PROCESS_ALL_ACCESS, FALSE, ProcessID); SIZE_T DllFullPathLength = ((wcslen(__DllFullPath) + )); SIZE_T ReturnLength = ;
BOOL IsOk = FALSE; // 申请一次内存
if (__DllFullPathBufferData == NULL)
{
__DllFullPathBufferData =
VirtualAllocEx(
ProcessHandle,
NULL,
DllFullPathLength * ,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
); if (__DllFullPathBufferData == NULL)
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
} IsOk = WriteProcessMemory(
ProcessHandle,
__DllFullPathBufferData,
__DllFullPath,
DllFullPathLength * ,
&ReturnLength
); if (IsOk == FALSE)
{ VirtualFree(__DllFullPathBufferData,
DllFullPathLength * , MEM_RELEASE); CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
}
} __LoadLibraryWAddress =
(UINT_PTR)GetProcAddress(
GetModuleHandle(L"Kernel32.dll"),
"LoadLibraryW"
); if (__LoadLibraryWAddress == NULL)
{
VirtualFree(
__DllFullPathBufferData,
DllFullPathLength * , MEM_RELEASE);
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
return FALSE;
} __try
{
ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID);
DWORD v1 = QueueUserAPC(
(PAPCFUNC)__LoadLibraryWAddress,
ThreadHandle,
(UINT_PTR)__DllFullPathBufferData
); //LoadLibraryWAddress("DllFullPathBufferData")
if (v1 == )
{
printf("FAIL %d\r\n", GetLastError());
}
else if (v1 != )
{
printf("Success\r\n");
}
} __except (EXCEPTION_CONTINUE_EXECUTION)
{ } CloseHandle(ProcessHandle);
CloseHandle(ThreadHandle); return TRUE;
} BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector)
{
HANDLE ThreadSnapshotHandle = NULL;
THREADENTRY32 ThreadEntry32 = { }; ThreadEntry32.dwSize = sizeof(THREADENTRY32); ThreadSnapshotHandle = CreateToolhelp32Snapshot(
TH32CS_SNAPTHREAD, );
if (ThreadSnapshotHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
} BOOL IsOk = Thread32First(
ThreadSnapshotHandle, &ThreadEntry32); if (IsOk)
{
do
{
if (
ThreadEntry32.th32OwnerProcessID
== ProcessID)
{
ThreadIDVector.emplace_back(
ThreadEntry32.th32ThreadID); // 把该进程的所有线程id压入模板
}
} while (Thread32Next(
ThreadSnapshotHandle, &ThreadEntry32)
); } CloseHandle(ThreadSnapshotHandle);
ThreadSnapshotHandle = NULL; return TRUE;
} BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID)
{
HANDLE ProcessSnapshotHandle = NULL;
ProcessSnapshotHandle =
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, ); if (ProcessSnapshotHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
} PROCESSENTRY32 ProcessEntry32 = { };
ProcessEntry32.dwSize = sizeof(PROCESSENTRY32); BOOL IsOk = Process32First(
ProcessSnapshotHandle,
&ProcessEntry32
); if (IsOk)
{
do
{
if (
lstrcmpi(ProcessEntry32.szExeFile,
ProcessImageName)==
)
{
*ProcessID = ProcessEntry32.th32ProcessID;
break;
}
} while (Process32Next(
ProcessSnapshotHandle,
&ProcessEntry32
)
);
} if (*ProcessID==)
{
printf("Get ProcessID FAIL! 请打开任务管理器.\r\n");
return FALSE;
} CloseHandle(ProcessSnapshotHandle);
ProcessSnapshotHandle = NULL; return TRUE;
} BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable)
{
BOOL bRet = TRUE;
HANDLE TokenHandle;
TOKEN_PRIVILEGES TokenPrivileges; //进程 Token 令牌
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &TokenHandle))
{
bRet = FALSE;
return bRet;
}
TokenPrivileges.PrivilegeCount = ;
TokenPrivileges.Privileges[].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : ; LookupPrivilegeValue(NULL, DebugName, &TokenPrivileges.Privileges[].Luid);
AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
if (GetLastError() != ERROR_SUCCESS)
{
bRet = FALSE;
} CloseHandle(TokenHandle);
return bRet; }

注入 - Ring3 APC注入的更多相关文章

  1. Dll注入:Ring3 层 APC注入

    APC,即Asynchronous procedure call,异步程序调用APC注入的原理是:在一个进程中,当一个执行到SleepEx()或者WaitForSingleObjectEx()时,系统 ...

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

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

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

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

  4. APC注入

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

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

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

  6. 注入理解之APC注入

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

  7. Dll注入技术之APC注入

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

  8. windows:shellcode 代码远程APC注入和加载

    https://www.cnblogs.com/theseventhson/p/13197776.html  上一章介绍了通用的shellcode加载器,这个加载器自己调用virtualAlloc分配 ...

  9. DLL注入-APC注入

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

随机推荐

  1. PS学习之动态表情制作

    准备素材 1. 2. 3. 4. 最后效果图: 在PS中打开四个图片 另外新建一个文件 用魔棒工具抠图 点击白色位置 右键选择反向 右键人物 选择拷贝的图层 重复,将四个图片扣好 拖到新建的文件里 如 ...

  2. SpringCloud学习

    1.SpringCloud的参考博客1 首先主要遇到的问题就是1.写好项目然后放到tomcat或者其他的容器中,然后稍微一点修改就要整个项目重新发布,非常麻烦,这就是微服务出现的契机了 基础知识 PS ...

  3. Explicit

    Prefixing the explicit keyword to the constructor prevents the compiler from using that constructor ...

  4. cocos2d-x游戏开发 跑酷(三) 人物跑动

    原创.转载请注明出处:http://blog.csdn.net/dawn_moon/article/details/21245881 好吧.最终要跑起来了. 要实现跑酷须要用到帧动画,什么是帧动画,不 ...

  5. 一、搭建Django,建立第一个demo

    一. 1.安装好Python(我用的最新版2.7.15),配置环境变量,并且安装好对应的Django版本(pip install django),在Python安装目录下的Scropts下会多出dja ...

  6. (转)mysql创建表时反引号的作用

    试用navicat工具查看现网mysql建表语句时,发现表名和字段名都是反引号引起来的 CREATE TABLE `tab_notice_title_tv` ( `i_id` int(11) NOT ...

  7. webpack 提取 manifest 文件

    当 webpack 生成 bundle 时, 它同时维护一个 manifest 文件.你可以在生成的 vendor bundle 中找到它.manifest 文件描述了哪些文件需要 webpack 加 ...

  8. API - .addClass()

    比较简单的一个方法,  jQuery官网中.addClass()有两种参数: 1 .addClass( className )   /* className 为一个或多个(多个时用空格分隔) css ...

  9. Hadoop JAVA HDFS客户端操作

    JAVA HDFS客户端操作 通过API操作HDFS org.apache.logging.log4jlog4j-core2.8.2org.apache.hadoophadoop-common${ha ...

  10. 阿里巴巴Dubbo实现的源码分析

    1.      Dubbo概述 Dubbo是阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及作为SOA服务治理的方案.它的核心功能包括: #remoting ...