#!/usr/bin/perl
;############ MODIFY THIS LINE WITH YOUR PERL LOCATION ############
push(@INC,"/usr/lib/perl5");
require("flush.pl");


;##################################################################
;######## LINUX DISASSEMBLER 2.0799
;######## (C) SiuL+Hacky Jul 1999
;######## You may copy, modify, distribute this program and
;######## is up you to keep this header here
;######## Usage: dasm exe_file dasm_file
;##################################################################


$f_input=$ARGV[0];
$f_output=$ARGV[1];
&printflush(STDOUT, "\nCreating disassembled file ...");
$return=system("objdump -d -T -x --prefix-addresses ".$f_input.">".$f_output."2");
if ($return!=0){
  print "\nERROR OPENING OBJDUMP $return";
  print "\nUsage: dasm exe_file dasm_file";
  print "\nBe sure to get objdump in your path. Check also file
  permissions\n"; exit(1);
 }

open(INPUT, "<".$f_output."2");

&printflush(STDOUT, "\nReading strings ...");
$_=<INPUT>;
while (!/.rodata/){
  $_=<INPUT>;
}
($rubbish, $rest)=split(/.rodata/,$_,2);
($rubbish, $rest)=split(/0/,$rest,2);
@numbers=split(/  /,$rest,5);
$size=hex($numbers[0]);
$starting_address=hex($numbers[1]);
$end_address=$starting_address+$size;
$offset=hex($numbers[3]);
open(CODIGO, "<".$f_input);
seek(CODIGO,$offset,0);
read(CODIGO,$cadena,$size);
close(CODIGO);


SEARCH: while (<INPUT>){
  last SEARCH if (/SYMBOL TABLE/);
}
if (/SYMBOL TABLE/){ 
  &printflush(STDOUT, "\nProcessing symbol table ...");
  $_=<INPUT>;
  while (!/^\n/){
   @st_element=split(/ /, $_);
   $_=$st_element[$#st_element];
   chop;
   $symbol_table{$st_element[0]}=$_;
   $_=<INPUT>;
  }
}
else {
  seek(INPUT,0,0);
}

while (!/\.text/){
  $_=<INPUT>;
}
&printflush(STDOUT,  "\nProcessing jmps and calls ...");

######### the regex gets rid of possible line information #############


while (<INPUT>){
  $_=~ s/0x//g;
  $_=~ s/<.*?>//g;
  $_=~s/  / /g;
  if (/j/){
    ($direccion,$inst,$destino)=split(/ /,$_,3);
    $destino=~s/ //g;
    chomp($destino);
    $salto{$destino}.=($direccion." \; ");
  }
  elsif (/call/){
    ($direccion,$inst,$destino)=split(/ /,$_,3);
    $destino=~s/ //g;
    chomp($destino);
    $call{$destino}.=($direccion." \; ");
  }
}

seek(INPUT,0,0);
&printflush(STDOUT, "\nWritting references ...\n");
open(OUTPUT, ">".$f_output) || die print "\nError opening write file\n";
print OUTPUT "FILE REFERENCED\n\n";

while (!/Disassembly of section .text:/){
 $_=<INPUT>;
 print OUTPUT;
}
$char=".";
$counter=0;
while(<INPUT>){
 $counter++;
 if ( ($counter % 400)==0){
   printflush(STDOUT,$char);
   if ( ($counter % 4000)==0){
     printflush(STDOUT,"\r");
     if ($char eq "."){ $char=" ";}
     else { $char=".";}
   }  
 }
 $copia=$_;
 $_=~s/0x//g;
 $_=~s/<.*?>//ge;
 $_=~s/  / /g;
 ($direccion, $inst, $destino)=split(/ /,$_,3);
 if ( defined( $symbol_table{$direccion} )){
   print OUTPUT "\n";
   print OUTPUT "---- Function : ".$symbol_table{$direccion}." ----\n";
 }
 if (/call/){
   $destino=~s/ //g;
   chomp($destino);
   if ( defined( $symbol_table{$destino} )){
     print OUTPUT "\n";
     print OUTPUT "Reference to function : ".$symbol_table{$destino}."\n\n";
   }
 }  
 if ( defined( $salto{$direccion} )){
   print OUTPUT "\n";
   print OUTPUT "Referenced from jump at ".$salto{$direccion}."\n\n";
 }
 if ( defined( $call{$direccion} )){
   print OUTPUT "\n";
   print OUTPUT "Referenced from call at ".$call{$direccion}."\n\n";
 }
 if (/\$/){
        ($instruccion, $operand)=split(/\$/,$_,2);
        if (!/push/){
          ($operand, $rest)=split(/\,/,$operand,2);
        }
        chomp($operand);
        $offset=hex($operand);
        if ( ($offset <= $end_address) && ($offset >= $starting_address )
        ){
          $auxiliar=substr($cadena, $offset-$starting_address);
          $length=index($auxiliar, pack("x") );
          $auxiliar=substr($auxiliar, 0, $length);       
          $auxiliar=~s/\n//g;
          print OUTPUT "\n";
          print OUTPUT "Possible reference to string:";
          print OUTPUT "\n\"$auxiliar\"\n\n"
        }       
  }
 print OUTPUT $copia;
}
close(INPUT);
close(OUTPUT);
print "\n";
system("rm ".$f_output."2");