Dll注入:Ring3 层 APC注入
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注入的更多相关文章
- Dll注入技术之APC注入
APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下: 1)当EXE里某个线程执行到SleepEx( ...
- 注入理解之APC注入
近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ...
- Windows x86/ x64 Ring3层注入Dll总结
欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ...
- 分析恶意驱动(进程启动apc注入dll)
一.前言 用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向. 今天记录一下sudami曾经逆向过的fuck.sys.第一遍自己走的时候漏掉了 ...
- DLL注入-APC注入
APC注入 APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下: 1)当EXE里某个线程执行到Sl ...
- APC注入
0X01 注入原理 当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的 具体的流程: 1 当EXE里的某个线程执行到sleepEX(),或者waitF ...
- 常见注入手法第二讲,APC注入
常见注入手法第二讲,APC注入 转载注明出处 首先,我们要了解下什么是APC APC 是一个简称,具体名字叫做异步过程调用,我们看下MSDN中的解释,异步过程调用,属于是同步对象中的函数,所以去同步对 ...
- DEDECMS数据库执行原理、CMS代码层SQL注入防御思路
我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...
- Dll注入:注册表注入
在系统中每一个进程加载User32.dll时,会受到DLL_PROCESS_ATTACH通知,当User32.dll对其进行处理时,会取得注册表键值HKEY_LOCAL_MACHINE\Softwar ...
随机推荐
- Deep Image Matting
论文地址:https://arxiv.org/abs/1703.03872 TF复现地址:https://github.com/Joker316701882/Deep-Image-Matting 领域 ...
- Unity3D -- shader语法内置函数
该篇是Unity Shader中HLSL的内置函数,主要是一些数学方面的计算函数.在写Shader的时候可以直接使用. abs //计算输入值的绝对值. acos //返回输入值反余弦值. all / ...
- css 实现三级联动菜单
昨天因为项目中想要把二级联动菜单改成三级联动菜单,所以我就单独写了一个tab导航栏,用纯css的方式实现的三级联动.一开始我想着可以用js实现,但是js的hover事件和mouseenter,mous ...
- 关于CSRF攻击详解
CSRF的原理以及防范 CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解: 攻击者盗用了你的身份,以你 ...
- uuid安装 插件安装
yum -y install uuid uuid-devel 安装uuid包tar -zxvf uuid-1.6.1.tar.gzcd uuid-1.6.1./configuremakemake in ...
- 备份与恢复:MySQL系列之十二
一.备份策略赘述 1.备份的类型 类型1: 热备份:读写不受影响(MyISAM不支持热备,InnoDB支持热备) 温备份:仅可以执行读操作 冷备份:离线备份,读写操作均中止 类型2: 物理备份:复制数 ...
- php魔术常量、超全局变量、魔术方法
一.魔术常量(魔术变量) 概念:所谓的魔术常量就是PHP预定义的一些常量,这些常量会随着所在的位置而变化. 1.__LINE__ 获取文件中的当前行号. 2.__FILE__ 获取文件的完整路径和 ...
- "微信戴圣诞帽"的一个简易实现程序
准备安装 由于是利用别人写的人脸识别的一个库,所以需要在import之前安装好相应的环境.如果直接安装face_recognition库的时候就会直接提示缺少的相应的dlib库.而dlib库本身需要c ...
- linux下rename命令使用(可以实现文件批量重名)
rename命令使用 把所有文件中的@符号去掉 wang@2a.pngzhang@2a.pngzhou@2a.pnghaha@2a.pngmama@2a.png CentOS:rename \@2a. ...
- spring boot test MockBean
使用spring boot , MockBean @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) p ...