root/framework2/trunk/msfconsole

Revision 2296, 24.4 kB (checked in by hdm, 3 years ago)

The console will now return to the last selected exploit

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl
2 ###############
3
4 ##
5 #         Name: msfconsole
6 #       Author: H D Moore <hdm [at] metasploit.com>
7 #       Author: spoonm <ninjatools [at] hush.com>
8 #  Description: Console shell interface to the Metasploit Exploit Framework
9 #      Version: $Revision$
10 #      License:
11 #
12 #      This file is part of the Metasploit Exploit Framework
13 #      and is subject to the same licenses and copyrights as
14 #      the rest of this package.
15 #
16 ##
17
18 require 5.6.0;
19
20 use strict;
21 use FindBin qw{$RealBin};
22 use lib "$RealBin/lib";
23 use vars qw($VERSION);
24 use IO::Socket;
25 use POSIX;
26 use Getopt::Std;
27 use Sys::Hostname;
28
29 use Pex::PsuedoShell;
30 use Msf::TextUI;
31 use Pex;
32
33 no utf8;
34 no locale;
35
36 Msf::UI::ActiveStateSucks();
37 Msf::UI::BrokenUTF8();
38
39 my $ui = Msf::TextUI->new($RealBin);
40 my $FRAMEVERSION = $ui->Version;
41 my $VERSION = '$Revision$';
42
43 $SIG{'CHLD'} = sub { while (waitpid(-1, WNOHANG) == 0) { } };
44
45 my $exploitsIndex;
46 my $payloadsIndex;
47 my $encodersIndex;
48 my $nopsIndex;
49
50 my $exploits;
51 my $eclasses;
52 my $payloads;
53 my $encoders;
54 my $nops;
55
56 my %opts;
57 getopts('hvqs:', \%opts);
58
59 Usage() if($opts{'h'});
60 Version() if($opts{'v'});
61
62 my $state = {'Mode' => 'Main'};
63
64 # load the modules
65 Load();
66
67 my $console = Pex::PsuedoShell->new('Metasploit Console', 'msf > ', 0);
68 $console->tabCompletion(\&xTabCompletion);
69
70 # configure the last exploit
71 if ( (my $le = $ui->GetEnv('LastModule')) ) {
72         $state->{'Mode'} = 'Exploit';
73         $state->{'Exploit'}->{'Name'} = $le;
74         gUse('use', $le);
75 }
76                
77 # virtual command table
78 my %virtualCmds = ();
79
80 # global command tables
81 my %globalCmds =
82 (
83     'version'   => [\&gVersion,       "Show console version"],
84     'help'      => [\&gHelp,          "Show the main console help"],
85     '?'         => [\&gHelp,          "Show the main console help"],
86     'quit'      => [\&gExit,          "Exit the console"],
87     'exit'      => [\&gExit,          "Exit the console"],
88     'use'       => [\&gUse,           "Select an exploit by name"],
89     'info'      => [\&gInfo,          "Display detailed exploit or payload information"],
90     'cd'        => [\&gChdir,         "Change working directory"],
91     'save'      => [\&gSave,          "Save configuration to disk"],
92     'setg'      => [\&gSet,           "Set a global environment variable"],
93     'unsetg'    => [\&gUnset,         "Remove a global environment variable"],
94     'reload'    => [\&Load,           "Reload exploits and payloads"],
95 );
96
97
98 # main mode commands
99 my %mainCmds =
100 (
101     'show'      => [\&mShow,   "Show available exploits and payloads"],
102 );
103
104 # exploit mode commands
105 my %exploitCmds =
106 (
107     'set'       => [\&eSet,           "Set a temporary environment variable"],
108     'unset'     => [\&eUnset,         "Remove a temporary environment variable"],
109     'back'      => [\&eBack,          "Drop back to the main menu"],
110     'show'      => [\&eShow,          "Show options, advanced, payloads, or targets"],
111     'check'     => [\&eCheck,         "Perform vulnerability check"],
112     'rcheck'    => [\&eReloadCheck,   "Perform vulnerability check"],   
113     'exploit'   => [\&eExploit,       "Launch the actual exploit"],
114     'rexploit'  => [\&eReloadExploit, "Reload and exploit, for us tester types"],
115 );
116
117
118 $state->{'LocalAddress'} = Pex::Utils::SourceIP();
119 xAddAddressCache($state->{'LocalAddress'});
120
121 if (! defined($opts{'q'})) {
122
123     my $username = ($ENV{'USER'} || $ENV{'USERNAME'} || 'unknown');
124     Msf::Logging->PrintLine('[' . localtime(time()) . '] msfconsole started on host ' . hostname() . ' by user ' . $username );
125     Msf::TextUI::PrintAsciiLogo();
126
127     printf("\n+ -- --=[ msfconsole v%s [%d exploits - %d payloads]\n\n",
128            $FRAMEVERSION,
129            scalar(keys(%{$exploits})),
130            scalar(keys(%{$payloads}))
131     );
132 }
133
134 ProcessCmd('use', shift(@ARGV)) if(@ARGV);
135 ProcessScript($opts{'s'}) if(exists($opts{'s'}));
136
137 while (1)
138 {
139     SetupCmds();
140     last if(!ProcessCmd($console->readCommand()));
141 }
142 print "\n";
143
144 sub SetupCmds {
145   %virtualCmds = %globalCmds;
146  
147   my $stateMode = $state->{'Mode'};
148    
149   if ($stateMode eq 'Main')    { foreach (keys(%mainCmds)){ $virtualCmds{$_} = $mainCmds{$_} } }
150   if ($stateMode eq 'Exploit') { foreach (keys(%exploitCmds)){ $virtualCmds{$_} = $exploitCmds{$_} } }
151 }
152
153 sub ProcessCmd {
154   my $cmd = shift;
155   my @args = @_;
156
157   SetupCmds();
158
159   return(0) if(!defined($cmd));
160
161   if(exists($virtualCmds{$cmd})) {
162     $virtualCmds{$cmd}->[0]($cmd, @args);
163   }
164   else {
165     gUnknown($cmd, @args);
166   }
167   return(1);
168 }
169
170 sub ProcessScript {
171   my $file = shift;
172   open(INFILE, "<$file") or die("Cannot open script: $file: $!\n");
173   local $/;
174   my $data = <INFILE>;
175   close(INFILE);
176   foreach my $line (split("\n", $data)) {
177     ProcessCmd(Pex::PsuedoShell->parseCommands($line));
178   }
179 }
180
181 sub Load {
182         my $genv = $ui->_Env;
183         my $senv = $ui->_TempEnvs;
184         my $tenv = $ui->_TempEnv;
185
186     $exploitsIndex = $ui->LoadExploits;
187     $payloadsIndex = $ui->LoadPayloads;
188     $encodersIndex = $ui->LoadEncoders;
189     $nopsIndex     = $ui->LoadNops;
190     $exploits = { };
191     $eclasses = { };
192     $payloads = { };
193     $encoders = { };
194     $nops     = { };
195    
196     foreach my $key (sort(keys(%{$exploitsIndex}))) {
197         $exploits->{$exploitsIndex->{$key}->SelfEndName} = $exploitsIndex->{$key};
198         $eclasses->{$exploitsIndex->{$key}->ModuleClass}++;
199     }
200    
201     foreach my $key (sort(keys(%{$encodersIndex}))) {
202         $encoders->{$encodersIndex->{$key}->SelfEndName} = $encodersIndex->{$key};
203     }
204        
205     foreach my $key (sort(keys(%{$nopsIndex}))) {
206         $nops->{$nopsIndex->{$key}->SelfEndName} = $nopsIndex->{$key};
207     }   
208    
209     foreach my $key (keys(%{$payloadsIndex})) {
210         $payloads->{$payloadsIndex->{$key}->SelfEndName} = $payloadsIndex->{$key};
211     }
212
213
214     # Important, reload the exploit object in state
215     if($state->{'Mode'} eq 'Exploit') {
216       my $exploit = $exploits->{$state->{'Exploit'}->{'Name'}};
217
218       # check to make sure the module reloaded, it could have had errors..
219       if(!$exploit) {
220         xMsg('reload', 'Error reloading current exploit, moving back to Main.');
221         eBack();
222       }
223       # ok, call gUse to reload tab completion, etc
224       else {
225         gUse('use', $state->{'Exploit'}->{'Name'});
226       }
227     }
228        
229         $ui->_Env($genv);
230         $ui->_TempEnvs($senv);
231         $ui->_TempEnv($tenv);
232 }
233
234 sub gSave {
235     my $cmd = shift;
236         if($state->{'Mode'} eq 'Exploit') {
237                 $ui->SetGlobalEnv('LastModule', $state->{'Exploit'}->{'Name'});
238                 $ui->SaveTempEnv($state->{'Exploit'}->{'Name'});
239         } else {
240                 $ui->UnsetGlobalEnv('LastModule');
241         }
242        
243     $ui->SaveConfig;
244     print "Saved configuration to: " . $ui->ConfigFile . "\n";
245 }
246
247 sub gVersion { print "msfconsole version ". Pex::Utils::Rev2Ver($VERSION)."\n" }
248
249 sub gSet {
250     my $cmd = shift;
251     if(@_ == 1) {
252         print "$_[0]: " . $ui->GetGlobalEnv($_[0]) . "\n";
253     }
254     elsif(@_ == 2) {
255         print "$_[0] -> $_[1]\n";
256         $ui->SetGlobalEnv($_[0], $_[1]);
257     }
258     else {
259         foreach (sort(keys(%{$ui->GetGlobalEnv}))) {
260             print "$_: " . $ui->GetGlobalEnv($_) . "\n";
261         }
262     }
263 }
264
265 sub gUnset
266 {
267     my ($cmd, $key) = @_;
268
269     if(!defined($key))
270     {
271         my $ok = xAskYN('Clear env? [yes/no]: ');
272                 return if $ok ne 'yes';
273         $ui->UnsetGlobalEnv;
274     }
275     $ui->UnsetGlobalEnv($key);
276 }
277
278 sub eSet {
279     my $cmd = shift;
280     if(@_ == 1) {
281         print "$_[0]: " . $ui->GetTempEnv($_[0]) . "\n";
282     }
283     elsif(@_ == 2) {
284         print "$_[0] -> $_[1]\n";
285         $ui->SetTempEnv($_[0], $_[1]);
286     }
287     else {
288         foreach (sort(keys(%{$ui->GetTempEnv}))) {
289             print "$_: " . $ui->GetTempEnv($_) . "\n";
290         }
291     }
292    
293     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
294     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload) {
295         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
296     }
297     $prompt .= ' > ';
298     $console->_prompt($prompt);
299 }
300
301 sub eUnset
302 {
303     my ($cmd, $key) = @_;
304
305     if(!defined($key))
306     {
307         my $ok = xAskYN('Clear temporary env? [yes/no]: ');
308                 return if $ok ne 'yes';
309         $ui->UnsetTempEnv;
310     }
311     $ui->UnsetTempEnv($key);
312    
313     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
314     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload) {
315         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
316     }
317     $prompt .= ' > ';
318     $console->_prompt($prompt);
319 }
320
321
322 sub gExit
323 {
324     Msf::Logging->PrintLine('[' . localtime(time()) . '] msfconsole closed' );
325     POSIX::_exit(0) if($ui->GetEnv('AlternateExit') == 1);
326     if($ui->GetEnv('AlternateExit') == 2) {
327       exec('true');
328     }
329     exit(0);
330 }
331
332 sub gUnknown
333 {
334     my ($cmd, @args) = @_;
335    
336     if (! xCheckSystemCommand($cmd))
337     {
338         xMsg($cmd, "command not found");
339     } else {
340                 my $cmdline = "$cmd ". join(" ", @args);
341                 Msf::Logging->PrintLine('[' . localtime(time()) . "] executing system command line '$cmdline'");       
342         system($cmdline);
343     }
344 }
345
346 sub gHelp
347 {
348     my ($cmd, @args) = @_;
349    
350     my $col = Msf::ColPrint->new(8, 6);
351     print "\nMetasploit Framework " . $state->{'Mode'}  . " Console Help\n";
352     print   "======================================\n\n";
353     foreach my $cmd (sort(keys(%virtualCmds)))
354     {
355         $col->AddRow($cmd, $virtualCmds{$cmd}->[1]);
356     }
357     print $col->GetOutput . "\n";
358 }
359
360 sub gUse
361 {
362     my ($cmd, @args) = @_;
363     if (! exists($exploits->{$args[0]}))
364     {
365         xMsg("use", "please specify a valid exploit name");
366         return;
367     }
368    
369     my $exploit = $exploits->{$args[0]};
370    
371     # switch to exploit mode
372     $state->{'Mode'} = 'Exploit';
373    
374     # wipe out any previous exploit state
375     delete($state->{'Exploit'});
376    
377     $state->{'Exploit'}->{'Exploit'} = $exploit;
378     $state->{'Exploit'}->{'Name'} = $args[0];
379     $state->{'Exploit'}->{'Payloads'} = xValidPayloads($exploit);
380
381     $ui->LoadTempEnv($args[0]);
382
383     if(defined($exploit->UseMessage)) {
384       print $exploit->UseMessage . "\n";
385     }
386    
387     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
388     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload)
389     {
390         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
391     }
392     $prompt .= ' > ';
393     $console->_prompt($prompt);
394 }
395
396 sub eBack
397 {
398     $ui->SaveTempEnv($state->{'Exploit'}->{'Name'});
399     $ui->UnsetTempEnv;
400     $state->{'Mode'} = 'Main';
401     $console->_prompt("msf > ");
402 }
403
404 sub gChdir
405 {
406     my ($cmd, @args) = @_;
407    
408     if (! $args[0])
409     {
410         chdir($ENV{'HOME'});
411         return;
412     }
413    
414     if (chdir($args[0]))
415     {
416         xMsg("chdir", "changed to directory $args[0]");
417     } else {
418         xMsg("chdir", "failed to change directory $!");
419     }
420 }
421
422 sub gInfo {
423   my $cmd = shift;
424   my @args = @_;
425   my $module;
426   my $type;
427
428   # Support old info exploit/payload syntax
429   if(@args == 2) {
430     $module = $args[1];
431     $type = $args[0];
432   }
433   elsif(@args == 1) {
434     $module = $args[0];
435   }
436    
437   if(!defined($module) || ($type ? $type !~ /^(encoder|exploit|payload|nop)$/ : 0)) {
438     xMsg("info", "usage: info [type] <module name>");
439     return;
440   }
441
442   if($exploits->{$module} && ($type ? $type eq 'exploit' : 1)) {
443     print "\n" . $ui->DumpExploitSummary($exploits->{$module});
444   }
445   elsif($payloads->{$module} && ($type ? $type eq 'payload' : 1)) {
446     print "\n" . $ui->DumpPayloadSummary($payloads->{$module});
447   }
448
449   # Kinda a hack, we rebuild the keys for exploits and payloads, but
450   # not for nops or encoders...
451   elsif($encoders->{$module} && ($type ? $type eq 'encoder' : 1)) {
452     print "\n" . $ui->DumpEncoderSummary($encoders->{$module});
453   }
454   elsif($nops->{$module} && ($type ? $type eq 'nop' : 1)) {
455     print "\n" . $ui->DumpNopSummary($nops->{$module});
456   }
457  
458   else {
459     xMsg("info", "invalid module name");
460   }
461 }
462
463 sub mShow
464 {
465     my ($cmd, @args) = @_;
466     my $c = $state->{'CONF'};
467    
468     if (lc($args[0]) eq "exploits")
469     {
470         print "\nMetasploit Framework Loaded Exploits\n";
471         print   "====================================\n\n";
472        
473         print $ui->DumpExploits(2, $exploits, $args[1]) . "\n";
474         return;
475     }
476    
477     if (lc($args[0]) eq "payloads")
478     {
479         print "\nMetasploit Framework Loaded Payloads\n";
480         print   "====================================\n\n";
481        
482         print $ui->DumpPayloads(2, $payloads) . "\n";
483         return;
484     }
485
486     if (lc($args[0]) eq "encoders")
487     {
488         print "\nMetasploit Framework Loaded Encoders\n";
489         print   "====================================\n\n";
490        
491         print $ui->DumpEncoders(2, $encoders) . "\n";
492         return;
493     }
494
495     if (lc($args[0]) eq "nops")
496     {
497         print "\nMetasploit Framework Loaded Nop Engines\n";
498         print   "=======================================\n\n";
499        
500         print $ui->DumpNops(2, $nops) . "\n";
501         return;
502     }
503
504     if (lc($args[0]) eq "config")
505     {
506         print "\nMetasploit Framework Configuration\n";
507         print   "====================================\n\n";
508        
509         foreach my $v (sort(keys(%{$c}))) {
510             print "  $v" . (" " x (30-length($v))) . $c->{$v} ."\n";
511         }
512         print "\n";
513         return;
514     }
515
516     xMsg("show", "requires an option: 'exploits', 'payloads', 'encoders', or 'nops'");
517 }
518
519
520 sub eShow
521 {
522     my ($cmd, @args) = @_;
523     if (lc($args[0]) eq 'options')  { eOptions();  return }
524     if (lc($args[0]) eq 'advanced') { eAdvanced(); return }
525     if (lc($args[0]) eq 'targets')  { eTargets();  return }
526     if (lc($args[0]) eq 'payloads') { ePayloads(); return }
527
528     xMsg("show", "specify 'targets', 'payloads', 'options', or 'advanced'");
529
530 }
531
532 sub ePayloads {
533   SaveTemp();
534   FillTemp();
535   $ui->Payloads;
536   RestoreTemp();
537 }
538 sub eOptions {
539   SaveTemp();
540   FillTemp();
541   $ui->Options;
542   RestoreTemp();
543 }
544 sub eAdvanced {
545   SaveTemp();
546   FillTemp();
547   $ui->AdvancedOptions;
548   RestoreTemp();
549 }
550 sub eTargets  {
551   SaveTemp();
552   FillTemp();
553   $ui->Targets;
554   RestoreTemp();
555 }
556
557 sub eCheck {
558   return if($state->{'Mode'} ne 'Exploit');
559   xUpdateAddrCache();
560   SaveTemp();
561   FillTemp();
562   $ui->Check;
563   RestoreTemp();
564 }
565
566 sub eReloadCheck {
567   Load();
568   return eCheck(@_);
569 }
570
571 sub eExploit {
572   return if($state->{'Mode'} ne 'Exploit');
573   xUpdateAddrCache();
574   SaveTemp();
575   FillTemp();
576   $ui->Exploit;
577   RestoreTemp();
578 }
579
580 sub eReloadExploit {
581   Load();
582   return eExploit(@_);
583 }
584
585 sub xMsg
586 {
587     my ($loc, $msg) = @_;
588     print STDERR "msfconsole: $loc: $msg\n";
589 }
590
591 sub xValidPayloads
592 {
593     my $exploit = shift;
594     if($exploit->Payload) {
595       $state->{'Exploit'}->{'Payloads'} = $ui->MatchPayloads($exploit, $payloads);
596       return $state->{'Exploit'}->{'Payloads'};
597     }
598     return;
599 }
600
601 sub xCheckSystemCommand
602 {
603     my $cmd = shift;
604     return(1) if -e $cmd;
605     foreach my $d (split(/:/, $ENV{'PATH'})) {
606    
607         if ($^O eq 'cygwin') {
608             return(1) if -e "$d/$cmd";
609         } else {
610             return(1) if -x "$d/$cmd";
611         }
612     }
613     return(0);
614 }
615
616 sub xGetAddressCache
617 {
618     my $cache = $state->{'CacheAddress'};
619     return keys(%{$cache});
620 }
621
622 sub xAddAddressCache
623 {
624     my $addr = shift;
625     $state->{'CacheAddress'}->{$addr}++
626 }
627
628 sub xUpdateAddrCache
629 {
630     my $x = $state->{'Exploit'}->{'Exploit'};
631     my $p = $ui->GetEnv('PAYLOAD');
632     my %options = ();
633
634    
635     # create a list of all exploit options of type ADDR
636     foreach (keys(%{$x->UserOpts})) {
637         next if $x->UserOpts->{$_}->[1] ne 'ADDR';
638         $options{$_}++;
639     }
640     foreach (keys(%{$x->Advanced})) {
641         next if $x->Advanced->{$_}->[1] ne 'ADDR';
642         $options{$_}++;
643     } 
644
645     # create a list of all payload options of type ADDR
646     if ($x->Payload && $p && exists($payloads->{$p}))
647     {
648         $p = $payloads->{$p};
649         $p->_Load;
650         foreach (keys(%{$p->UserOpts})) {
651             next if $p->UserOpts->{$_}->[1] ne 'ADDR';
652             $options{$_}++;
653         }       
654         foreach (keys(%{$p->Advanced})) {
655             next if $p->Advanced->{$_}->[1] ne 'ADDR';
656             $options{$_}++;
657         }
658     }
659    
660     # scan environments and add to the cache
661     foreach (keys(%options)) {
662         my $value = $ui->GetTempEnv($_) || $ui->GetEnv($_) || undef;
663         next if ! $value;
664         $state->{'CacheAddress'}->{$value}++;
665     }
666 }
667
668 sub xAskYN {
669         my $quest       = shift;
670         my $cinp        = IO::Handle->new_from_fd(0, '<');
671         my $cout        = IO::Handle->new_from_fd(1, '>');
672         my $iblock      = $cinp->blocking;
673        
674         $cinp->blocking(1);
675
676         my $res = 'run';
677         while ($res && $res ne 'yes' && $res ne 'no') {
678                 $cout->printflush($quest);
679                 if ( defined($res = $cinp->getline)) {
680                         chomp($res);
681                         $res = lc($res);
682                 }
683                 else { $cout->printflush("\nError reading from input: $!\n"); }
684         }
685         $cinp->blocking($iblock);
686         return $res;
687 }
688
689
690 #
691 # TAB COMPLETION ROUTINES
692 #
693
694 sub xCreateSetList
695 {
696     if ($state->{"Mode"} eq "Main") { return keys(%{$ui->GetGlobalEnv}) }
697    
698     if ($state->{"Mode"} eq "Exploit")
699     {
700         my %options = ();
701        
702         my $x = $state->{'Exploit'}->{'Exploit'};
703         my $p = $ui->GetEnv('PAYLOAD');
704        
705         foreach (keys(%{$x->UserOpts})) { $options{$_}++ }
706         foreach (keys(%{$x->Advanced})) { $options{$_}++ }
707        
708         if ($x->Payload && $p && exists($payloads->{$p}))
709         {
710             $p = $payloads->{$p};
711             $p->_Load;
712             foreach (keys(%{$p->UserOpts})) { $options{$_}++ }
713             foreach (keys(%{$p->Advanced})) { $options{$_}++ }
714         }
715          
716         if ($x->Payload) { $options{"PAYLOAD"}++ }
717         if ($x->TargetsList) { $options{"TARGET"}++  }
718
719         foreach my $e (keys(%{ $ui->GetEnv })) {
720             $options{$e}++;
721         }
722        
723         foreach my $e (keys(%{ $ui->GetTempEnv })) {
724             $options{$e}++;
725         }   
726
727         return(keys(%options));
728     }
729 }
730
731 sub xCreateSetValueList
732 {
733     if ($state->{"Mode"} eq "Main") { return ' ' }
734    
735     if ($state->{"Mode"} eq "Exploit")
736     {
737         my %results = ();
738        
739         my $n = $state->{'SetName'};
740         my $x = $state->{'Exploit'}->{'Exploit'};
741         my $v = $state->{'Exploit'}->{'Payloads'};
742         my $p = $ui->GetEnv('PAYLOAD');
743
744         if ($x->Payload && $p && exists($payloads->{$p})) { $p = $payloads->{$p} }
745        
746         if (uc($n) eq "PAYLOAD") { return keys(%{$v}) }
747        
748         if (uc($n) eq "TARGET")
749         {
750             my $tidx = 0;
751             foreach ($x->TargetsList) { $results{$tidx}++ ; $tidx++;}
752             return keys(%results);
753         }
754        
755         my ($req, $type, $desc, $dflt);
756        
757         if (exists($x->UserOpts->{$n})) {
758             ($req, $type, $desc, $dflt) = @{$x->UserOpts->{$n}}; 
759         }
760        
761         if (exists($x->Advanced->{$n})) {
762             ($req, $type) = (0, 'DATA');
763             ($dflt, $desc) = @{$x->Advanced->{$n}};
764         }
765                
766         if ($x->Payload && $p && exists($p->UserOpts->{$n})) {
767             ($req, $type, $desc, $dflt) = @{$p->UserOpts->{$n}}; 
768         }
769                
770         if ($x->Payload && $p && exists($p->Advanced->{$n})) {
771             ($req, $type) = (0, 'DATA');
772             ($dflt, $desc) = @{$p->Advanced->{$n}};
773         }
774        
775         if ($dflt) { return ($dflt) }
776        
777         if ($type eq "ADDR") { return xGetAddressCache() }
778         if ($type eq "BOOL") { return ("TRUE", "FALSE") }
779         if ($type eq "FILE") { return undef }
780         if ($type eq "PATH") { return undef }
781         return ' ';
782     }
783 }
784
785 sub xTabCompletion
786 {
787     my ($text, $line, $start, $end) = @_;
788     my ($cmd, @args) = split(/\s+/, $line);
789    
790     # default to match of space
791     $state->{'TabVals'} = [' '];
792    
793     # this handles command matching
794     if ($start == 0) { $state->{'TabVals'} = [sort(keys(%virtualCmds))] }
795    
796     if (lc($cmd) eq "use") { $state->{'TabVals'} = [sort(keys(%{$exploits}))] }
797    
798     if (lc($cmd) eq "show")
799     {
800         if ($state->{'Mode'} eq 'Main') {
801            
802             # Handle ModuleClass tab completion stuff
803             if ($args[0] eq 'exploits') {
804                 $state->{'TabVals'} = [sort(keys(%{$eclasses}))];
805             }
806             # Default to the standard show options
807             else {
808                 $state->{'TabVals'} = ['exploits', 'payloads', 'encoders', 'nops'];
809             }
810         }
811                
812         if ($state->{'Mode'} eq 'Exploit') {
813             $state->{'TabVals'} = ['advanced', 'options', 'targets', 'payloads']
814         }
815     }
816    
817     if (lc($cmd) eq "info")
818     {
819         # display variables if no args are specified
820         if (! $args[0] || (! $args[1] && ($args[0] && $text))) {
821            
822             my %allmods;
823             for (keys(%{$exploits}), keys(%{$payloads}), keys(%{$encoders}), keys(%{$nops})) {
824                 $allmods{$_}++;
825             }
826            
827             $state->{'TabVals'} = ['exploit', 'payload', 'encoder', 'nop', sort(keys(%allmods))]
828         }
829         if (! $args[1] || (! $args[2] && ($args[1] && $text)))
830         {
831             if ($args[0] eq "exploit") { $state->{'TabVals'} = [sort(keys(%{$exploits}))] }
832             if ($args[0] eq "payload") { $state->{'TabVals'} = [sort(keys(%{$payloads}))] }
833             if ($args[0] eq "encoder") { $state->{'TabVals'} = [sort(keys(%{$encoders}))] }
834             if ($args[0] eq "nop"    ) { $state->{'TabVals'} = [sort(keys(%{$nops}))] }           
835         }
836     }
837        
838     if (
839         ($state->{'Mode'} eq "Main"    && lc($cmd) =~ /^(un|)setg$/) ||
840         ($state->{'Mode'} eq "Exploit" && lc($cmd) =~ /^(un|)set$/)
841        )
842     {
843         # display variables if no args are specified
844         if (! $args[0] || (! $args[1] && ($args[0] && $text)))
845         {
846             $state->{'TabVals'} = [sort(xCreateSetList())];
847         } elsif (! $args[1] || (! $args[2] && ($args[1] && $text)))
848         {
849             $state->{'SetName'} = $args[0];
850             $state->{'TabVals'} = [sort(xCreateSetValueList())];
851         }
852     }
853    
854     # revert to file completion for non-commands
855     if (! scalar(@{$state->{'TabVals'}}) && ! exists($virtualCmds{$cmd})) {
856         $state->{'TabVals'} = [];
857     }
858    
859    
860
861     my @matches = $console->_term->completion_matches($text, \&xTabCompletionMatcher);
862     return(@matches);
863 }
864
865
866 # This is a localized closure for matching speed, this routine has been borrowed
867 # from http://lists.n0i.net/pipermail/perl/2003-October/000015.html
868 {
869     my $list_index;
870     my @name;
871    
872     sub xTabCompletionMatcher
873     {
874         my ($text, $mstate) = @_;
875         $text = quotemeta($text);
876
877         # If this is a new word to complete, initialize now.  This
878         # includes saving the length of TEXT for efficiency, and
879         # initializing the index variable to 0.
880
881         unless ($mstate) {
882                 $list_index = 0;
883             @name = @{$state->{'TabVals'}};
884             return undef if (scalar(@name) == 0);
885         }
886
887         # Return the next name which partially matches from the
888         # command list.
889         while ($list_index <= $#name) {
890                 $list_index++;
891                 return $name[$list_index - 1]
892                 if ($name[$list_index - 1] =~ /^$text/);
893         }
894
895         # If no names matched, then return NULL.
896         return undef;
897     }
898 }
899
900 sub SaveTemp {
901   $ui->SaveTempEnv('_Save');
902 }
903
904 sub RestoreTemp {
905   $ui->LoadTempEnv('_Save');
906   $ui->DeleteTempEnv('_Save');
907 }
908
909 sub FillTemp {
910   $ui->SetTempEnv('_ExploitsIndex', $exploitsIndex);
911   $ui->SetTempEnv('_PayloadsIndex', $payloadsIndex);
912   $ui->SetTempEnv('_Encoders', $encodersIndex);
913   $ui->SetTempEnv('_Nops', $nopsIndex);
914
915   $ui->SetTempEnv('_Exploits', $exploits);
916   $ui->SetTempEnv('_Payloads', $payloads);
917
918   my $exploit = $state->{'Exploit'}->{'Exploit'};
919   $ui->SetTempEnv('_Exploit', $exploit);
920  
921   $ui->SetTempEnv('_UI', $ui);
922
923   # XXX added by spoon, maybe this should be looked at...
924   # applying the AutoOpts settings to the local temp env we have setup,
925   # specifically this fixes things like the EXITFUNC display issues
926   # this will later get called again in Exploit::Prepare, maybe we should
927   # look into just having it done once....
928   $exploit->ApplyAutoOpts;
929
930   # setup payload data if exploit requires a payload
931   if($exploit->Payload) {
932     my $payloadName = $ui->GetEnv('PAYLOAD');
933     $ui->SetTempEnv('_PayloadName', $payloadName);
934     my $validPayloads = $ui->MatchPayloads($exploit, $payloads);
935     my $payload = $validPayloads->{$payloadName};
936     # make sure the OO stuff is good for whoever might use this...
937     $payload->_Load if($payload);
938     $ui->SetTempEnv('_Payload', $payload);
939     $ui->SetTempEnv('_ValidPayloads', $validPayloads);
940   }
941   else {
942     $ui->SetTempEnv('_PayloadName', undef);
943     $ui->SetTempEnv('_Payload', undef);
944     $ui->SetTempEnv('_ValidPayloads', undef);
945   }
946 }
947
948 sub Usage {
949     print STDERR qq{
950   Usage: $0 <options> <exploit>
951 Options:
952          -h             You're looking at me baby
953          -v             List version information
954          -s   <file>    Process file of console commands
955          -q             No splash screen on startup
956
957 };
958     exit(0);
959 }
960
961 sub Version {
962     my $ver = Pex::Utils::Rev2Ver($VERSION);
963     print STDERR qq{
964    Framework Version:  $FRAMEVERSION
965   Msfconsole Version:  $ver
966
967 };
968
969   exit(0);
970 }
Note: See TracBrowser for help on using the browser.