#!/usr/bin/perl
#
# (hhp-temprace.pl) v6.0
# Author: Cody Tubbs (loophole of hhp).
#   Site: http://www.hhp-programming.net/
#  Email: pigspigs@yahoo.com
#   Date: 07/08/2001. 03:01:45PM CST.
#  iDate: 01/13/2001. 11:34:32PM CST.
#
# Description:
# A _simple_ program that works on linux, BSD, Sun/Solaris,
# and   IRIX.    This  initializes  Linux's  strace,  BSD's
# ktrace/kdump, Sun/Solaris's truss, and IRIX's par to find
# and  parse /tmp and current directory temporary file.  It
# parses  for *open(), *stat(), unlink(), and rmdir() calls
# done  within  the  target  program.  (BSD only tested for
# open()  so  far,  will add more later).  This information
# can  then  be  used to determine if the target program is
# vulnerable to any temp race conditions.  I made this so I
# don't  have  to  do it manually for every binary I check.
# Use  if  desired  and give the code shouts if a temp race
# condition is found/exploited.
#
# Note  that  I  didn't  really expand the verbosity of the
# *stat()  showings,  just remember that the target program
# probably  checks  to  see  if the temp file exists before
# creation  if  this  is  used,  check in depth afterwards.
#
# Email suggestions if you want to see anything added.
#
# ChangeLog:
#  6.0: Added support for IRIX.  Created some subroutines.
#       (Thanks for the account on your irix box bighawk).
#  5.0: Added OS auto detection, not user supplied anymore.     
#  4.0: Added support for BSD and Sun/Solaris and verbosity
#       for ktrace[NAMI].
#  3.0: Added verbosity of stat(), unlink() and rmdir().
#
# Todo:
#  Add support for DGUX.
#
################################################

$ver="6_0";

if((@ARGV<1)||(@ARGV>3)){&usage}
$y=0;$f=0;$z=0;$os=0;$foundOS=0;$t=".tmprace";
if((@ARGV<4)&&(@ARGV==3)&&(@ARGV[2] eq"-o")){($p,$k,$o)=@ARGV;$y=1}
if(@ARGV==1){($p)=@ARGV}
if((-e   "/usr/sbin/par")&&($foundOS==0)){$os=4;$foundOS=1}
if((-e "/usr/bin/strace")&&($foundOS==0)){$os=1;$foundOS=1}
if((-e  "/usr/bin/truss")&&($foundOS==0)){$os=2;$foundOS=1}
if((-e "/usr/bin/ktrace")&&($foundOS==0)){$os=3;$foundOS=1}

if($os==0){printf("strace, truss, or ktrace was not found!\n");exit(0)}
unlink("$t");unlink("ktrace.out");
if($y==1){open(O,">>$o")or die "Can't open \"$o\".\n"}

if($os==1){`strace -o $t $p>/dev/null 2>&1`; open(T,"$t")or &dye;}
if($os==2){`truss -o $t $p>/dev/null 2>&1`;  open(T,"$t")or &dye;}
if($os==3){`ktrace $p>/dev/null 2>&1`;       open(T,"$t")or &dye;}
if($os==4){`par -o $t $p>/dev/null 2>&1`;    open(T,"$t")or &dye;}

if($y==1){print O "-"x10 . " temprace$ver results for \"$p\".\n"}else{
 printf("%s temprace$ver results for \"%s\".\n", '-'x10, $p);
}
while(<T>){
 $line=$_;
 chomp($line);
 if($os==1){&stracetruss;}
 if($os==2){&stracetruss;}
 if($os==3){&kdump;}
 if($os==4){&par;}

}

if($f==0){if($y==1){
 print O "NO TMP FILE INFORMATION OR MODIFICATION WAS FOUND!\n"}else{
 printf("NO TMP FILE INFORMATION OR MODIFICATION WAS FOUND!\n")} 
}
if($y==1){print O "-"x10 . " End of results.\n"}else{
 printf("%s End of results.\n", '-'x10);
}
if($y==1){close(O);}
if($y==1){printf(">> Wrote results to: ($o).\n")}
unlink("$t");
unlink("ktrace.out");
exit(0);

sub stracetruss(){
 if($line=~/(.*)open\("(\/tmp\/)*(.*)", (\S+), (\S+)\)/){
  $g=uc($1);$x=$2;$i=$3;$fl=$4;$m=$5;$f=1;
  if(($x eq"")&&($i!~/\//)||($x ne"")){
   if($y==1){print O ">> ".$g."OPEN: ($x$i), FLAGS: ($fl), MODE: ($m).\n"}else{
    printf(">> %sOPEN: (%s%s), FLAGS: (%s), MODE: (%s).\n",$g,$x,$i,$fl,$m);
   }
  }
 }
 if($line=~/stat\("(\/tmp\/)*(.*)", /){ #Might add more here later.
  $ts=$1;$st=$2;$f=1;
  if($z==0){
   if($y==1){print O ">> *STAT: ($ts$st) used at least once.\n"}else{
    printf(">> *STAT: (%s%s) used at least once.\n",$ts,$st);
   }
   $z=1;
  }
 }
 if($line=~/rmdir\("(\/tmp\/)*(.*)"\)/){
  $tr=$1;$rm=$2;$f=1;
  if(($tr eq"")&&($rm!~/\//)||($tr ne"")){
   if($y==1){print O ">> RMDIR: ($tr$rm).\n"}else{
    printf(">> RMDIR: (%s%s).\n",$tr,$rm);
   }
  }
 }
 if($line=~ /unlink\("(\/tmp\/)*(.*)"\)/){
  $tu=$1;$ul=$2;$f=1;
  if(($tu eq"")&&($ul!~/\//)||($tu ne"")){
   if($y==1){print O ">> UNLINK: ($tu$ul).\n"}else{
    printf(">> UNLINK: (%s%s).\n",$tu,$ul);
   }
  }
 }
}

sub kdump(){
 if($line=~/NAMI  "(\/tmp\/)*(.*)"/){ #ktrace open() name.
  $x=$1;$i=$2;$f=1;
  if(($x eq"")&&($i!~/\//)||($x ne"")){
   if($y==1){print O ">> OPEN: ($x$i).\n"}else{
    printf(">> OPEN: (%s%s).\n",$x,$i);
   }
  }
 }
}

sub par(){
 if($line=~/.*mS.*:(.*)open\("(\/tmp\/)*(.*)", (\S+), (\S+)\)/){
  $g=uc($1);$x=$2;$i=$3;$fl=$4;$m=$5;$f=1;
  if(($x eq"")&&($i!~/\//)||($x ne"")){
   if($y==1){print O ">> ".$g."OPEN: ($x$i), FLAGS: ($fl), MODE: ($m).\n"}else{
    printf(">> %sOPEN: (%s%s), FLAGS: (%s), MODE: (%s).\n",$g,$x,$i,$fl,$m);
   }
  }
 }
 if($line=~/.*mS.*: stat\("(\/tmp\/)*(.*)", /){ #Might add more here later.
  $ts=$1;$st=$2;$f=1;
  if($z==0){
   if($y==1){print O ">> *STAT: ($ts$st) used at least once.\n"}else{
    printf(">> *STAT: (%s%s) used at least once.\n",$ts,$st);
   }
   $z=1;
  }
 }
 if($line=~/.*mS.*: rmdir\("(\/tmp\/)*(.*)"\)/){
  $tr=$1;$rm=$2;$f=1;
  if(($tr eq"")&&($rm!~/\//)||($tr ne"")){
   if($y==1){print O ">> RMDIR: ($tr$rm).\n"}else{
    printf(">> RMDIR: (%s%s).\n",$tr,$rm);
   }
  }
 }
 if($line=~ /.*mS.*: unlink\("(\/tmp\/)*(.*)"\)/){
  $tu=$1;$ul=$2;$f=1;
  if(($tu eq"")&&($ul!~/\//)||($tu ne"")){
   if($y==1){print O ">> UNLINK: ($tu$ul).\n"}else{
    printf(">> UNLINK: (%s%s).\n",$tu,$ul);
   }
  }
 }
}

sub dye(){print "Can't open internal tmp file \"$t\".\n";exit(0);}

sub usage(){
 if($<!=0){printf("NOTE: Might require root to execute strace/ktrace|kdump/truss/
par.\n")}
 printf("Usage: %s \"<program> [args]\" [-o outfile]\n",$0);
 printf("Examp: %s \"wall a\"\n",$0);
 printf("Examp: %s \"wall a\" -o outfile\n",$0);
 exit(0);
}
#EOF

