Below is a sample input file.
#!/usr/bin/perl =head1 SYNOPSYS A small program that does trivial things. =cut #here is a comment sub doit { my ($v) = @_; print "it's " . ($v + time()) . " seconds since epoch\n"; } doit(2);
Below is that file with just obfuscation applied (though by default Perl-Obfus applies encoding too), with POD documentation preserved. No encoding was applied to the result of obfuscation, so it still looks like difficult-to-understand perl code.
#!/usr/bin/perl =head1 SYNOPSYS A small program that does trivial things. =cut sub zc47cc8b9f5 { ( my ( $z9e1f91fa38 ) = @_ ) ; print ( ( ( "\x69\x74\x27\x73\x20" . ( $z9e1f91fa38 + time ) ) . "\x20\x73\x65\x63\x6f\x6e\x64\x73\x20\x73\x69\x6e\x63\x65\x20\x65\x70\x6f\x63\x68\x0a" ) ) ; } zc47cc8b9f5 ( (0x1963+ 433-0x1b12) ) ;
Below is that file with obfuscation and encoding applied, with POD documentation preserved. As you can see, there is no resemblense of the original or just obfuscated file. (Users of standards non-compliant browsers like Opera6 or Konqueror, please see the sample here).
#!/usr/bin/perl =head1 SYNOPSYS A small program that does trivial things. =cut my $SDzEh = q"{7hD$ZAo8eDSD+/FPUl$m0.nZl3l'++hdD)))%1jO)X2P52YT($IJCsMd+dD))02P52YT($IJCsMdDdWUU);N$IJCsMNi~NYT^272\\/k=dnDJBLRWf+NHpr9.:a q6Ab3xj7FVt45?8Ei1XSYMcOKvuCZgGm,IQ_U2yPhloTe0wzs^272\\/Eg4JN?D9Gfe2sYruVqOW6PF1BXh5:LIiKUZbw8nTamQHlovtCx,_yM70A+dRp z=jc3k.S^272\\/;$IJCsMNiNIEV.($IJCsM);;N};2b3N$IJCsMNiNR^67\\#tVpVeVpTwVpvpgFVpVeVpTmVpYpYVIeIBYvVpVtVpVtVpVtVppXVVglYtTITeglYtTYTvglYtTVTYglYtTYTTglYtTVTpVVVpVBVpVtVpVvYXTeIgToIITeToIIIoTTTtVpVmVpYvIeIwIgVpVeVpVeVpVBVppXVVglYtTpTtVmVpTITY^33\\';$::JBkLsL(.2M(gkbgi2($::JBkxEE0wxE))>hp?3n2((0j01.2M(gkbgi2($::JBkxVxE)))%y0h)Ygkbgi2($::JBkxEE0hxE))Ngkbgi2($::JBkxEE0wxE7E)Ngkbgi2($::JBkxExEE00);L$::JBkLs~Li2^272\\/swNBjVlE+a5oiIWMAgyd6DY=8nLJ7XKu9hpce.0bGPt?r3_mQOC41,RvzxUk:qFH TZSf^272\\/,5L?0duFVab=s mG8ZtxQEiPcn.9+YDXrpCIOWNKAkS1lgU4zMhT_yeH3vR7:w6fjo2JBq^272\\/;$::JBkLsL FdW($::JBk);;L};{KUL$::JBkLsL^33\\'MTTTeVwTpYtTVTpTgTeVeVpVeVpTmpX^545\\';K$H_cwwKR~K1.^272\\/pgITVwXmFBvYtelo^191\\\";$CLR5 JDJbCHbk,($CLR5 INpKjIttNt)1bCHbk,($CLR5 ItINpKt)1(x,U(bCHbk,($CLR5 ItIt))>j7f8,((t=x,U(bCHbk,($CLR5 I9It)))%N32)ybCHbk,($CLR5 INpKNIt));J$CLR5 JD~Jk,\\/K3qDNXrvd:cPlJfe+2Ysko5CShR6x=ujyBLpZUg9zFHmO,VIaTM?wtE0.8A1_4nQW Gi7b\\/EaQ2ykXL_BxcvVn,71rq4:Au3eGzKWTNmdJtDIjMY?9PFbsO.5H+R SZowU6ig8hf0=lCp\\/;$CLR5 JDJVZuB($CLR5 );;J};W{dTJ$CLR5 JDJa\"y^80\\/IpBoltTvYVgXmFwe^272\\/;K$H_cwwKRKV_TyKQTwaK(^545\\'A*^545\\'h$H_cww);Q.,W1K=Cfduu$@K,Y$@;$H_cww;} bTVTpglYtTYTTglYtTITgglYtTITTglYtTIIIglYtTIIgglYtTITvglYtTYTTglYtTVTpglYtTYTTglYtTITeglYtTIIgglYtX,TITTglYtTITgglYtTVTpglYtTITgglYtTYTpglYtTIIIglYtTITTglYtTITtglYtTpIoVVpXVpVeVpVeVpTmVpYwVpY^16\\/;$q1dPXQtQPedPqO($q1dPXGf,.?GZFA)+PedPqO($q1dPXGf6pAGAf)+(cOD(PedPqO($q1dPXGpGf))>fp6=78O((TAYcOD(PedPqO($q1dPXGf6p?Gf)))%ZF6)xPedPqO($q1dPXGf6pTGf))+PedPqO($q1dPXGpGf,.?);Q$q1dPXQt~QqO^16\\/DKoqVI6pzWn9Y7+Oj2.g8rEXwQhU:aB?k_,v5GdRA1mCZ Nub0xFlS3yts4McHJ=eTPfLi^16\\/j3wypar.1W8hxAEk,OcPR5f TV6NHi9=enXBKLmICY?UJ0+udFG4lo7Z:tsDSMbvg2_zQq^16\\/;$q1dPXQtQ04mW($q1dPX);;Q};N&^7\\\";$L?X6bGmG+DA+a8($L?X6bscs3xg)9+DA+a8($L?X6bs3xgs3cWU)9(b8e(+DA+a8($L?X6bs3gEVs3))>W5KI8((EcNb8e(+DA+a8($L?X6bsgcxVs3)))%gUW)l+DA+a8($L?X6bsgcxWs3))9+DA+a8($L?X6bs3gEVsxqF);G$L?X6bGm~Ga8^16\\/Ipwh1KPTUFdSvQ9_iYB8uDJx4EmNa0=7M2ArkyCbcg: H63+WnR?oVzX,q5telOZfjG.sL^16\\/Jci.TY+VSUA7OG16ZNnIjeClMvR04d5KyuFHX? kb=t:,WP9BrzxpLQwqahmDo8g3fsE_2^16\\/;$L?X6bGmGdMRB($L?X6b);;G};{P0G$L?X6bGmGy^7\\\"{3NQ$q1dPXQtQM^16\\/ITTvTYITITTtIVTeIITgVpVtVpVtTpYtTpTI^135\\\";$1OjejDtD+qj+HX($1Ojej2U2ATx)Q(FXM(+qj+HX($1Ojej2xBA2B))>B5abv1X((TAJFXM(+qj+HX($1Ojej2xBU2B)))%AT:)3+qj+HX($1Ojej2xBB2B))Q+qj+HX($1Ojej2xBA2AAc)Q+qj+HX($1Ojej2ATx2BT:);D$1OjejDt~DHX^71\\#;$+zgaqxjxa=6aDr($+zgaq47OI94Ii9F)X(zrc(a=6aDr($+zgaq4P4I))>IbIV+Br((I8zrc(a=6aDr($+zgaq47OIF4I)))%O5F)ya=6aDr($+zgaq4iFb74I))Xa=6aDr($+zgaq4P47OIF);x$+zgaqxj~xDr\\/sx3VMfLo:ba.vc 5k60lzWinNhT81p+O,C?jQwgyH7u_Dr9q2IBREUXePmKdZt=JAYFG4S\\/,z5N9+pmSaQ3kZGKD0wElAMCO.vBXeb?r=h7R:Ty6VdqjtP2F41n cUsouiYLI8xHf_JWg\\/;$+zgaqxjxNLd1($+zgaq);;x};AYvx$+zgaqxjxQ#^200\\/uWIK2zDqU1=xlF6Cn, aMTHY?rpjgOec4o_Qm0fGwtibLXkABdhs.83SN7PZ:9RVv5EJ+y^272\\/IfUD0buwnHSyA5,ECOqY49Z?r8TQxiBeNck_adPmvM3167sp: 2oXF+hK=.RJGtVjLlgWz^272\\/;$1OjejDtDVk9z($1Ojej);;D};{80D$1OjejDtDy^135\\\"{r2K$H_cwwKRK^545\\'VpYTYgIVVpYXITTvTYITITTtIVTeIITgVpYmVpVtVpIwYeVpVtVpVvYXTeIgToIITeToIIIoTTT_^67\\#;$IJCsMNiN2P52YT($IJCsJ^3\\#;$HA4XA B UbjU.T($HA4XAniO33nu1h)cUbjU.T($HA4XAnhn++)cUbjU.T($HA4XAn++ni+xx)c(FTt(UbjU.T($HA4XAn++ni))>3xxR:dT((1hgFTt(UbjU.T($HA4XAn3K+3ni)))%3u1)?UbjU.T($HA4XAniO3ini)); $HA4XA B~ .T^16\\/kKzisN.7_GaOX0DSld2Z3vm?YJPw1L9cyHgUu=rntIqjC+F R4VoeM,A5x6WEbpBhf8T:Q^16\\/8:DMngw4y .v5Hba?6PSikB0rqeN2sch_o3uIWEV7dxQAUO=GpZftlXjR+z1KF,mYJTCL9^16\\/;$HA4XA B 6lGm($HA4XA);; };0^1\\';$WoUXdL5LxG1xSl($WoUXdcucR22_)0(glz(xG1xSl($WoUXdcR2Pucn))>n9_qEHl((6nbglz(xG1xSl($WoUXdcRP_2cn)))%R69)?xG1xSl($WoUXdcR22_cn))0xG1xSl($WoUXdcR2Pucnn2);L$WoUXdL5~LSl^16\\/PW52xZ6OtEKbI4B_FN9SAH1w diYgav3yrpo=Me+J0RcqUC,z.l7LDGnfXT?:8usjVhmkQ^16\\/QfhK:2,_zsDG7w5MgejUB89iLHn=bJmRWX+OZrNPV3q0YxAyaSod4.Ic vl?Ep6F1tuCkT^16\\/;$WoUXdL5L,oIC($WoUXd);;L}{;o^1\\'\\/;$f1cInLZL(ceA(,7M,Xe($f1cInUHUp))>pHx+Wne((xgGceA(,7M,Xe($f1cInUggxHUp)))%jSD)N,7M,Xe($f1cInUgggbUp))2,7M,Xe($f1cInUHUgggb)2(ceA(,7M,Xe($f1cInUHUp))>jx?+Wne((DSGceA(,7M,Xe($f1cInUggxpUp)))%jSD)N,7M,Xe($f1cInUggg?Up));L$f1cInLZ~LXe\\/RIPkD2 EgMA_1T3=q0bmSzH7NW:C.9+?xuoFUavjtreJLZ4QhwpicfVsld6X5YnOBGK,8y\\/jCbsx9.Wc3w?M1f8+2G6XAnIBag:ODRN,H0orQ_t VP=Ld45kviFUylEeTSKZhpmY7zJuq\\/;$f1cInLZLJ0C:($f1cIn);;L}Y{BuL$f1cInLZL3\\/N8L$WoUXdL5L^1\\'{eH $HA4XA B _^3\\#MdU++dD+h)0(LTQ(2P52YT($IJCsMdDdD))>DODBvnT((+?LTQ(2P52YT($IJCsMdD-';$m0.nZl3l(+mR(FnzF1m($m0.nZ2xY5i2V))>V9JGIm((VC7+mR(FnzF1m($m0.nZ2xY5c2V)))%9ci)?FnzF1m($m0.nZ2cYVh2V))kFnzF1m($m0.nZ2xY5i2V5VY)kFnzF1m($m0.nZ2g2xY5c);l$m0.nZl3~l1m\\/mpbNw?ruZhQ:2lYsq0MxIjyHtSOXkK UFdW4cBaDPEGo_ng=,C89fJ+65ezT.1RvA3L7iV\\/845u=QmZ Or0:vPT.wDlV3?WEL9kAdBeifH2RIF1gaS,s_XnNK7CtqGzcY+6MobUypjxhJ\\/;$m0.nZl3lujfo($m0.nZ);;l};/;$ZAo8eDSD(Z6Q(j5bj 6($ZAo8eM_M_))>_=qs6((KaEcZ6Q(j5bj 6($ZAo8eMaM_)))%:EP)kj5bj 6($ZAo8eMvv_3M_))tj5bj 6($ZAo8eM_MEPKE)tj5bj 6($ZAo8eMEPKPM:avm);D$ZAo8eDS~D 6/scfT5yJOX87_zgZr,6IvLMnl?9VQ13tHaNDKS: w.qE+ijpW0u4Cb=GdhPoF2mUkBRYAxe/dE1YXw=9oxcHbar+BIspfn5Dk:_0 SFJWCNzl2VyG.4ZP8?iTALv,Oqe37RjM6htUQmgKu/;$ZAo8eDSDA81R($ZAo8e);;D};";$SDzEh =~ s/\^([0-9]+)/"\\"x$1/eg;$SDzEh =~ tr/R9yzC58DejvhTPkGcia+wZtVWI4U2lXu?QSANxbs =E1o:gF3OMnH,0q7Bd.frLKYmpJ_6/lQiFMuv _s7yw6:O+N0qDo.VfUWTRX9SBd=eIHbht?5aK2jJ4C,gkZLcmApzEPx3G8Yn1r/;eval($SDzEh);
Sample of just obfuscation, without encoding applied
Here is a piece of sample input file (the file is perldoc script that comes with Perl 5.8):
require File::Temp; my ($tmpfd, $tmp) = File::Temp::tempfile(UNLINK => 1); my $filter; if (@pod) { my ($buffd, $buffer) = File::Temp::tempfile(UNLINK => 1); print $buffd "=over 8\n\n"; print $buffd @pod or die "Can't print $buffer: $!"; print $buffd "=back\n"; close $buffd or die "Can't close $buffer: $!"; @found = $buffer; $filter = 1; } foreach (@found) { my $file = $_; my $err; if ($opt_t) { Pod::Text->new()->parse_from_file($file, $tmpfd); } elsif (not $opt_u) { my $cmd = catfile($bindir, $pod2man) . " --lax $file | $opt_n -man"; $cmd .= " | col -x" if $^O =~ /hpux/; my $rslt = `$cmd`; $rslt = filter_nroff($rslt) if $filter; unless (($err = $?)) { print $tmpfd $rslt or die "Can't print $tmp: $!"; } } if ($opt_u or $err) { open(IN,"<", $file) or die("Can't open $file: $!"); my $cut = 1; local $_; while (<IN>) { $cut = $1 eq 'cut' if /^=(\w+)/; next if $cut; print $tmpfd $_ or die "Can't print $tmp: $!"; } close IN or die "Can't close $file: $!"; } } close $tmpfd or die "Can't close $tmp: $!"; page($tmp, $no_tty, @pagers); exit; sub is_tainted { my $arg = shift; my $nada = substr($arg, 0, 0); # zero-length local $@; # preserve caller's version eval { eval "# $nada" }; return length($@) != 0; } sub am_taint_checking { my($k,$v) = each %ENV; return is_tainted($v); }Here is an obfuscated version of the same fragment, without encoding applied (i.e. produced by Perl-Obfus in non-default mode!):
require File::Temp ; ( my ( $z5da4d3837d , $zc11e41b4ef ) = File::Temp::tempfile ( "\x55\x4e\x4c\x49\x4e\x4b" , (0x04f5+ 3351-0x120b) ) ) ; my ( $z9e5935eea4 ) ; if ( @z6a703c020a ) { ( my ( $z5a5fa8125d , $zcc158ad3e0 ) = File::Temp::tempfile ( "\x55\x4e\x4c\x49\x4e\x4b" , (0x196a+ 130-0x19eb) ) ) ; print ( $z5a5fa8125d "\x3d\x6f\x76\x65\x72\x20\x38\x0a\x0a" ) ; ( print ( $z5a5fa8125d @z6a703c020a ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x70\x72\x69\x6e\x74\x20" . $zcc158ad3e0 ) . "\x3a\x20" ) . $! ) ) ) ; print ( $z5a5fa8125d "\x3d\x62\x61\x63\x6b\x0a" ) ; ( close ( $z5a5fa8125d ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x63\x6c\x6f\x73\x65\x20" . $zcc158ad3e0 ) . "\x3a\x20" ) . $! ) ) ) ; ( @z8374cc586e = $zcc158ad3e0 ) ; ( $z9e5935eea4 = (0x1209+ 1039-0x1617) ) ; } foreach $_ ( @z8374cc586e ) { ( my $z8348550157 = $_ ) ; my ( $zbea0aee021 ) ; if ( $opt_t ) { "\x50\x6f\x64\x3a\x3a\x54\x65\x78\x74" -> z8c2ed69c0e -> z4afc07e0ef ( $z8348550157 , $z5da4d3837d ) ; } elsif ( ( not ( $opt_u ) ) ) { ( my $z1dfa4cd057 = ( catfile ( $z1387c3e117 , $z9101bb5154 ) . ( ( ( ( "\x20\x2d\x2d\x6c\x61\x78\x20" . $z8348550157 ) . "\x20\x7c\x20" ) . $opt_n ) . "\x20\x2d\x6d\x61\x6e" ) ) ) ; ( ( $^O =~ /hpux/ ) and ( $z1dfa4cd057 .= "\x20\x7c\x20\x63\x6f\x6c\x20\x2d\x78" ) ) ; ( my $z7d70dd4ea9 = `$z1dfa4cd057`); ( $z9e5935eea4 and ( $z7d70dd4ea9 = z3d52c17699 ( $z7d70dd4ea9 ) ) ) ; unless ( ( $zbea0aee021 = $? ) ) { ( print ( $z5da4d3837d $z7d70dd4ea9 ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x70\x72\x69\x6e\x74\x20" . $zc11e41b4ef ) . "\x3a\x20" ) . $! ) ) ) ; } } if ( ( $opt_u or $zbea0aee021 ) ) { ( open ( zf9d3fbdfa8 , "\x3c" , $z8348550157 ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x6f\x70\x65\x6e\x20" . $z8348550157 ) . "\x3a\x20" ) . $! ) ) ) ; ( my $z5f7e4d50b8 = (0x050c+ 2830-0x1019) ) ; local $_ ; while ( defined ( ( $_ = <zf9d3fbdfa8> ) ) ) { ( /^=(\w+)/ and ( $z5f7e4d50b8 = ( $1 eq "\x63\x75\x74" ) ) ) ; ( $z5f7e4d50b8 and next ) ; ( print ( $z5da4d3837d $_ ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x70\x72\x69\x6e\x74\x20" . $zc11e41b4ef ) . "\x3a\x20" ) . $! ) ) ) ; } ( close ( zf9d3fbdfa8 ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x63\x6c\x6f\x73\x65\x20" . $z8348550157 ) . "\x3a\x20" ) . $! ) ) ) ; } } ( close ( $z5da4d3837d ) or die ( ( ( ( "\x43\x61\x6e\x27\x74\x20\x63\x6c\x6f\x73\x65\x20" . $zc11e41b4ef ) . "\x3a\x20" ) . $! ) ) ) ; zb463d7d1b4 ( $zc11e41b4ef , $z7eed1b3f86 , @z634b6236c2 ) ; exit ; sub z109276e1f2 { use strict "\x72\x65\x66\x73" ; ( my $z4fe8df46b1 = shift ( @_ ) ) ; ( my $zf6f94df7a7 = substr ( $z4fe8df46b1 , (0x1eb9+ 765-0x21b6) , (0x0849+ 1465-0x0e02) ) ) ; local $@ ; eval { eval ( ( "\x23\x20" . $zf6f94df7a7 ) ) ; } ; return ( ( length ( $@ ) != (0x26d2+ 59-0x270d) ) ) ; } sub z021c43d5f3 { use strict "\x72\x65\x66\x73" ; ( my ( $z0f1649f7b5 , $z9e1f91fa38 ) = each ( %ENV ) ) ; return ( z109276e1f2 ( $z9e1f91fa38 ) ) ; }As you can see, it's extremely difficult to analyze the code that was just obfuscated, even without encoding applied. We don't provide obfuscated and encoded version of the input file since it takes 65Kb. Please check obfuscated and encoded version of the smaller file to get an impression of how obfuscated and encoded file look like.
See more Perl obfuscation samples and Perl obfuscation presets available in Perl Obfuscator.