# mio-star password cracker v 0.1 common modul
# 
#


$conf_file = './mio.conf';
$new_conf_file = './.new_mio.conf';
$statistik = './.statistik';
$new_statistik = './.new_statistik';
$statistik_roh = './.statistik_roh';
$new_statistik_roh = './.new_statistik_roh';
$session_dir = './sessions/';
$pool_file = './.pool_file';
$new_pool_file = './.new_pool_file';
$act_pool_file = './.act_pool';
$new_act_pool_file = './.new_act_pool';
$time_out = 5;


sub help {
   print "\n\n\t\tmio-star password cracker v 0.1\n";
   print "\t\t********************************\n\n";
   print "\tsyntax:\t$0 benutzername:crypt-pw bereich [pool] [session-id]\n";
   print "\tbsp:\t$0 root:LprGI9pVfAB4U 4-7 [1] [www.victim.com]\n\n";
   print "\tbereich definiert die mindest und maximal anzahl zeichen die in \n";
   print "\teinem passwort vorkommen können. pool definiert die zeichen, die\n";
   print "\tin einem passwort vorkommen duerfen (siehe mio.conf).\n";
   print "\tsession-id dient fuer das recovery und weiterfuehren von unter-\n";
   print "\tbrochenen crack-sessions\n\n";
   exit;
}

sub get_config {
   open(CONF, "< $conf_file") || give_up("$conf_file", $!, "permissions vom $conf_file ueberpruefen");
   my(@hosts) = ();
   my(@splitter) = ();
   my(@splitter2) = ();
   while(defined($conf_line = <CONF>)) {
      chomp($conf_line);
      next if $conf_line =~ /^#|^$/;
      if ($conf_line =~ /^host:/) {
         @splitter = split(/:/, $conf_line, 4);
	 push(@hosts, $splitter[1]);
      } elsif ($conf_line =~ /^pool$pool/) {
	 $pool_content = $conf_line;
         @splitter2 = split(/:/, $pool_content, 4);
         $characters = $splitter2[1];
      }
   }
   close(CONF);
   return($characters, @hosts);
}

sub get_hosts {
   my(@hosts) = @_;
   my(@splitter) = ();
   
   open(CONF, "< $conf_file") || give_up("$conf_file", $!, "permissions vom $conf_file ueberpruefen");
   while(defined($conf_line = <CONF>)) {
      next if $conf_line =~ /^#|^$/;
      if ($conf_line =~ /^host:/) {
         @splitter = split(/:/, $conf_line, 4);
	 push(@hosts, $splitter[1]);
      }
   }
   close(CONF);
   return(@hosts);
}

sub get_max_pools {
   my($file) = shift;
   my($myreturn) = 0;
   open(POOL_FILE, "< $file") || give_up("$file", $!, "permissions von $session_path und/oder $file ueberpruefen");
   while(defined($conf_line = <POOL_FILE>)) {
      $myreturn++;
   }
   close(POOL_FILE);
   return($myreturn);
}

sub get_passwd {
   my ($host) = shift;
   my @splitter;
   
   open(CONF, "< $conf_file") || give_up("$conf_file", $!, "permissions vom $conf_file ueberpruefen");
   while($conf_line = <CONF>) {
      chomp($conf_line);
      next if $conf_line =~ /^#|^$/;
      if ($conf_line =~ /^host:$host/) {
         @splitter = split(/:/, $conf_line, 4);
	 return($splitter[2]);
      }
   }
   return(0);
   close(CONF);
}

sub get_port {
   my ($host) = shift;
   my @splitter;
   
   open(CONF, "< $conf_file") || give_up("$conf_file", $!, "permissions vom $conf_file ueberpruefen");
   while($conf_line = <CONF>) {
      chomp($conf_line);
      next if $conf_line =~ /^#|^$/;
      if ($conf_line =~ /^host:$host/) {
         @splitter = split(/:/, $conf_line, 4);
	 return($splitter[3]);
      }
   }
   return(0);
   close(CONF);
}
   

sub make_pool {
   my($characters) = shift;
   my($min, $max) = @_;
   my @pool = ();
   my @letters = split(/ */, $characters);
   foreach $counter ($min..$max) {
      foreach $letter (@letters) {
         push(@pool, "$pool:$letter:$counter");
      }
   }
   return(@pool);
}

sub check_stat {
   my($suspended, $deactivated) = 0;
   open(CONF, "< $conf_file") || give_up("$conf_file", $!, "permissions vom $conf_file ueberpruefen");
   while($conf_line = <CONF>) {
      chomp($conf_line);
      if ($conf_line =~ /host:.+?:/) {
         if ($conf_line =~ /^host:/) {
#
# immer noch am cracken
#
           close(CONF);
	   return(0);
	 } elsif ($conf_line =~ /^#host:/) {
	    $deactivated++;
	 } elsif ($conf_line =~ /^##host:/) {
            $suspended++;
	 }
      }
   }
   close(CONF);

   if(($suspended == 0) && ($deactivated > 0)) {
#
# alle nicht mehr erreichbar -> abbruch
#
      return(1);
   } elsif (($suspended > 0) && ($deactivated == 0)) {
#
# alle fertig gecrackt
#
      return(2);
   } elsif (($suspended > 0) && ($deactivated > 0)) {
#
# hosts waren deaktiviert und weitere wurden suspendiert
#
      return(3);
   } else {
#
# scheissen! darf nicht vorkommen. fehler
#
      return(4);
   }
}

sub get_next_pool {
   my($myreply);
   my(@entries);
   
   open(POOLS, $pool_file) || give_up($pool_file, $!, "permissions vom lokalem verzeichnis ueberpruefen");
   open(NEW_POOLS, ">$new_pool_file") || give_up($new_pool_file, $!, "permissions vom lokalem verzeichnis ueberpruefen");

   @entries = <POOLS>;
   $myreply = shift(@entries);
   print NEW_POOLS @entries;

   close(POOLS);
   close(NEW_POOLS) || give_up($new_pool_file, $!, "permissions vom lokalem verzeichnis ueberpruefen");

   rename($new_pool_file, $pool_file);
   return($myreply);
}

sub update_act_pool_file {
   my($host, $pool) = @_; 
   my($line);
   my($status) = 0;
   chomp($host, $pool); 
   $host =~ s/SOCKET//;
 
   open(OLD, $act_pool_file) || give_up("$act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");
   open(NEW, ">$new_act_pool_file") || give_up("$new_act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");
   
   while (defined($entry = <OLD>)) {
      chomp($entry);
      if ($entry =~ /$host/) {
         print NEW "$host#$pool\n";
	 $status = 1;
      } else {
         print NEW "$entry\n";
      }
   }

   unless ($status) {
      print NEW "$host#$pool\n";
   }
   
   close(NEW) || give_up("$new_act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");;
   close(OLD);
   rename($new_act_pool_file, $act_pool_file);
}

sub add_old_pool_to_stack {
   my($host) = shift;
   my(@splitter);
   
   $host =~ s/SOCKET//;
   
   open(OLD, $act_pool_file) || give_up("$act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");
   open(NEW, ">$new_act_pool_file") || give_up("$new_act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");

   while (defined($entry = <OLD>)) {
      chomp($entry);
      if ($entry =~ /$host/) {
         open(POOL, ">>$pool_file") || give_up("$pool_file", $!, "permissions vom $pool_file ueberpruefen");
         @splitter = split(/#/, $entry);
	 print POOL "$splitter[1]\n";
	 close(POOL) || give_up("$pool_file", $!, "permissions vom $pool_file ueberpruefen");
      } else {
         print NEW "$entry\n";
      }
   }

   close(OLD);
   close(NEW) || give_up("$new_act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");
   rename($new_act_pool_file, $act_pool_file);
}

sub add_all_pools_to_stack {
   my(@splitter);
   
   $host =~ s/SOCKET//;
   
   open(OLD, $act_pool_file) || give_up("$act_pool_file", $!, "permissions vom $act_pool_file ueberpruefen");
   open(POOL, ">>$pool_file") || give_up("$pool_file", $!, "permissions vom $pool_file ueberpruefen");

   while (defined($entry = <OLD>)) {
      chomp($entry);
      @splitter = split(/#/, $entry);
      print POOL "$splitter[1]\n";
   }

   close(OLD);
   close(POOL) || give_up("$pool_file", $!, "permissions vom $pool_file ueberpruefen");
}

sub give_up {
   $function = shift;
   $err_msg = shift;
   $measures = shift;
   print "\nin $function ist ein fehler aufgetreten\n";
   print "systemfehlermeldung:\t$err_msg\n";
   print "massnahmen:\t\t$measures\n\n";
   exit;
}

sub connects {
   my(@hosts) = @_;
   my($buffer) = '';
   foreach $server_addr (@hosts) {
      $socket_name = "SOCKET" . $server_addr;
      select $socket_name; $| = 1; select STDOUT;
      $i_addr = (gethostbyname($server_addr))[4];
      $addr = sockaddr_in(get_port($server_addr), $i_addr);
      socket($socket_name, PF_INET, SOCK_STREAM, 6) ||
           (del_host($socket_name) && next);
      connect($socket_name, $addr) ||
           (del_host($socket_name) && next);
      printf("socket fuer\t%-20s \t\tok\n", $server_addr);
      recv $socket_name, $buffer, 512,0;
      (del_host($socket_name) && next) if $buffer !~ /OK/;
      $pass_string = get_passwd($server_addr);
      send $socket_name, "$pass_string  ", 0;
      recv $socket_name, $buffer, 512,0;
      del_host($socket_name) if $buffer !~ /OK/;
   }
}

sub close_connections {
   endwin();
   foreach $server_addr (@hosts) {
      $buffer = '';
      $socket_name = "SOCKET" . $server_addr;
      send $socket_name, "EXIT  ", 0;
      recv $socket_name, $buffer, 512, 0;
      unless ($buffer =~ /OK/) {
         print "die connection zu $server_addr konnte nicht getrennt werden\n\n";
         print "buffer = $buffer\n\n";
      }
      close($socket_name) ||
         give_up("CLOSE", "$socket_name: $!", "config pruefen");
   }	 
   
   unlink($statistik);
   unlink($new_statistik);
   unlink($statistik_roh);
   unlink($new_statistik_roh);
   unlink($pool_file);
   unlink($new_pool_file);
   unlink($act_pool_file);
   print "\a";
   exit;
}

sub stop_kill {
   $SIG{KILL} = \&stop_kill;
   add_all_pools_to_stack();
   copy($pool_file, $session_dir . $session_id);
   close_connections();
   exit;
}

sub stop_alarm {
   $SIG{ALRM} = \&stop_alarm;
   die "timeout";
}

sub statistik_roh {
   my $host = shift;
   my $secs = shift;
   my $cracks = shift;
   my $average = shift;
   my $zustand = shift;
   my $serial = shift;
   my $stat_roh_line;
   my $status = 0;
   unless(open(STAT_ROH, $statistik_roh)) {
      give_up("OPEN","$statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   
   unless(open(NEW_STAT_ROH, ">$new_statistik_roh")) {
      give_up("OPEN","$new_statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   }

   while($old_stat_roh_line = <STAT_ROH>) {
      chomp($old_stat_roh_line);
      if ($old_stat_roh_line =~ /^$host:/) {
         @splitter = split(/:/, $old_stat_roh_line);
	 if ($splitter[2] > $cracks) {
	    $new_secs   = $secs;
	    $new_cracks = $cracks;
	 } elsif ($splitter[2] == $secs) {
            $new_secs   = 0;
	    $new_cracks = 0;
	 } else {
            $new_secs   = $secs - $splitter[1];
	    $new_cracks = $cracks - $splitter[2];
	 }
	 print NEW_STAT_ROH "$host:$secs:$cracks:$serial\n";
	 $status = 1;
      } else {
	 print NEW_STAT_ROH "$old_stat_roh_line\n";
      }
   }
   unless ($status) {
      print NEW_STAT_ROH "$host:$secs:$cracks:$serial\n";
      statistik($host,$secs,$cracks,$serial);
   }
   close(STAT_ROH);
   close(NEW_STAT_ROH) ||  give_up("OPEN","$new_statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   rename($new_statistik_roh, $statistik_roh);
   statistik($host,$new_secs,$new_cracks,$serial);
}

sub statistik {
   my $host = shift;
   my $secs = shift;
   my $cracks = shift;
   my $serial = shift;
   unless(open(STATISTIK, $statistik)) {
      give_up("OPEN","$statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   
   unless(open(NEW_STAT, ">$new_statistik")) {
      give_up("OPEN","$new_statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   my $status = 0;
#
# neue statistik mit upgedateten daten
# erstellen
#
   while($stat_line = <STATISTIK>) {
      chomp($stat_line);
      if ($stat_line =~ /^$host:/) {
#
# eintrag updaten
#
         ($host, $old_secs, $old_cracks, $old_average) = split(/:/, $stat_line);
	 $new_secs = $old_secs + $secs;
	 $new_cracks = $old_cracks + $cracks;
	 $new_cracks = 1 if $new_cracks == 0;
	 $new_secs = 1 if $new_secs == 0;
	 $new_average = int $new_cracks / $new_secs;
	 print NEW_STAT "$host:$new_secs:$new_cracks:$new_average\n";
	 $status = 1;
      } else {
         print NEW_STAT "$stat_line\n";
      }
   }
#
# es war noch kein eintrag vorhanden
#
   unless ($status) {
      print NEW_STAT "$host:$secs:$cracks:$average\n";
   }

   close(STATISTIK);
   close(NEW_STAT) || give_up("OPEN","$new_statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   rename($new_statistik, $statistik);
}

sub init_file {
   my $file = shift;
   unlink($file);
   open(FILE, ">$file") || give_up("initialisieren von $file: ", $!, "permission, pfad von $file ueberpruefen");
   close(FILE);
}

sub screen {
   my $stat = shift;
   my $zeile = 7;
   my $tot_secs = 0;
   my $tot_cracks = 0;
   my $tot_average = 0;
   my $divisor = 1;

   open(FILE, $statistik) || give_up("$statistik", $!, "permissions anpassen oder erstellen");;

#   clear();
   while(<FILE>) {
      move(2,20);
      addstr('mio-star password cracker v 0.1');
      move(3,20);
      addstr('********************************');
      move(5,14);
      addstr('IP-ADRESSE');
      
#
# serial wird wider rausgekickt
#

      move(5,35);
      addstr('SEK');
      move(5,50);
      addstr('CRACKS');
      move(5,62);
      addstr('CRACKS/SEK');


      @stat_splitter = split(/:/, $_);
      $stat_splitter[0] =~ s/SOCKET//g;
#
# host adresse
#
      move($zeile,14);
      addstr($stat_splitter[0]);

#
# seriennummer
#

     move($zeile,33);
     addstr($serial);

#
# anzahl crack sekunden
#

      move($zeile,36);
      addstr($stat_splitter[1]);
#
# anzahl total cracks
#

      move($zeile,50);
      addstr($stat_splitter[2]);
      move($zeile, 1);

#
# anzahl cracks/sec
#

      move($zeile,62);
      addstr($stat_splitter[3]);
      refresh();
      $zeile = $zeile + 1;

#
# totalzeilenberechnungen
#
      $tot_secs = $tot_secs + $stat_splitter[1];
      $tot_cracks = $tot_cracks + $stat_splitter[2];
      $tot_average = $tot_average + $stat_splitter[3];
   }

#
# haesslich, ich weiss. hier waere ein professioneller
# tip sehr hilfreich
#

   if ($tot_secs == 0 || $tot_secs == 1) {
      $tot_secs = 1;
      $tot_secs_status = '__ON__';
   } else {
      if ($tot_secs_status ne '__ON__') {
         $tot_secs = $tot_secs - 1;
	 $tot_cracks = $tot_cracks - 1;
         my $tot_secs_status = '__OFF__';
      }
   }
   
   $zeile = $zeile + 1;
   move($zeile,0);
   addstr("--------------------------------------------------------------------------------");
   $zeile = $zeile + 1;
   $average = int $tot_cracks / $tot_secs;
   
#
# summierte totals
#

      
   move($zeile,1);
   addstr("TOTAL        : ");
   move($zeile,36);
   addstr($tot_secs);
   move($zeile,50);
   addstr($tot_cracks);
   move($zeile,62);
   addstr($tot_average);

   $zeile++;

#
# durchschnitts totals
#

# autsch, der ist haesslich.

   open(STATUS, $statistik) || give_up("$statistik", $!, "permissions vom $statistik ueberpruefen");
   while(<STATUS>) {
      $divisor = $.;
   }
   close(STATUS);
   move($zeile,1);
   addstr("DURCHSCHNITT : ");
   move($zeile,36);
   $avg_tot_secs = int $tot_secs / $divisor;
   addstr($avg_tot_secs);
   move($zeile,50);
   $avg_tot_cracks = int $tot_cracks / $divisor;
   addstr($avg_tot_cracks);
   $avg_tot_average = int $tot_average / $divisor;
   move($zeile,62);
   addstr($avg_tot_average);
   
#
# statistik in prozenten
#

   $zeile = $zeile + 1;
   move($zeile, 1);
   addstr("PROZENT      :");
   move($zeile, 16);
   my($percentage) = 100 * $pool_count / $max_pools;
   $percentage =~ s/(\d+\.\d{2}).*/$1/;
   addstr("$percentage%");

#
# status 1, gecrackt oder nix gefunden (dies duerfte aber nicht
# eintreffen
#

   if ($stat == 1) {
      my $username = shift;
      my $passwort = shift;
      $zeile = $zeile + 2;
      move($zeile,1);
      addstr("USERNAME: $username");
      $zeile = $zeile + 1;
      move($zeile,1);
      addstr("PASSWORT: $passwort");
      
   } elsif ($stat == 2) {
      $zeile = $zeile + 2;
      move($zeile,1);
      addstr("PASSWORT NICHT GEFUNDEN !!!");
   } elsif ($stat == 3) {
     $zeile = $zeile + 2;
     move($zeile,1);
     addstr("PASSWORT NICHT GEFUNDEN !!!");
   } elsif ($stat == 4) {
     $zeile = $zeile + 2;
     move($zeile,1);
     addstr("UNVORHERGESEHENER FEHLER IST AUFGETRETEN !!!");
   }

   refresh();
   clear();
   close(FILE);
}

sub ayt {
   my $host = shift;
   $host =~ s/SOCKET//;
   my $ayt_buffer = '';
   if (send $socket_name, "AYT  ", 0) {
      recv $socket_name, $ayt_buffer, 512, 0;
      if ( $ayt_buffer =~ /^OK/) {
         return(1);
      } else {
          return(0);
      }
   } else {
      return(0);
   }
}

sub del_host {
   my($host) = shift;
   my($entry);
   $host =~ s/SOCKET//;

   open(CONF, "$conf_file") || give_up("$conf_file", $!, "permissions vom $host_liste oder aktuellem directory ueberpruefen");
   open(NEW_CONF, ">$new_conf_file") || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
  
   while(defined($entry = <CONF>)) {
      chomp($entry);
      if ($entry =~ /$host/) {
         print NEW_CONF "#$entry\n";
      } else {
         print NEW_CONF "$entry\n";
      }
   }   

   close(CONF);
   close(NEW_CONF) || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
   rename($new_conf_file, $conf_file);
}

sub suspend_host {
   my($host) = shift;
   my($entry);
   $host =~ s/SOCKET//;
#
# pool_count wird im hauptloop nicht erhoeht, drum hier
# nachholen, damit die percentage-statistik wieder aufgeht.
#
   $pool_count++;
   open(CONF, "$conf_file") || give_up("$conf_file", $!, "permissions vom $host_liste oder aktuellem directory ueberpruefen");
   open(NEW_CONF, ">$new_conf_file") || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
  
   while(defined($entry = <CONF>)) {
      chomp($entry);
      if ($entry =~ /$host/) {
         print NEW_CONF "##$entry\n";
      } else {
         print NEW_CONF "$entry\n";
      }
   }   

   close(CONF);
   close(NEW_CONF) || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
   rename($new_conf_file, $conf_file);
}

sub reactivate_hosts {
   my($host) = shift;
   my($entry);
   $host =~ s/SOCKET//;

   open(CONF, "$conf_file") || give_up("$conf_file", $!, "permissions vom $host_liste oder aktuellem directory ueberpruefen");
   open(NEW_CONF, ">$new_conf_file") || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
  
   while(defined($entry = <CONF>)) {
      chomp($entry);
      if ($entry =~ /##$host/) {
         $entry =~ s/#//g;
         print NEW_CONF "$entry\n";
      } else {
         print NEW_CONF "$entry\n";
      }
   }   

   close(CONF);
   close(NEW_CONF) || give_up("$new_conf_fil", $!, "permissions vom $new_host_liste oder aktuellem directory ueberpruefen");
   rename($new_conf_file, $conf_file);
}

sub del_stat {
   my $host = shift;
   my $entry;

#
# zuerst die rohe statistik
#

   unless(open(STATISTIK_ROH, $statistik_roh)) {
      give_up("OPEN","$statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   
   unless(open(NEW_STAT_ROH, ">$new_statistik_roh")) {
      give_up("OPEN","$new_statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   while(defined($entry = <STATISTIK_ROH>)) {
      chomp($entry);
      if ($entry !~ /$host/) {
         print NEW_STAT_ROH "$entry\n";
      }      
   }

   close(STATISTIK_ROH);
   close(NEW_STAT_ROH) || give_up("OPEN","$new_statistik_roh: $!", "permission, pfad ueberpruefen oder erstellen");
   rename($new_statistik_roh, $statistik_roh);

#
# dann die berechnete statistik
#
   unless(open(STATISTIK, $statistik)) {
      give_up("OPEN","$statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   
   unless(open(NEW_STAT, ">$new_statistik")) {
      give_up("OPEN","$new_statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   }
   while(defined($entry = <STATISTIK>)) {
      chomp($entry);
      if ($entry !~ /$host/) {
         print NEW_STAT "$entry\n";
      }      
   }
   close(STATISTIK);
   close(NEW_STAT) || give_up("OPEN","$new_statistik: $!", "permission, pfad ueberpruefen oder erstellen");
   rename($new_statistik, $statistik);
}


1;
