Commit 5d4be768 authored by Sophie Brun's avatar Sophie Brun

Imported Upstream version 2.0.7+git20160629

parent d3ed3654
......@@ -12,11 +12,11 @@ Evilgrade is a modular framework that allows the user to take advantage of poor
It comes with pre-made binaries (agents), a working default configuration for fast pentests, and has it's own WebServer and DNSServer modules.
Easy to set up new settings, and has an autoconfiguration when new binary agents are set.
* When should I use evilgrade?
##### * When should I use evilgrade?
This framework comes into play when the attacker is able to make hostname redirections (manipulation of victim's dns traffic), and such thing can be done on 2 scenarios:
Internal scenery:
##### Internal scenery:
- Internal DNS access
- ARP spoofing
- DNS Cache Poisoning
......@@ -24,19 +24,19 @@ Internal scenery:
- TCP hijacking
- Wi-Fi Access Point impersonation
External scenery:
##### External scenery:
- Internal DNS access
- DNS Cache Poisoning
* How does it work?
##### * How does it work?
Evilgrade works with modules, in each module there's an implemented structure which is needed to emulate a fake update for an specific application/system.
* What OS are supported?
##### * What OS are supported?
ISR-Evilgrade is crossplatform, it only depends of having an appropriate payload for the right target platform to be exploited.
Implemented modules:
#### Implemented modules:
-------------------
- Freerip 3.30
- Jet photo 4.7.2
......@@ -422,7 +422,7 @@ help - prints this screen, or help on 'command'
```
.:: [ADVANCED] ::.
## .:: [ADVANCED] ::.
- Modules Options:
Each module has special options, but the "agent" field is always present.
......@@ -473,7 +473,7 @@ After our payload was generated, we leave a multi handler listening on the previ
[*] Starting the payload handler...
```
.:: [MODULE DEVELOPMENT] ::.
## .:: [MODULE DEVELOPMENT] ::.
Module development is very simple. Since evilgrade is based on modules, you just have to use a package .pm (perl module).
In this case we are going to describe the sunjava update module (comments with #):
......@@ -590,17 +590,42 @@ my $base=
};
```
.:: [TIPS] ::.
## .:: [TIPS] ::.
1) Don't forget to run evilgrade with an user that has privileges to create listening sockets,
otherwise you won't be able to use evilgrade's Services.
2) Everytime you modify a module with evilgrade running don't forget to 'reload' them.
3) Set the binary 'agents' before starting services because there are some fields that evilgrade
will fill out for you (agentmd5, agentsha256, and agentsize) that can't be done with them already running.
.:: [REQUIREMENTS] ::.
4) If you're using a dynamic response with variables such as: <%AGENTSIZE%>, <%AGENTMD5%>, <%URL\_FILE%>, <%URL\_FILE\_EXT%>, or custom ones defined at the options section, don't forget to set *parse* on 1.
5) Same goes for injecting an agent, you must enable de *bin* flag on 1.
6) If you want to make plaintext responses using HTTP use the *cheader* flag. Example below:
```
{ 'req' => '/sitepath/download/file.zip'
, #regex friendly
'type' => 'string', #file|string|agent|install
'method' => '', #any
'bin' => '',
'string' => '',
'parse' => '1',
'file' => '',
'cheader' => "HTTP/1.1 302 Found\r\n"
. "Location: http://sitedomain.com/<%URL_FILE%>.exe \r\n"
. "Content-Length: 0 \r\n"
. "Connection: close \r\n\r\n",
},
7) To filter via User-Agent, use as an example the Sparkle2 module. In base add 'useragent' => 'true', and on a request use as you would use the 'req' field but for user agents in 'useragent'. Note that this field already stripped "User-Agent: ".
```
## .:: [REQUIREMENTS] ::.
# Perl Modules
### Perl Modules
```
Data::Dump
Digest::MD5
......@@ -608,7 +633,7 @@ will fill out for you (agentmd5, agentsha256, and agentsize) that can't be done
RPC::XML
```
.:: [MORE INFORMATION] ::.
## .:: [MORE INFORMATION] ::.
This framework was presented in the following security conferences:
......@@ -621,7 +646,7 @@ This framework was presented in the following security conferences:
```
.:: [AUTHOR] ::.
## .:: [AUTHOR] ::.
Francisco Amato
famato+at+infobytesec+dot+com
Version 2.0.8 - 08-06-2016
--------------------------
- ASUS OEM LiveUpdate module added
- Fixed ReadLine::Gnu bug
- Improved README.md
- Added a 2 new configuration variables <%URL_FILE%> and <%URL_FILE_EXT%>
- ACER Care Center Live Update module added
- OpenBazaar module added
- Sparkle module generic exploitation added
- Extended filtering of requests via useragent too.
Version 2.0.7 - 03-06-2016
--------------------------
- (Samsung SW Update Tool 2.2.5.16) samsung module added
......@@ -50,7 +61,7 @@ Last Versions:
- Jet photo 4.7.2
*- Teamviewer 5.1.9385
- ISOpen 4.5.0
- Istat
- Istat
- Gom 2.1.25.5015
- Atube catcher 1.0.300
- Vidbox 7.5
......@@ -86,7 +97,7 @@ Last Versions:
- Flashget
- Miranda
- Orbit
- Photoscape
- Photoscape
- Panda Antirootkit
- Skype
- Sunbelt
......@@ -102,7 +113,7 @@ Last Versions:
- Paint.Net 3.5.4
- wmedia version 9
- Cygwin 1.5.25-11
- DIVX Suite 6.2 ( Player, WebPlayer, Codec Converter, DrDivX )
- DIVX Suite 6.2 ( Player, WebPlayer, Codec Converter, DrDivX )
- Opera 9.51
......
......@@ -33,10 +33,10 @@ use Socket;
use IO::Handle;
use IO::Select;
$SIG{CHLD} = 'IGNORE';
#kill zombies
#$SIG{INT} = sub { die "[shellz] - $$ dying\n"; };
our $VERSION = '0.02';
#=============================================================================
......@@ -44,49 +44,54 @@ our $VERSION = '0.02';
#=============================================================================
sub new {
my $cls = shift;
my $o = bless {
term => eval {
# Term::ReadKey throws ugliness all over the place if we're not
# running in a terminal, which we aren't during "make test", at
# least on FreeBSD. Suppress warnings here.
local $SIG{__WARN__} = sub { };
# This env setting fixes FD locks in win32 shell.
$ENV{TERM} = 'not dumb' if $^O eq 'MSWin32';
Term::ReadLine->new('shell');
} || undef,
on_signal => 0,
}, ref($cls) || $cls;
term => eval {
# Term::ReadKey throws ugliness all over the place if we're not
# running in a terminal, which we aren't during "make test", at
# least on FreeBSD. Suppress warnings here.
local $SIG{__WARN__} = sub { };
# This env setting fixes FD locks in win32 shell.
$ENV{TERM} = 'not dumb' if $^O eq 'MSWin32';
Term::ReadLine->new('shell');
}
|| undef,
on_signal => 0,
},
ref($cls)
|| $cls;
# Set up the API hash:
$o->{command} = {};
$o->{API} = {
args => \@_,
case_ignore => ($^O eq 'MSWin32' ? 1 : 0),
check_idle => 0, # changing this isn't supported
class => $cls,
command => $o->{command},
cmd => $o->{command}, # shorthand
match_uniq => 1,
pager => $ENV{PAGER} || 'internal',
readline => eval { $o->{term}->ReadLine } || 'none',
script => (caller(0))[1],
version => $VERSION,
$o->{API} = {
args => \@_,
case_ignore => ( $^O eq 'MSWin32' ? 1 : 0 ),
check_idle => 0, # changing this isn't supported
class => $cls,
command => $o->{command},
cmd => $o->{command}, # shorthand
match_uniq => 1,
pager => $ENV{PAGER} || 'internal',
readline => eval { $o->{term}->ReadLine } || 'none',
script => ( caller(0) )[1],
version => $VERSION,
};
# Note: the rl_completion_function doesn't pass an object as the first
# argument, so we have to use a closure. This has the unfortunate effect
# of preventing two instances of Term::ReadLine from coexisting.
my $completion_handler = sub {
$o->rl_complete(@_);
$o->rl_complete(@_);
};
if ($o->{API}{readline} eq 'Term::ReadLine::Gnu') {
my $attribs = $o->{term}->Attribs;
$attribs->{completion_function} = $completion_handler;
if ( $o->{API}{readline} eq 'Term::ReadLine::Gnu' ) {
my $attribs = $o->{term}->Attribs;
$attribs->{completion_function} = $completion_handler;
}
elsif ($o->{API}{readline} eq 'Term::ReadLine::Perl') {
$readline::rl_completion_function =
$readline::rl_completion_function = $completion_handler;
elsif ( $o->{API}{readline} eq 'Term::ReadLine::Perl' ) {
$readline::rl_completion_function = $readline::rl_completion_function
= $completion_handler;
}
$o->find_handlers;
$o->init;
......@@ -97,141 +102,162 @@ sub DESTROY {
my $o = shift;
$o->fini;
}
sub cmd {
my $o = shift;
$o->{line} = shift;
if ($o->line =~ /\S/) {
my ($cmd, @args) = $o->line_parsed;
$o->run($cmd, @args);
unless ($o->{command}{run}{found}) {
my @c = sort $o->possible_actions($cmd, 'run');
if (@c and $o->{API}{match_uniq}) {
print $o->msg_ambiguous_cmd($cmd, @c);
}
else {
print $o->msg_unknown_cmd($cmd);
}
}
if ( $o->line =~ /\S/ ) {
my ( $cmd, @args ) = $o->line_parsed;
$o->run( $cmd, @args );
unless ( $o->{command}{run}{found} ) {
my @c = sort $o->possible_actions( $cmd, 'run' );
if ( @c and $o->{API}{match_uniq} ) {
print $o->msg_ambiguous_cmd( $cmd, @c );
}
else {
print $o->msg_unknown_cmd($cmd);
}
}
}
else {
$o->run('');
$o->run('');
}
}
sub stoploop { $_[0]->{stop}++ }
sub cmdloop {
my $o = shift;
$o->{stop} = 0;
$o->preloop;
# while (defined (my $line = $o->readline($o->prompt_str))) {
# $o->cmd($line);
# last if $o->{stop};
# }
# while (defined (my $line = $o->readline($o->prompt_str))) {
# $o->cmd($line);
# last if $o->{stop};
# }
#communication between STDIN thread and prompt thread
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "[ERROR] - STDIN socketpair: $!";
socketpair( CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC )
or die "[ERROR] - STDIN socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);
#communication MSG entities
socketpair(CHILDM, PARENTM, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "[ERROR] - MSG socketpair: $!";
socketpair( CHILDM, PARENTM, AF_UNIX, SOCK_STREAM, PF_UNSPEC )
or die "[ERROR] - MSG socketpair: $!";
CHILDM->autoflush(1);
PARENTM->autoflush(1);
#save MSG
$o->{child} = \*CHILDM;
$o->{parent} = \*PARENTM;
$|=1;
die "[ERROR] Can't fork STDIN thread: $!" unless defined (my $pid = fork());
#save MSG
$o->{child} = \*CHILDM;
$o->{parent} = \*PARENTM;
$| = 1;
die "[ERROR] Can't fork STDIN thread: $!"
unless defined( my $pid = fork() );
$o->{pid} = $pid;
if ($pid == 0){ #STDIN thread (child)
close CHILD;
while(1){ #STDIN loop
my $line;
if ($^O eq 'MSWin32'){
$line = $o->readline($o->prompt_str);
}else{
$line = $o->readline();
}
print PARENT $line."\n";
exit 0 if $line eq "exit";
}
}else { #PROMPT thread (father)
close PARENT;
#Select's handlers
my $hl = new IO::Select(\*CHILD);
my $hl2 = new IO::Select(\*CHILDM);
#Print Prompt
print "\c[[4m".$o->prompt_str."\c[[0m" unless ($^O eq 'MSWin32');
while(1) { #Msg loop
usleep(10000);
#sleep(1); #fix loop cpu usage
my @ready = $hl->can_read(0);
foreach my $fh (@ready){
my $line = <$fh>;
$o->cmd($line);
print "\c[[4m".$o->prompt_str."\c[[0m" if (!$o->{stop} && !($^O eq 'MSWin32'));
}
my @ready2 = $hl2->can_read(0);
#TODO: Detect multiple entries
foreach my $fh (@ready2){
my $line = <$fh>;
if ($line =~ /^\<acc\>/){
$o->console_cmd($line);
}else{
print "\n$line";
print "\n"."\c[[4m".$o->prompt_str."\c[[0m";
}
}
if ($o->{stop}){
#TODO: recovery STDIN
kill HUP => $pid;
close(STDIN);
last;
}
}
if ( $pid == 0 ) { #STDIN thread (child)
close CHILD;
while (1) { #STDIN loop
my $line;
if ( $^O eq 'MSWin32' ) {
$line = $o->readline( $o->prompt_str );
}
else {
$line = $o->readline();
}
$line = "empty" unless $line;
if ( $line eq "empty" ) {
print PARENT "\n";
}
else {
print PARENT $line . "\n";
}
exit 0 if $line eq "exit";
}
}
else { #PROMPT thread (father)
close PARENT;
#Select's handlers
my $hl = new IO::Select( \*CHILD );
my $hl2 = new IO::Select( \*CHILDM );
#Print Prompt
print "\c[[4m" . $o->prompt_str . "\c[[0m"
unless ( $^O eq 'MSWin32' );
while (1) { #Msg loop
usleep(10000);
#sleep(1); #fix loop cpu usage
my @ready = $hl->can_read(0);
foreach my $fh (@ready) {
my $line = <$fh>;
$o->cmd($line);
print "\c[[4m" . $o->prompt_str . "\c[[0m"
if ( !$o->{stop} && !( $^O eq 'MSWin32' ) );
}
my @ready2 = $hl2->can_read(0);
#TODO: Detect multiple entries
foreach my $fh (@ready2) {
my $line = <$fh>;
if ( $line =~ /^\<acc\>/ ) {
$o->console_cmd($line);
}
else {
print "\n$line";
print "\n" . "\c[[4m" . $o->prompt_str . "\c[[0m";
}
}
if ( $o->{stop} ) {
#TODO: recovery STDIN
kill HUP => $pid;
close(STDIN);
last;
}
}
}
$o->postloop;
}
*mainloop = \&cmdloop;
sub readline {
my $o = shift;
my $o = shift;
my $prompt = shift;
if( $o->{on_signal} == 1 ){
if ( $o->{on_signal} == 1 ) {
return "exit\n";
}
}
return $o->{term}->readline($prompt)
if $o->{API}{check_idle} == 0
or not defined $o->{term}->IN;
if $o->{API}{check_idle} == 0
or not defined $o->{term}->IN;
# They've asked for idle-time running of some user command.
local $Term::ReadLine::toloop = 1;
local *Tk::fileevent = sub {
my $cls = shift;
my ($file, $boring, $callback) = @_;
$o->{fh} = $file; # save the filehandle!
$o->{cb} = $callback; # save the callback!
local *Tk::fileevent = sub {
my $cls = shift;
my ( $file, $boring, $callback ) = @_;
$o->{fh} = $file; # save the filehandle!
$o->{cb} = $callback; # save the callback!
};
local *Tk::DoOneEvent = sub {
# We'll totally cheat and do a select() here -- the timeout will be
# $o->{API}{check_idle}; if the handle is ready, we'll call &$cb;
# otherwise we'll call $o->idle(), which can do some processing.
my $timeout = $o->{API}{check_idle};
use IO::Select;
if (IO::Select->new($o->{fh})->can_read($timeout)) {
# Input is ready: stop the event loop.
$o->{cb}->();
}
else {
$o->idle;
}
# We'll totally cheat and do a select() here -- the timeout will be
# $o->{API}{check_idle}; if the handle is ready, we'll call &$cb;
# otherwise we'll call $o->idle(), which can do some processing.
my $timeout = $o->{API}{check_idle};
use IO::Select;
if ( IO::Select->new( $o->{fh} )->can_read($timeout) ) {
# Input is ready: stop the event loop.
$o->{cb}->();
}
else {
$o->idle;
}
};
$o->{term}->readline($prompt);
}
......@@ -239,98 +265,100 @@ sub readline {
sub term { $_[0]->{term} }
# These are likely candidates for overriding in subclasses
sub init { } # called last in the ctor
sub fini { } # called first in the dtor
sub preloop { }
sub postloop { }
sub precmd { }
sub postcmd { }
sub console_cmd {} #internal command between THREADs and parents
sub prompt_str { 'shell> ' }
sub idle { }
sub cmd_prefix { '' }
sub cmd_suffix { '' }
sub init { } # called last in the ctor
sub fini { } # called first in the dtor
sub preloop { }
sub postloop { }
sub precmd { }
sub postcmd { }
sub console_cmd { } #internal command between THREADs and parents
sub prompt_str {'shell> '}
sub idle { }
sub cmd_prefix {''}
sub cmd_suffix {''}
#=============================================================================
# The pager
#=============================================================================
sub page {
my $o = shift;
my $text = shift;
my $maxlines = shift || $o->termsize->{rows};
my $pager = $o->{API}{pager};
my $o = shift;
my $text = shift;
my $maxlines = shift || $o->termsize->{rows};
my $pager = $o->{API}{pager};
# First, count the number of lines in the text:
my $lines = ($text =~ tr/\n//);
my $lines = ( $text =~ tr/\n// );
# If there are fewer lines than the page-lines, just print it.
if ($lines < $maxlines or $maxlines == 0 or $pager eq 'none') {
print $text;
if ( $lines < $maxlines or $maxlines == 0 or $pager eq 'none' ) {
print $text;
}
# If there are more, page it, either using the external pager...
elsif ($pager and $pager ne 'internal') {
require File::Temp;
my ($handle, $name) = File::Temp::tempfile();
select((select($handle), $| = 1)[0]);
print $handle $text;
close $handle;
system($pager, $name) == 0
or print <<END;
elsif ( $pager and $pager ne 'internal' ) {
require File::Temp;
my ( $handle, $name ) = File::Temp::tempfile();
select( ( select($handle), $| = 1 )[0] );
print $handle $text;
close $handle;
system( $pager, $name ) == 0
or print <<END;
Warning: can not run external pager '$pager': $!.
END
unlink $name;
unlink $name;
}
# ... or the internal one
else {
my $togo = $lines;
my $line = 0;
my @lines = split '^', $text;
while ($togo > 0) {
my @text = @lines[$line .. $#lines];
my $ret = $o->page_internal(\@text, $maxlines, $togo, $line);
last if $ret == -1;
$line += $ret;
$togo -= $ret;
}
return $line;
my $togo = $lines;
my $line = 0;
my @lines = split '^', $text;
while ( $togo > 0 ) {
my @text = @lines[ $line .. $#lines ];
my $ret = $o->page_internal( \@text, $maxlines, $togo, $line );
last if $ret == -1;
$line += $ret;
$togo -= $ret;
}
return $line;
}
return $lines
return $lines;
}
sub page_internal {
my $o = shift;
my $lines = shift;
my $maxlines = shift;
my $togo = shift;
my $start = shift;
my $o = shift;
my $lines = shift;
my $maxlines = shift;
my $togo = shift;
my $start = shift;
my $line = 1;
while ($_ = shift @$lines) {
print;
last if $line >= ($maxlines - 1); # leave room for the prompt
$line++;
while ( $_ = shift @$lines ) {
print;
last if $line >= ( $maxlines - 1 ); # leave room for the prompt
$line++;
}
my $lines_left = $togo - $line;
my $lines_left = $togo - $line;
my $current_line = $start + $line;
my $total_lines = $togo + $start;
my $total_lines = $togo + $start;
my $instructions;
if ($o->have_readkey) {
$instructions = "any key for more, or q to quit";
if ( $o->have_readkey ) {
$instructions = "any key for more, or q to quit";
}
else {
$instructions = "enter for more, or q to quit";
$instructions = "enter for more, or q to quit";
}
if ($lines_left > 0) {
local $| = 1;
my $l = "---line $current_line/$total_lines ($instructions)---";
my $b = ' ' x length($l);
print $l;
my $ans = $o->readkey;
print "\r$b\r" if $o->have_readkey;
print "\n" if $ans =~ /q/i or not $o->have_readkey;
$line = -1 if $ans =~ /q/i;
if ( $lines_left > 0 ) {
local $| = 1;
my $l = "---line $current_line/$total_lines ($instructions)---";
my $b = ' ' x length($l);
print $l;
my $ans = $o->readkey;
print "\r$b\r" if $o->have_readkey;
print "\n" if $ans =~ /q/i or not $o->have_readkey;
$line = -1 if $ans =~ /q/i;
}
$line;
}
......@@ -339,32 +367,32 @@ sub page_internal {
# Run actions
#=============================================================================
sub run {
my $o = shift;