I figure I might as well take a stab at some more of
Erudil's code after
deciphering How to (ab)use substr. I don't in any way mean intend these spoilers to demean the work
Erudil has done. I've discovered that it's far, far easier to deconstruct than construct. I'm not even sure I could come up with the thought processes necessary to create the obfus.
Now, on to the spoiler!
Okay. Usually the first step in understanding an obfuscation is to reformat the code so it's more readable. With this example, however, we don't quite want to do that yet. There are only a couple of lines at the very end that are of interest to us at the momemt. Let's break those out.
#!/usr/bin/perl -w # my 2 cents worth
use strict;
$_='$_=tue($=+(two
($;)>>(two($;)>>2+2))){tue
(too(two(tue($=+(two($;)>>(two
($;)>>2+2))))+(two($;)>>2+2))){tue
(too(two(tue($=+(two($;)>>(two($;)>>2+
2))))+(two($;)>>2+2))-2){tue(too(two(tue
($=+(two($;)>>(two($;)>>2+2)))))){tue(too(
too(two($;)>>(two($;) >>2+2)))){tue(too($=+
+(two($;)>>2+2))){tue ((two($;)<<2)-2){tue
((two($;)<<2)-(two($; )>>2+2)){tue(too(two(
tue($=+(two($;)>>(two ($;)>>2+2)))))){{tue
(too($=+(two($;)>>2)+
(two($;)>>2+2))){{tue
(too($=+(two($;)>>2)-
2)){{{tue(too($=+(two
($;)>>(two($;)>>2+2))
-2)){tue(too(too(two(
$;)>>(two($;)>>2+2)))
){tue(too(too(too(too
(two($;)>>(two($;)>>2
+2)))))){{tue(too($=+
(two($;)>>2)-2))}tue(
too($=+(two($;)>>(two
($;)>>2+2))-2)){tue((
two($;)<<2)-((two($;)
>>2>>2)<<2))}tue(too(
too(two($;)>>(two($;)
>>2+2))))}}tue(too($=
+(two($;)>>2)+(two($;)>>2+2)))}}tue(too($=+(
two($;)>>2+2)))}}tue(too((two($;)<<(two($;)>>
2>>2))+(two($;)>>2)))}}}tue((two($;)<<2)-((two
($;)>>2>>2)<<2)-(two($;)>>2>>2))}}}tue(too($=+(
two($;)>>2)-2))}}}tue(too($=+(two($;)>>(two($;)
>>2+2))-2))}}}tue(too(too(two($;)>>(two($;)>>2+
2)))+(two($;)>>(two($;)>>2+2))-2);';
y;{};..;sd;
s;two;ord;g;
s;too;hex;g;
s;tue;chr;g;
eval;
print;
We can pull these lines out because if you look closely, you'll see that everything else after the
use strict; to the
y is an assignment to
$_, and is essentially one line. The extracted lines may look a bit strange at first, but remember that Perl lets you use other delimeters in regular expressions. The last few lines can be easily rewritten as this:
y/{}/../sd;
s/two/ord/g;
s/too/hex/g;
s/tue/chr/g;
Now, we apply the
y to translate all of the braces to periods. This is why we didn't want to format the code right off the bat - it wouldn't make much sense and gets messy quickly. After translation, we essesntially have:
$_='$_=tue($=+(two
($;)>>(two($;)>>2+2))).tue
(too(two(tue($=+(two($;)>>(two
($;)>>2+2))))+(two($;)>>2+2))).tue
(too(two(tue($=+(two($;)>>(two($;)>>2+
2))))+(two($;)>>2+2))-2).tue(too(two(tue
($=+(two($;)>>(two($;)>>2+2)))))).tue(too(
too(two($;)>>(two($;) >>2+2)))).tue(too($=+
+(two($;)>>2+2))).tue ((two($;)<<2)-2).tue
((two($;)<<2)-(two($; )>>2+2)).tue(too(two(
tue($=+(two($;)>>(two ($;)>>2+2)))))).tue
(too($=+(two($;)>>2)+
(two($;)>>2+2))).tue
(too($=+(two($;)>>2)-
2)).tue(too($=+(two
($;)>>(two($;)>>2+2))
-2)).tue(too(too(two(
$;)>>(two($;)>>2+2)))
).tue(too(too(too(too
(two($;)>>(two($;)>>2
+2)))))).tue(too($=+
(two($;)>>2)-2)).tue(
too($=+(two($;)>>(two
($;)>>2+2))-2)).tue((
two($;)<<2)-((two($;)
>>2>>2)<<2)).tue(too(
too(two($;)>>(two($;)
>>2+2)))).tue(too($=
+(two($;)>>2)+(two($;)>>2+2))).tue(too($=+(
two($;)>>2+2))).tue(too((two($;)<<(two($;)>>
2>>2))+(two($;)>>2))).tue((two($;)<<2)-((two
($;)>>2>>2)<<2)-(two($;)>>2>>2)).tue(too($=+(
two($;)>>2)-2)).tue(too($=+(two($;)>>(two($;)
>>2+2))-2)).tue(too(too(two($;)>>(two($;)>>2+
2)))+(two($;)>>(two($;)>>2+2))-2);';
s/two/ord/g;
s/too/hex/g;
s/tue/chr/g;
eval;
print;
Next, we apply the
s/// statements. This is where most of the trickery of this obfuscation comes in to play. I'm sure a lot of people (myself included) looked at this the first time wondering where the heck the subs
two,
tue, and
too were declared. Turns out they're just placeholders for
ord,
chr, and
hex. The next step's result is:
$_='$_=chr($=+(ord
($;)>>(ord($;)>>2+2))).chr
(hex(ord(chr($=+(ord($;)>>(ord
($;)>>2+2))))+(ord($;)>>2+2))).chr
(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+
2))))+(ord($;)>>2+2))-2).chr(hex(ord(chr
($=+(ord($;)>>(ord($;)>>2+2)))))).chr(hex(
hex(ord($;)>>(ord($;) >>2+2)))).chr(hex($=+
+(ord($;)>>2+2))).chr ((ord($;)<<2)-2).chr
((ord($;)<<2)-(ord($; )>>2+2)).chr(hex(ord(
chr($=+(ord($;)>>(ord ($;)>>2+2)))))).chr
(hex($=+(ord($;)>>2)+
(ord($;)>>2+2))).chr
(hex($=+(ord($;)>>2)-
2)).chr(hex($=+(ord
($;)>>(ord($;)>>2+2))
-2)).chr(hex(hex(ord(
$;)>>(ord($;)>>2+2)))
).chr(hex(hex(hex(hex
(ord($;)>>(ord($;)>>2
+2)))))).chr(hex($=+
(ord($;)>>2)-2)).chr(
hex($=+(ord($;)>>(ord
($;)>>2+2))-2)).chr((
ord($;)<<2)-((ord($;)
>>2>>2)<<2)).chr(hex(
hex(ord($;)>>(ord($;)
>>2+2)))).chr(hex($=
+(ord($;)>>2)+(ord($;)>>2+2))).chr(hex($=+(
ord($;)>>2+2))).chr(hex((ord($;)<<(ord($;)>>
2>>2))+(ord($;)>>2))).chr((ord($;)<<2)-((ord
($;)>>2>>2)<<2)-(ord($;)>>2>>2)).chr(hex($=+(
ord($;)>>2)-2)).chr(hex($=+(ord($;)>>(ord($;)
>>2+2))-2)).chr(hex(hex(ord($;)>>(ord($;)>>2+
2)))+(ord($;)>>(ord($;)>>2+2))-2);';
eval;
print;
If you look at the first line,
$_ is being assigned a string that starts with
"$_=".
$_ is then
eval'ed, which results in
$_ being assigned the value of the string. It's almost recursive. It is also easy to remove without affecting the operation of the script.
$_=chr($=+(ord
($;)>>(ord($;)>>2+2))).chr
(hex(ord(chr($=+(ord($;)>>(ord
($;)>>2+2))))+(ord($;)>>2+2))).chr
(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+
2))))+(ord($;)>>2+2))-2).chr(hex(ord(chr
($=+(ord($;)>>(ord($;)>>2+2)))))).chr(hex(
hex(ord($;)>>(ord($;) >>2+2)))).chr(hex($=+
+(ord($;)>>2+2))).chr ((ord($;)<<2)-2).chr
((ord($;)<<2)-(ord($; )>>2+2)).chr(hex(ord(
chr($=+(ord($;)>>(ord ($;)>>2+2)))))).chr
(hex($=+(ord($;)>>2)+
(ord($;)>>2+2))).chr
(hex($=+(ord($;)>>2)-
2)).chr(hex($=+(ord
($;)>>(ord($;)>>2+2))
-2)).chr(hex(hex(ord(
$;)>>(ord($;)>>2+2)))
).chr(hex(hex(hex(hex
(ord($;)>>(ord($;)>>2
+2)))))).chr(hex($=+
(ord($;)>>2)-2)).chr(
hex($=+(ord($;)>>(ord
($;)>>2+2))-2)).chr((
ord($;)<<2)-((ord($;)
>>2>>2)<<2)).chr(hex(
hex(ord($;)>>(ord($;)
>>2+2)))).chr(hex($=
+(ord($;)>>2)+(ord($;)>>2+2))).chr(hex($=+(
ord($;)>>2+2))).chr(hex((ord($;)<<(ord($;)>>
2>>2))+(ord($;)>>2))).chr((ord($;)<<2)-((ord
($;)>>2>>2)<<2)-(ord($;)>>2>>2)).chr(hex($=+(
ord($;)>>2)-2)).chr(hex($=+(ord($;)>>(ord($;)
>>2+2))-2)).chr(hex(hex(ord($;)>>(ord($;)>>2+
2)))+(ord($;)>>(ord($;)>>2+2))-2);
print;
Now we can start applying some formatting to make it manageable. Let's break each line on a period because that will make the most sense as we progress.
$_= chr($=+(ord($;)>>(ord($;)>>2+2))).
chr(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+2))))+(ord($;)>>2+2))).
chr(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+2))))+(ord($;)>>2+2))-2).
chr(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+2)))))).
chr(hex(hex(ord($;)>>(ord($;)>>2+2)))).
chr(hex($=+ +(ord($;)>>2+2))).
chr((ord($;)<<2)-2).
chr((ord($;)<<2)-(ord($;)>>2+2)).
chr(hex(ord(chr($=+(ord($;)>>(ord($;)>>2+2)))))).
chr(hex($=+(ord($;)>>2)+(ord($;)>>2+2))).
chr(hex($=+(ord($;)>>2)-2)).
chr(hex($=+(ord($;)>>(ord($;)>>2+2))-2)).
chr(hex(hex(ord($;)>>(ord($;)>>2+2)))).
chr(hex(hex(hex(hex(ord($;)>>(ord($;)>>2+2)))))).
chr(hex($=+(ord($;)>>2)-2)).
chr(hex($=+(ord($;)>>(ord($;)>>2+2))-2)).
chr((ord($;)<<2)-((ord($;)>>2>>2)<<2)).
chr(hex(hex(ord($;)>>(ord($;)>>2+2)))).
chr(hex($=+(ord($;)>>2)+(ord($;)>>2+2))).
chr(hex($=+(ord($;)>>2+2))).
chr(hex((ord($;)<<(ord($;)>>2>>2))+(ord($;)>>2))).
chr((ord($;)<<2)-((ord($;)>>2>>2)<<2)-(ord($;)>>2>>2)).
chr(hex($=+(ord($;)>>2)-2)).
chr(hex($=+(ord($;)>>(ord($;)>>2+2))-2)).
chr(hex(hex(ord($;)>>(ord($;)>>2+2)))+(ord($;)>>(ord($;)>>2+2))-2)
+;
print;
Now we can start simplifying these lines. The first step is to remove the Perl special characters.
$; is the subscript separator for multi dimension arrays. Its default is '\034', which is the decimal value 28.
$= is the number of lines per page as used in formats. It defaults to 60. Therefore, we can replace
ord($;) with 28, and
$= with 60.
$_= chr(60+(28>>(28>>2+2))).
chr(hex(ord(chr(60+(28>>(28>>2+2))))+(28>>2+2))).
chr(hex(ord(chr(60+(28>>(28>>2+2))))+(28>>2+2))-2).
chr(hex(ord(chr(60+(28>>(28>>2+2)))))).
chr(hex(hex(28>>(28>>2+2)))).
chr(hex(60+ +(28>>2+2))).
chr((28<<2)-2).
chr((28<<2)-(28>>2+2)).
chr(hex(ord(chr(60+(28>>(28>>2+2)))))).
chr(hex(60+(28>>2)+(28>>2+2))).
chr(hex(60+(28>>2)-2)).
chr(hex(60+(28>>(28>>2+2))-2)).
chr(hex(hex(28>>(28>>2+2)))).
chr(hex(hex(hex(hex(28>>(28>>2+2)))))).
chr(hex(60+(28>>2)-2)).
chr(hex(60+(28>>(28>>2+2))-2)).
chr((28<<2)-((28>>2>>2)<<2)).
chr(hex(hex(28>>(28>>2+2)))).
chr(hex(60+(28>>2)+(28>>2+2))).
chr(hex(60+(28>>2+2))).
chr(hex((28<<(28>>2>>2))+(28>>2))).
chr((28<<2)-((28>>2>>2)<<2)-(28>>2>>2)).
chr(hex(60+(28>>2)-2)).
chr(hex(60+(28>>(28>>2+2))-2)).
chr(hex(hex(28>>(28>>2+2)))+(28>>(28>>2+2))-2);
print;
Now it's starting to become more manageable. The next step is to get rid of those bit shift operations. At this point, there are basically four different operations that we can replace with their values.
28>>2+2 evaluates to 1.
28<<2 equals 112,
28>>2>>2 is 1, and
28>>2 is 7. Let's make these substitutions.
$_= chr(60+(28>>(1))).
chr(hex(ord(chr(60+(28>>(1))))+(1))).
chr(hex(ord(chr(60+(28>>(1))))+(1))-2).
chr(hex(ord(chr(60+(28>>(1)))))).
chr(hex(hex(28>>(1)))).
chr(hex(60+ +(1))).
chr((112)-2).
chr((112)-(1)).
chr(hex(ord(chr(60+(28>>(1)))))).
chr(hex(60+(7)+(1))).
chr(hex(60+(7)-2)).
chr(hex(60+(28>>(1))-2)).
chr(hex(hex(28>>(1)))).
chr(hex(hex(hex(hex(28>>(1)))))).
chr(hex(60+(7)-2)).
chr(hex(60+(28>>(1))-2)).
chr((112)-((1)<<2)).
chr(hex(hex(28>>(1)))).
chr(hex(60+(7)+(1))).
chr(hex(60+(1))).
chr(hex((28<<(1))+(7))).
chr((112)-((1)<<2)-(1)).
chr(hex(60+(7)-2)).
chr(hex(60+(28>>(1))-2)).
chr(hex(hex(28>>(1)))+(28>>(1))-2);
print;
Now, we can make the substitutions of
28>>1 = 14 ,
28<<1 = 56, and
1<<2 = 4, and clean up extra parens.
$_= chr(60+14).
chr(hex(ord(chr(60+14))+1)).
chr(hex(ord(chr(60+14))+1)-2).
chr(hex(ord(chr(60+14)))).
chr(hex(hex(14))).
chr(hex(60+ +1)).
chr(112-2).
chr(112-1).
chr(hex(ord(chr(60+14)))).
chr(hex(60+7+1)).
chr(hex(60+7-2)).
chr(hex(60+14-2)).
chr(hex(hex(14))).
chr(hex(hex(hex(hex(14))))).
chr(hex(60+7-2)).
chr(hex(60+14-2)).
chr(112-4).
chr(hex(hex(14))).
chr(hex(60+7+1)).
chr(hex(60+1)).
chr(hex(56+7)).
chr(112-4-1).
chr(hex(60+7-2)).
chr(hex(60+14-2)).
chr(hex(hex(14))+14-2);
print;
Now we can do some arithmetic simplification, and a little more cleanup. There are several places where
ord(chr(X)) shows up in the script. If you think about what
ord() and
chr() do, it's obvious that
ord(chr(X)) = X, so we can simplify those statements quite a bit.
$_= chr(74).
chr(hex(75)).
chr(hex(75)-2).
chr(hex(74)).
chr(hex(hex(14)).
chr(hex(61)).
chr(110).
chr(111).
chr(hex(74)).
chr(hex(68)).
chr(hex(65)).
chr(hex(72)).
chr(hex(hex(14))).
chr(hex(hex(hex(hex(14))))).
chr(hex(65)).
chr(hex(72)).
chr(108).
chr(hex(hex(14))).
chr(hex(68)).
chr(hex(61)).
chr(hex(63)).
chr(107).
chr(hex(65)).
chr(hex(72)).
chr(hex(hex(14))+12);
print;
It should be pretty easy to get the solution now, but I'll make it a little easier to get you started.
$_= 'J'.
chr(hex(75)).
chr(hex(75)-2).
chr(hex(74)).
chr(hex(hex(14)).
chr(hex(61)).
'n'.
'o'.
chr(hex(74)).
chr(hex(68)).
chr(hex(65)).
chr(hex(72)).
chr(hex(hex(14))).
chr(hex(hex(hex(hex(14))))).
chr(hex(65)).
chr(hex(72)).
'l'.
chr(hex(hex(14))).
chr(hex(68)).
chr(hex(61)).
chr(hex(63)).
'k'.
chr(hex(65)).
chr(hex(72)).
chr(hex(hex(14))+12);
print;
GuildensternNegaterd character class uber alles!
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.