-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbash_obfus.plx
More file actions
executable file
·136 lines (130 loc) · 4.3 KB
/
bash_obfus.plx
File metadata and controls
executable file
·136 lines (130 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/perl -w
use strict;
use warnings;
use feature ':5.10';
sub print_usage() {
say "$0 is a bash shell script minifier/obfuscator.";
say "It deletes full line comments, whitespaces and tabs, and obfuscates variable names.";
say "Usage:";
say "\t $0 -h \t This help message.";
say "\t $0 -i <input_file> -o <output_file> [-V <new_var_string>] -C -F";
say "\t Where:";
say "\t\t<input_file>\tis the shell script you want to obfuscate";
say "\t\t<output_file>\tis where you want to save the obfuscated script";
say "\t\t<new_var_string>\tis an optional argument that defines what all variables will be changed to.";
say "\t\t\tThe default is 'a', which means all variables will be changed to a0,a1,a2,a3,...";
say "\t\t-C\tis an option to clean out full line comments and blank lines.";
say "\t\t-F\tis an option to flatten out the code (remove indentations)";
exit 0;
}
sub parse_cmd_args {
my $input_file="";
my $output_file="";
my $delete_blanks="";
my $flatten="";
my $new_var="a";
for my $argnum (0 .. $#ARGV) {
if ($ARGV[$argnum] eq "-i") {
$input_file=$ARGV[$argnum+1];
$argnum++;
} elsif ($ARGV[$argnum] eq "-o") {
$output_file=$ARGV[$argnum+1];
$argnum++;
} elsif ($ARGV[$argnum] eq "-h") {
&print_usage();
} elsif ($ARGV[$argnum] eq "-V") {
$new_var=$ARGV[$argnum+1];
$argnum++;
} elsif ($ARGV[$argnum] eq "-C") {
$delete_blanks=1;
} elsif ($ARGV[$argnum] eq "-F") {
$flatten=1;
}
}
if ($input_file eq "" || $output_file eq "") {
say "Input or output file not specified!!";
&print_usage();
}
return ($input_file,$output_file,$new_var,$delete_blanks,$flatten);
}
sub parse_vars_from_file {
my $file_name=shift;
open(my $fh, "<", $file_name) || die "Couldn't open '".$file_name."' for reading because: ".$!;
my %vars=();
while(my $line=<$fh>) {
# First pull var names from declarations
if ($line =~ m/^[ \t]*([a-z]+[a-z0-9_]*)=/) {
$vars{$1}=1;
# Then, from read statements
} elsif (($line =~ m/^[ \t]*read -s ([a-z]+[a-z0-9_]*)/) || ($line =~ m/^[ \t]*read ([a-z]+[a-z0-9_]*)/)) {
$vars{$1}=1;
# Then, from for loops
} elsif ($line =~ m/^[ \t]*for ([a-z]+[a-z0-9_]*) /) {
$vars{$1}=1;
# Then, from array access
} elsif ($line =~ m/^[ \t]*([a-z]+[a-z0-9_]*)\[.+\]=/) {
$vars{$1}=1;
}
}
close $fh;
return keys %vars;
}
sub obfuscate {
my $input_file=shift;
my $output_file=shift;
my $new_var=shift;
my $delete_blanks=shift;
my $flatten=shift;
my @sorted_vars=@_;
open(my $ifh, "<", $input_file) || die "Couldn't open '".$input_file."' for reading because: ".$!;
open(my $ofh, ">", $output_file) || die "Couldn't open '".$output_file."' for writing because: ".$!;
my %var_obfus=();
my $var_index=0;
for my $var (@sorted_vars) {
$var_obfus{$var}=$new_var.$var_index;
$var_index++;
}
my %vars=();
while(my $line=<$ifh>) {
if ($delete_blanks && (($line =~ m/^#[^!].*/) || ($line =~ m/^[ \t]*$/))) {
next;
}
if ($flatten) {
$line =~ s/^[ \t]*//;
}
for my $var (@sorted_vars) {
# Substitute var names in declarations
$line =~ s/^([ \t]*)$var=/$1$var_obfus{$var}=/;
# Then, in read statements
$line =~ s/^([ \t]*read .*)$var/$1$var_obfus{$var}/;
# Then, in for loops
$line =~ s/^([ \t]*for )$var/$1$var_obfus{$var}/;
# Then, in array access
$line =~ s/^([ \t]*)$var(\[.+\]=)/$1$var_obfus{$var}$2/;
# General "$" usage while making sure we're not inside ''
while ($line =~ m/^(([^\']*('[^']*')*[^']*)*)\$$var/) {
$line =~ s/^(([^\']*('[^']*')*[^']*)*)\$$var/$1\$$var_obfus{$var}/;
}
# Only allow a $var to be replaced between '' if they're already inside ""
while ($line =~ m/^([^']*(('[^']*')*("[^"]")*)*"[^"]*)\$$var/) {
$line =~ s/^([^']*(('[^']*')*("[^"]")*)*"[^"]*)\$$var/$1\$$var_obfus{$var}/;
}
# Special case ${var} usage while making sure we're not inside ''
while ($line =~ m/^(([^']*('[^']*')*[^']*)*)\$\{$var/) {
$line =~ s/^(([^']*('[^']*')*[^']*)*)\$\{$var/$1\$\{$var_obfus{$var}/;
}
# Likewise, allow ${var} between '' only if we're already between ""
while ($line =~ m/^([^']*(('[^']*')*("[^"]")*)*"[^"]*)\$\{$var/) {
$line =~ s/^([^']*(('[^']*')*("[^"]")*)*"[^"]*)\$\{$var/$1\$\{$var_obfus{$var}/;
}
}
# Print whatever got through the filters
print $ofh $line
}
close $ifh;
close $ofh;
}
my ($input_file,$output_file,$new_var,$delete_blanks,$flatten)=&parse_cmd_args();
my @parsed_vars=&parse_vars_from_file($input_file);
my @sorted_vars = sort { length($b) <=> length($a) } @parsed_vars;
&obfuscate($input_file,$output_file,$new_var,$delete_blanks,$flatten,@sorted_vars);