############### # shellz.pm # # Copyright 2010 Francisco Amato # # This file is part of isr-evilgrade, www.infobytesec.com . # # isr-evilgrade is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation version 2 of the License. # # isr-evilgrade is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with isr-evilgrade; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # ''' ## package isrcore::shellz; use strict; #internal modules use base qw(isrcore::Shell); use isrcore::webserver; use isrcore::main; use isrcore::ASCIITable; use isrcore::dnsserver; #external modules use Data::Dump qw(dump); require RPC::XML; require RPC::XML::Client; #ignore child's process to avoid zombie $SIG{CHLD} = 'IGNORE'; ########################################################################## # FUNCTION init # RECEIVES # RETURNS # EXPECTS # DOES class initialize my $ppid=0; sub init { my $self = shift; my $webserver = isrcore::webserver->new(); my $dnsserver = isrcore::dnsserver->new(); my $isrmain = isrcore::main->new(); if( $shellz::ppid == 0 ) { $shellz::ppid= $$; } #Loadmodules my $ret = $isrmain->loadmodules(); if ($ret != 1){ # loadmodules error $isrmain->println($ret); exit; } $self->{'dnsserver'}=$dnsserver; $self->{'webserver'}=$webserver; $self->{'isrmain'}=$isrmain; $self->{'VERSION'}="2.0.1"; $self->{'path'}=""; $self->{'prompt'}="evilgrade"; $self->{'change'}=0; } ########################################################################## # FUNCTION prompt_str # RECEIVES # RETURNS # EXPECTS # DOES return shell's prompt sub prompt_str { my $self =shift; my $prompt = $self->{'prompt'}; if ($self->{'path'}){ $prompt .= "($self->{'path'})"; } $prompt .= ">"; "$prompt" } #() ########################################################################## # SHELLS COMMANDS ########################################################################## ########################################################################## # FUNCTION run_show # RECEIVES cmd # RETURNS # EXPECTS # DOES show [object]'s information sub run_show { my $self = shift; my ($cmd) = @_; my $mods=0; if ($cmd eq "modules"){ $self->{'isrmain'}->ptitle("List of modules"); foreach my $module (sort(keys %{$self->{'isrmain'}->{'modules'}})){ $self->{'isrmain'}->println("$module\n"); $mods++; } $self->{'isrmain'}->println("- $mods modules available.\n\n");; $self->{'isrmain'}->println("\n"); }elsif ($cmd eq "status"){ $self->run_status($self); }elsif ($cmd eq "version"){ $self->run_version($self); }elsif ($cmd eq "vhosts"){ $self->run_vhosts($self); }elsif ($cmd eq "active"){ $self->{'isrmain'}->ptitle("List of actived modules"); foreach my $module (@{$self->{'webserver'}->{'current'}}){ $self->{'isrmain'}->println("$module\n"); $mods++; } $self->{'isrmain'}->println("- $mods modules loaded.\n\n");; $self->{'isrmain'}->println("\n"); }elsif ($cmd eq "options"){ $self->{'isrmain'}->ptitle("Display options"); my $object; if ($self->{'path'}){ $object = $self->{'isrmain'}->{'modules'}->{$self->{'path'}}->{'Base'}; $self->{'isrmain'}->println("Name = $object->{'name'}\n"); $self->{'isrmain'}->println("Version = $object->{'version'}\n"); $self->{'isrmain'}->println("Author = ".dump($object->{'author'})."\n"); $self->{'isrmain'}->println("Description = ".dump($object->{'description'})."\n"); $self->{'isrmain'}->println("VirtualHost = ".dump($object->{'vh'})."\n\n"); }else{ $object = $self->{'isrmain'}->{'Base'}; } my $t = new isrcore::ASCIITable; $t->setCols(['Name','Default','Description']); foreach my $module (keys %{$object->{'options'}}){ if (!$object->{'options'}->{$module}->{'hidden'}){ #Verify if it's a hidden option $t->addRow($module,$object->{'options'}->{$module}->{'val'},$object->{'options'}->{$module}->{'desc'}); } } $self->{'isrmain'}->println($t->draw()."\n"); } } ########################################################################## # FUNCTION run_set # RECEIVES cmd,value # RETURNS # EXPECTS # DOES configure option sub run_set { my $self = shift; my ($cmd,$value) = @_; $self->{'isrmain'}->println("set $cmd, $value\n"); my $object; if ($self->{'path'}){ $object = \$self->{'isrmain'}->{'modules'}->{$self->{'path'}}->{'Base'}->{'options'}; }else{ $object = \$self->{'isrmain'}->{'Base'}->{'options'}; } if (!$cmd){ $self->{'isrmain'}->println("(*) Please specify option name\n"); return }else{ if (!exists($$object->{$cmd})){ $self->{'isrmain'}->println("(*) Option name ($cmd) did not exists\n"); return }else { $self->{'change'}=1; $$object->{$cmd}->{'val'} =$value; #TODO: check exists val #TODO: Message required webserver restart } } } ########################################################################## # FUNCTION run_configure # RECEIVES cmd # RETURNS # EXPECTS # DOES configure modules sub run_configure { my $self = shift; my ($cmd) = @_; if ($cmd){ if (!exists($self->{'isrmain'}->{'modules'}->{$cmd})){ $self->{'isrmain'}->println("(*) Module name ($cmd) did not exists\n"); return } $self->{'path'}=$cmd }else { $self->{'path'}=""; } } ########################################################################## # FUNCTION run_vhosts # RECEIVES cmd # RETURNS # EXPECTS # DOES display vhosts available sub run_vhosts{ my $self = shift; my ($cmd) = @_; $self->{'isrmain'}->ptitle("Virtual hosts"); print $self->{'isrmain'}->println(dump($self->{'dnsserver'}->{'Base'}->{'domains'})); } ########################################################################## # FUNCTION run_version # RECEIVES cmd # RETURNS # EXPECTS # DOES display console version sub run_version{ my $self = shift; my ($cmd) = @_; $self->{'isrmain'}->println("version " . $self->{'VERSION'}."\n"); } ########################################################################## # FUNCTION run_reload # RECEIVES # RETURNS # EXPECTS # DOES reload modules sub run_reload { my $self = shift; $self->{'isrmain'}->println("reload\n"); $self->{'isrmain'}->loadmodules(); } ########################################################################## # FUNCTION run_start # RECEIVES # RETURNS # EXPECTS # DOES start servers sub run_start { my $self = shift; my ($cmd) = @_; start_server( $self, "webserver",$cmd); start_server( $self, "dnsserver",$cmd) unless ( $self->{'isrmain'}->{'Base'}->{'options'}->{'DNSEnable'}->{'val'} == 0 ); } sub start_server { my $self = shift; my $server_type = shift; my ($cmd) = @_; if ($self->{$server_type}->status() ){ $self->{'isrmain'}->println("$self->{$server_type}->{'Base'}->{'whoami'} : (pid $self->{$server_type}->{'Base'}->{'child'}) already running\n"); return; } my $response = $self->{$server_type}->loadconfig($self->{'isrmain'}); if ($response != 1){ #error loadconfig $self->{'isrmain'}->println($response); return; } if( $server_type == "webserver" ){ #solo para webserver esto $self->{'comm'}->{'parent'} = $self->{'parent'}; $self->{'comm'}->{'child'} = $self->{'child'}; } my $child; my $line; # crear el fork para salir die "Can't fork: $!" unless defined ($child = fork()); if ($child==0) { my $line; $self->{$server_type}->start($self); if ($self->{$server_type}->{'Base'}->{'error'}){ $self->{'isrmain'}->println("\n\nError: $self->{$server_type}->{'Base'}->{'error'}\n"); } exit 0; } $self->{$server_type}->{'Base'}->{'child'} = $child; } ########################################################################## # FUNCTION run_status # RECEIVES # RETURNS # EXPECTS # DOES display servers status sub get_status { my $self = shift; my $server_type = shift; if ($self->{$server_type}->status()){ $self->{'isrmain'}->println("$self->{$server_type}->{'Base'}->{'whoami'} : (pid $self->{$server_type}->{'Base'}->{'child'}) already running\n"); } else{ $self->{'isrmain'}->println("$self->{$server_type}->{'Base'}->{'whoami'} : stopped.\n"); } } sub run_status{ my $self = shift; get_status($self,"webserver"); get_status($self,"dnsserver") unless ( $self->{'isrmain'}->{'Base'}->{'options'}->{'DNSEnable'}->{'val'} == 0 ); my $j=0; $self->{'isrmain'}->ptitle("Users status"); my $t = new isrcore::ASCIITable; $t->setCols(['Client','Module','Status','Md5,SHA256,Cmd,File']); foreach my $ip (keys %{$self->{'webserver'}->{'users'}}){ foreach my $module (keys %{$self->{'webserver'}->{'users'}->{$ip}}){ my ($obj,$file) = $self->{'webserver'}->{'users'}->{$ip}->{$module}; $file = $obj->{'file'} if ($obj->{'file'}); $t->addRow($ip,$module,$obj->{'status'},$file); } $j++; } if ($j){ #object found $self->{'isrmain'}->println($t->draw()."\n"); }else{ $self->{'isrmain'}->println("[*] Waiting users..\n") } } ########################################################################## # FUNCTION run_stop # RECEIVES # RETURNS # EXPECTS # DOES stop servers sub stop_server { my $self = shift; my $server_type = shift; if ($self->{$server_type}->status()){ $self->{$server_type}->stop(); $self->{'isrmain'}->println("Stopping $self->{$server_type}->{'Base'}->{'whoami'} [OK]\n"); } else{ $self->{'isrmain'}->println("$self->{$server_type}->{'Base'}->{'whoami'} : stopped\n"); } } sub run_stop { my $self = shift; stop_server($self,"webserver"); stop_server($self,"dnsserver") unless ( $self->{'isrmain'}->{'Base'}->{'options'}->{'DNSEnable'}->{'val'} == 0 ); } ########################################################################## # FUNCTION run_restart # RECEIVES # RETURNS # EXPECTS # DOES restart servers sub run_restart { my $self = shift; $self->run_stop(); $self->run_start(); } ########################################################################## # FUNCTION run_exit # RECEIVES # RETURNS # EXPECTS # DOES exit console sub run_exit { my $self = shift; if( $$ == $shellz::ppid ){ $self->run_stop(); kill KILL => $self->{pid}; $self->{on_signal}=1; $self->stoploop(); $self->SUPER::DESTROY; system("reset"); } # $self->SUPER::DESTROY; # require Term::Screen; # my $terminal = new Term::Screen; # $terminal->clrscr(); # $terminal::DESTROY; # sleep 2; exit 0; } ########################################################################## # FUNCTION console_cmd # RECEIVES xml cmd command # RETURNS # EXPECTS # DOES communication commands between thread and parent (called from Shell) sub console_cmd { my $self = shift; my ($cmd) = @_; my ($action,$module,$ip,$file); #TODO: Move to object my $action =$1 if $cmd =~ /\([\w]+)\<\/action\>/; my $module =$1 if $cmd =~ /\([\w\:\_\-]+)\<\/module\>/; my $ip =$1 if $cmd =~ /\([\d\.]+)\<\/ip\>/; my $file =$1 if $cmd =~ /([\w\W]+)\<\/file\>/; my $md5 =$1 if $cmd =~ /([\w\W]+)\<\/md5\>/; my $sha256 =$1 if $cmd =~ /([\w\W]+)\<\/sha256\>/; my $cwd =$1 if $cmd =~ /([\w\W]+)\<\/cmd\>/; my $tfile=$self->{'webserver'}->{'users'}->{$ip}->{$module}->{'file'}; $self->{'webserver'}->{'users'}->{$ip}->{$module}->{'status'}=$action if ($action); if ($file) { $self->{'webserver'}->{'users'}->{$ip}->{$module}->{'file'}=($tfile) ? "$tfile\n$md5,$sha256,'$cwd',$file" :"$md5,$sha256,'$cwd',$file"; } #RPC faraday connection if ($self->{'isrmain'}->{'Base'}->{'options'}->{'faraday'}->{'val'} == 1){ eval { my $cli = RPC::XML::Client->new($self->{'isrmain'}->{'Base'}->{'options'}->{'RPCfaraday'}->{'val'}); my $resp = $cli->send_request('devlog','Importing evilgrade information'); my $h_id = $cli->send_request('createAndAddHost',$ip,"unknown"); my $var = RPC::XML::array->new("URL-http://github.com/infobyte/evilgrade/"); my $v_id = $cli->send_request('createAndAddVulnToHost',$h_id->value,"Evilgrade injection -".$module,"This ip is interacted with evilgrade framework see the notes inside the host for more information",$var,"HIGH"); #add note host id, note, value my $n_id = $cli->send_request('createAndAddNoteToHost',$h_id->value,"Evilgrade -".$module,$action) if ($action); my $n_id2 = $cli->send_request('createAndAddNoteToHost',$h_id->value,"Evilgrade file -".$module,($tfile) ? "$tfile\n$md5,$sha256,'$cwd',$file" :"$md5,$sha256,'$cwd',$file"); } } } ########################################################################## ## HELP ########################################################################## sub smry_show {"Display information of ."} sub smry_version {"Display framework version."} sub smry_set {"Configure variables"} sub smry_configure {"Configure "} sub smry_reload {"Reload to update all the modules"} sub smry_start {"Start webserver"} sub smry_status {"Get webserver status"} sub smry_stop {"Stop webserverR"} sub smry_restart {"Restart webserver"} sub smry_vhosts {"Show vhosts enable"} sub help_show { my ($o,$cmd) = @_; <<'END'; Display information of END } ########################################################################## ## AUTOCOMPLETE ########################################################################## ########################################################################## # FUNCTION comp_show # RECEIVES # RETURNS # EXPECTS # DOES autocomplete command show sub comp_show{ my ($o, $word, $line, $start) = @_; my @comp = ('modules','active','options','status','version','vhosts'); @comp = sort @comp; @comp; } ########################################################################## # FUNCTION comp_configure # RECEIVES # RETURNS # EXPECTS # DOES autocomplete command configure sub comp_configure { my ($o, $word, $line, $start) = @_; my @comp = keys %{$o->{'isrmain'}->{'modules'}}; @comp = sort @comp; @comp; } ########################################################################## # FUNCTION gtime # RECEIVES # RETURNS parsed time string # EXPECTS # DOES get parsed localtime sub gtime{ my @t = localtime(time); return "[".$t[3]."/".(int($t[4])+1)."/".(int($t[5])+1900).":".$t[2].":".$t[1].":".$t[0]."] - "; } ########################################################################## ## PUBLIC FUNCTIONS ########################################################################## ########################################################################## # FUNCTION printshell # RECEIVES msg # RETURNS # EXPECTS message,debug,time # DOES print information to the console thread sub printshell{ my $self = shift; my ($msg,$debug,$time) = @_; #return if return if ($debug && $self->{'isrmain'}->{'Base'}->{'options'}->{'debug'}->{'val'} == 0); local *PARENT = $self->{'comm'}->{'parent'}; my $data; $data=$self->gtime if (!$time); $data .= "[DEBUG] - " if ($debug); $data .=$msg; print PARENT $data; sleep 1; } ########################################################################## # FUNCTION sendcommand # RECEIVES msg # RETURNS # EXPECTS # DOES send internal command between child and parent sub sendcommand{ my $self = shift; my ($msg) = @_; local *PARENT = $self->{'comm'}->{'parent'}; print PARENT $msg; } 1;