#!/usr/bin/perl # VHDL Obfuscation # Dave Stevens # http://iDav.eS/Other-Projects/VHDL-obfuscator/ 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"; $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{lc($word)} = $string; $hash_str_inp{$string} = lc($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{lc($_)} = 1; } close KEYWORD_FILE; } else { print "The keyword file you specified: $keyword_file does not exist\n"; exit(0); } } foreach $file (@files) { print "FILE: $file\n"; $reached_code = 0; open FILE, "< $file" or die "Could not open: $file : $!\n"; @file2 = split(/\//, $file); open FILE_OUT, "> $outdir/$file2[$#file2]" or die "Could not open file: $outdir/$file2[$#file2] : $!\n"; while( ) { $linez = ""; chomp(); ($code, $comment) = split(/--/); $code =~ s/^\s*//; $code =~ s/\s*$//; # check for pragmas if($comment =~ /pragma/) { $linez .= "NEWLINE--$comment"; $linez .= "NEWLINE"; } if((defined($code)) && ($code ne "")) { $reached_code = 1; &token(lc($code)); } if($reached_code != 1) { $linez .= "$_"; $linez .= "NEWLINE"; } # need to get rid of spaces here $linez =~ s/\s+/ /g; $linez =~ s/NEWLINE/\n/g; @linez = split(//, $linez); for($count_it=0;$count_it<=$#linez;$count_it++) { if(($linez[$count_it] eq " ") && (($delim{$linez[$count_it+1]}) || ($delim{$linez[$count_it-1]}))) { } else { print FILE_OUT $linez[$count_it]; } } } close FILE_OUT; close FILE; } open HASH, "> $outdir/hashed.txt" or die; foreach $key (%hash_inp_str) { if($hash_inp_str{$key} ne "") { print HASH "$hash_inp_str{$key} => $key\n"; } } close HASH; exit(0); sub token() { $line = $_[0]; $line .= " "; @line = split(//, $line); $starting = 0; for($i=0;$i<=$#line;$i++) { $what .= $line[$i]; foreach $key (@delim) { if($line[$i] =~ /$key/) { $test = chop($what); if($delim{$test} == 1) { if($test =~ /\t/) { $need_to_add_on = " "; } else { $need_to_add_on = $test; } } else { $what .= $test; } if(($keywords{$what} == 1) || ($delim{$what} == 1) || ($what =~ /^[0-9a-fA-F]+$/) || ($need_to_add_on eq "#")) { @temp = split(//, $what); $k = 0; for($j=$starting;$j<=$i;$j++) { $keyw[$j] = $temp[$k]; $k++; } if($test ne "") { $keyw[$j-1] = $need_to_add_on; undef($need_to_add_on); } $starting = $i+1; $what = ""; last; } else { @temp = split(//, $what); $k = 0; for($j=$starting;$j<=$i;$j++) { $nonkeyw[$j] = $temp[$k]; $k++; } if($test ne "") { $keyw[$j-1] = $need_to_add_on; undef($need_to_add_on); } $starting = $i+1; $what = ""; last; } } } } $to_hash = ""; for($i=0;$i<=length($line)-2;$i++) { if(defined($keyw[$i])) { if($to_hash ne "") { $to_hash = &create_random_string($to_hash); if($to_hash =~ /^(\d)/) { $temp = chr(ord($1) + 64); $to_hash =~ s/^\d/$temp/; $linez .= "$to_hash"; $temp = ""; } else { $linez .= "$to_hash"; } $to_hash = ""; } $linez .= "$keyw[$i]"; } else { $to_hash .= $nonkeyw[$i]; } } if($to_hash ne "") { $to_hash = &create_random_string($to_hash); if($to_hash =~ /^(\d)/) { $temp = chr(ord($1) + 64); $to_hash =~ s/^\d/$temp/; $linez .= "$to_hash"; $temp = ""; } else { $linez .= "$to_hash"; } $to_hash = ""; } $linez .= " "; @keyw = @blank; @nonkeyw = @blank; } # 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{$keyz} = 1; } } # create a random string sub create_random_string() { $inp = $_[0]; $str = ""; # if one has already been created then use that if(defined($hash_inp_str{$inp})) { return $hash_inp_str{$inp}; } # create the new string for($_i=0;$_i<$str_len;$_i++) { $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); } } # 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; }