#!/usr/bin/perl # VHDL Obfuscator # Dave Stevens - D.Stevens@lboro.ac.uk use POSIX; if($#ARGV < 0) { print< - directory of input files -outdir= - directory to output to *optional -l= - length of strings -k= - file of words to not obfuscate -h= - file of previous hashes ERROR exit(0); } srand(1234567); $extension = "vhd"; #$entity = 1; $str_len = 32; $keyword_file = ""; $hash_file = ""; foreach $arg (@ARGV) { if($arg =~ /-l=(\d+)/) { $str_len = $1; } elsif($arg =~ /\-indir=(\/?((\w+)\/?)+)/i) { if($arg =~ /\/$/) { chop($arg); } ($none, $indir) = split(/=/, $arg); push @files, <$indir/*.$extension>; } elsif($arg =~ /\-outdir=(\/?((\w+)\/?)+)/i) { if($arg =~ /\/$/) { chop($arg); } ($none, $outdir) = split(/=/, $arg); } elsif($arg =~ /-k=(.+)/) { $keyword_file = $1; } elsif($arg =~ /-h=(.+)/) { $hash_file = $1; } } if($outdir eq "") { print "You haven't specified an Output Directory, please use the parameter -outdir=\n"; exit(0); } if($indir eq "") { print "You haven't specified an Input Directory, please use the parameter -indir=\n"; exit(0); } if($#files < 0) { print "No Files Found: $indir\n"; exit(0); } print "SETTINGS------------------------\n"; print "INDIR: $indir\n"; print "OUTDIR: $outdir\n"; print "KEYWORD: $keyword_file\n"; print "HASH: $hash_file\n"; print "LENGTH: $str_len\n\n"; # if out directory does not exist if(!(-d($outdir))) { system("mkdir $outdir"); } &setup_delims("/,>=\"-+)':<&*(.;| "); &setup_keywords("left|right|is|file|entity|reject|e|constant|sll|linkage|severity|rem|access|open|group|impure|else|inout|configuration|case|generate|out|of|body|ror|bus|disconnect|others|for|next|sra|xnor|library|function|downto|begin|rol|attribute|block|x|on|register|nand|array|postponed|alias|use|report|buffer|guarded|package|not|xor|map|signal|if|loop|exit|to|subtype|nor|sla|all|component|until|end|b|and|pure|generic|abs|assert|srl|select|or|new|null|variable|label|unaffected|literal|when|procedure|record|units|process|inertial|return|then|architecture|transport|port|while|o|shr|shl|high|low|range|elsif|mod|type|shared|in|with|wait|after|integer|std_logic|std_logic_vector|ieee|work|std_logic_1164|std_logic_arith|std_logic_unsigned|std_logic_signed|numeric_std|signed|unsigned|std|textio|time|ns|ms|conv_std_logic_vector|natural|range|warning|failure|false|boolean|conv_integer|rising_edge|falling_edge|true|note|error|foreign|event|string"); # pull in the hashed file and the keyword file here! if($hash_file ne "") { # check if file exists if(-e($hash_file)) { open HASH_FILE, "< $hash_file" or die "Could not open file: $hash_file ($!)\n"; while( ) { chomp(); ($string, $word) = split(/ => /); if(defined($string)) { $hash_inp_str{uc($word)} = $string; $hash_str_inp{$string} = uc($word); } } close HASH_FILE; } else { print "The hash file you specified: $hash_file does not exist\n"; exit(0); } } if($keyword_file ne "") { # check if file exists if(-e($keyword_file)) { open KEYWORD_FILE, "<$keyword_file" or die "Could not open file: $keyword_file ($!)\n"; while( ) { chomp(); $keywords{uc($_)} = 1; } close KEYWORD_FILE; } else { print "The keyword file you specified: $keyword_file does not exist\n"; exit(0); } } foreach $file (@files) { open IN_FILE, "< $file" or die "Could not open: $file : $!\n"; @out_file = split(/\//, $file); open OUT_FILE, "> $outdir/$out_file[$#out_file]" or die "Could not open file: $outdir/$out_file[$#out_file] : $!\n"; $in_a_string = 0; while( ) { chomp(); $_ =~ s/^\s+//g; ($code, $comment) = split(/--/, $_); if($comment =~ /pragma/) { print OUT_FILE "\n--", $comment, "\n"; } if(defined($code)) { @words = split(/\s+/, $code); foreach $word (@words) { @chars = split(//, $word); $current = ""; for($i=0;$i<=$#chars;$i++) { if($in_a_string) { for($j=$i;$j<=$#chars;$j++) { print OUT_FILE $chars[$j]; if($chars[$j] eq '"') { $in_a_string = 0; #this is the end; $i = $j+1; last; } } if($j >= $#chars) { print OUT_FILE " "; last; } } elsif($chars[$i] eq '"') { if(defined($current) && ($current ne "")) { if($keywords{uc($current)} == 1) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\d+$/) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\w+#\w+#$/) { print OUT_FILE $current; undef($current); } else { print OUT_FILE &create_random_string($current); undef($current); } } $in_a_string = 1; print OUT_FILE $chars[$i]; for($j=$i+1;$j<=$#chars;$j++) { print OUT_FILE $chars[$j]; if($chars[$j] eq '"') { $i = $j+1; $in_a_string = 0; last; } } if($j >= $#chars) { print OUT_FILE " "; last; } } $current .= $chars[$i]; # check for delims if($delim{$chars[$i]} == 1) { $delim .= chop($current); if(defined($current) && ($current ne "")) { if($keywords{uc($current)} == 1) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\d+$/) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\w+#\w+#$/) { print OUT_FILE $current; undef($current); } else { print OUT_FILE &create_random_string($current); undef($current); } } print OUT_FILE $delim; undef($delim); } } if(defined($current) && ($current ne "")) { if($keywords{uc($current)} == 1) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\d+$/) { print OUT_FILE $current; undef($current); } elsif($current =~ /^\w+#\w+#$/) { print OUT_FILE $current; undef($current); } else { print OUT_FILE &create_random_string($current); undef($current); } } print OUT_FILE " "; } } # print OUT_FILE "\n"; } close IN_FILE; close OUT_FILE; } open HASHED, "> hashed.txt" or die; while(($key, $value) = each(%hash_str_inp)) { print HASHED $key, " => ", $value, "\n"; } close HASHED; exit(0); # setup @delim and %delim sub setup_delims() { @delims = split(//, $_[0]); foreach $del (@delims) { push @delim, "\\$del"; $delim{$del} = 1; } } # setup %keywords sub setup_keywords() { @keywords = split(/\|/, $_[0]); foreach $keyz (@keywords) { $keywords{uc($keyz)} = 1; } } # create a random string sub create_random_string() { $inp = uc($_[0]); $str = ""; # if one has already been created then use that if(defined($hash_inp_str{$inp})) { return $hash_inp_str{$inp}; } # while(($key, $value) = each(%hash_inp_str)) # { # if($key =~ /^$inp$/i) # { # return $hash_inp_str{$inp}; # } # } # create the new string for($_i=0;$_i<$str_len;$_i++) { #$str .= chr(int(rand(26)) + 97); $temp = int(rand(26+26+10)); if($temp < 26) { $str .= chr($temp + 97); } elsif(($temp >= 26) && ($temp < 52)) { $str .= chr($temp - 26 + 65); } else { $str .= chr($temp - 52 + 48); } } if($str =~ /^(\d)/) { $temp = chr(ord($1) + 64); $str =~ s/^\d/$temp/; } # at this point if there are ay clashes they fail out. if(defined($hash_str_inp{$str})) { print "There has been a clash matey!\n"; exit(0); } $hash_inp_str{$inp} = $str; $hash_str_inp{$str} = $inp; return $str; }