系统产生一个软中断,当线程再次被唤醒时,此线程会首先执行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. YIT-CTF—Web

    一:背后 打开传送门——>查看网页源代码——>1b0679be72ad976ad5d491ad57a5eec0——>用MD5解密 二:一种编码 [][(![]+[])[+[]]+([ ...

  2. Centos6.8 搭建Tomcat服务器

    Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,是一个可以提供web服务同时也支持Servlet的JSP服务器. ...

  3. HTML表格元素

      学习要点:     1.表格元素总汇     2.构建表格解析 一.表格元素总汇     表格的基本构成最少需要三个元素:<table>.<tr>.<td>,其 ...

  4. MySQL在登陆时出现ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)错误

    错误显示:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 解决方案: 1.找到配 ...

  5. Roll a ball 学习

    using UnityEngine; using System.Collections; /// <summary> /// 相机控制 /// </summary> publi ...

  6. Revit 开发将自己的窗口设置为Revit窗口

    在Revit开发中如果使用modeless的对话框,经常容易被Revit窗体覆盖,但是如果将窗体设为Topmost的话,当Revit失去焦点后,它又会遮住其他程序的界面,比如将Revit最小化后,To ...

  7. dependencies、devDependencies、webpack打包 的区别与联系

    为什么要在dependencies.devDependencies中声明依赖? 答:保证任何人在(或者你自己在其他设备上)对这个项目进行修改(开发)时,通过npm install就能获取同样的开发环境 ...

  8. linux shell编程中的数组定义、遍历

    代码如下: 数组定义法1: arr=( ) # 注意是用空格分开,不是逗号!! 数组定义法2: array array[]="a" array[]="b" ar ...

  9. virtualbox下centos虚拟机安装增强工具教程和常见错误解决

    VirtualBox 4.3.6上安装CentOS 6.5 https://my.oschina.net/tashi/blog/190060 错误1.Building the main Guest A ...

  10. 最全Pycharm教程(1)——定制外观

    http://blog.csdn.net/u013088062/article/details/50100121