note
Guildenstern
<b>Update:</b> *sigh* Apparently, the READMORE tag has some issues. My apologies to all for the long post.<br><br>Well, this is the first obfu from [Erudil] that I was able to decipher, so I thought I'd break it down and write the spoiler.<br><br>
<READMORE>
<br><code>
#!/usr/bin/perl -w # how to (ab)use substr
use strict;
my $pi='3.14159210535152623346475240375062163750446240333543375062';
substr ($^X,0)=
substr ($pi,-6);map{
substr ($^X,$.++,1)=chr(
substr($pi,21,2)+
substr($pi,$_,2))}(12,28,-18,-6,-10,14);map{$^O=$"x(
substr ($pi,-5,2));
substr ($^O,sin(++$a/8)*32+
substr ($pi,-2)/2+1,1)=$_;
substr ($^O,sin($a/4)*(
substr ($pi,2,2))+
substr ($pi,-7,-5)-1,1)=$_;print"$^O$/";eval($^X.('$b,'x3).
substr ($pi,-3,1).'.'.
substr ($pi,9,2));}(map{chr($_+
substr ($pi,21,2))}(
substr ($pi,8)x3)=~/../g);
</code><br><br>
Let's clean up the formatting a bit first:
<br><br><code>
substr($^X,0)=substr($pi,-6);
map{
substr($^X,$.++,1)=chr(
substr($pi,21,2)+
substr($pi,$_,2))
}(12,28,-18,-6,-10,14);
map{
$^O=$"x(substr ($pi,-5,2));
substr($^O,sin(++$a/8)*32+
substr($pi,-2)/2+1,1)=$_;
substr($^O,sin($a/4)*(
substr($pi,2,2))+
substr($pi,-7,-5)-1,1)=$_;
print"$^O$/";
eval($^X.('$b,'x3).
substr($pi,-3,1).'.'.
substr($pi,9,2));
}(map{
chr($_+
substr($pi,21,2))
}(substr($pi,8)x3)=~/../g);
</code><br><br>
Let's remove some of the pesky <code>map</code>s
<br><br><code>
substr($^X,0)=substr($pi,-6);
foreach (12,28,-18,-6,-10,14)
{
substr($^X,$.++,1)=chr(
substr($pi,21,2)+
substr($pi,$_,2));
}
# We need this for the moment to get
# rid of the second map below.
# Don't worry, it goes away.
my @tempa;
foreach (substr($pi,8)x3)=~/../g)
{
push(@tempa,chr($_+substr($pi,21,2)));
}
map{
$^O=$"x(substr ($pi,-5,2));
substr($^O,sin(++$a/8)*32+
substr($pi,-2)/2+1,1)=$_;
substr($^O,sin($a/4)*(
substr($pi,2,2))+
substr($pi,-7,-5)-1,1)=$_;
print"$^O$/";
eval($^X.('$b,'x3).
substr($pi,-3,1).'.'.
substr($pi,9,2));
}(@tempa);
</code><br><br>
Now, most of the <code>substr($pi,....)</code> statements return the same value each time. Let's just replace those statements with their values.
<br><br><code>
substr($^X,0)=375062;
foreach (12,28,-18,-6,-10,14)
{
substr($^X,$.++,1)=chr(
64+
substr($pi,$_,2));
}
# We need this for the moment to get
# rid of the second map below.
# Don't worry, it goes away.
my @tempa;
foreach (substr($pi,8)x3)=~/../g)
{
push(@tempa,chr($_+64));
}
map{
$^O=$"x(75);
substr($^O,sin(++$a/8)*32+
62/2+1,1)=$_;
substr($^O,sin($a/4)*(
14)+
33-1,1)=$_;
print"$^O$/";
eval($^X.('$b,'x3).
0.'.'.
05);
}(@tempa);
</code><br><br>
If we look at the first <code>foreach</code>, we can see that we are replacing the numerical values of <code>$^X</code> with character values, one by one. The resulting value of <code>$^X</code> is 'select', so we can eliminate the first <code>foreach</code> entirely (and do some more tidying).<br><br><code>
$^X="select";
# We need this for the moment to get
# rid of the second map below.
# Don't worry, it goes away.
my @tempa;
foreach (substr($pi,8)x3)=~/../g)
{
push(@tempa,chr($_+64));
}
map{
$^O=$"x75;
substr($^O,sin(++$a/8)*32+32,1)=$_;
substr($^O,sin($a/4)*14+32,1)=$_;
print"$^O$/";
eval($^X.('$b,'x3).'0.05');
}(@tempa);
</code><br><br>
Now, we can finally get rid of that last pesky <code>map</code> statement.
<br><br><code>
$^X="select";
foreach (substr($pi,8)x3)=~/../g)
{
$_ = chr($_+64);
$^O=$"x75;
substr($^O,sin(++$a/8)*32+32,1)=$_;
substr($^O,sin($a/4)*14+32,1)=$_;
print"$^O$/";
eval($^X.('$b,'x3).'0.05');
}
</code><br><br>
Just for the sake of simplification, let's remove that <code>eval</code> statement as well, since it's really a <code>select</code>.
<br><br><code>
foreach (substr($pi,8)x3)=~/../g)
{
$_ = chr($_+64);
$^O=$"x75;
substr($^O,sin(++$a/8)*32+32,1)=$_;
substr($^O,sin($a/4)*14+32,1)=$_;
print"$^O$/";
select $b,$b,$b,0.05;
}
</code><br><br>
Now it's fairly simple to tell what's going on. To make it even easier to see, let's replace the expression in the <code>foreach</code>. The combination of <code>substr($pi,8)x3=~/../g</code> and the <code>$_ = chr($_+64)</code> results in the string "Just~another~Perl~hacker~" repeated three times. Let's just add that to the <code>foreach</code> and clean up a bit more.
<br><br><code>
foreach (("Just~another~Perl~hacker~"x3)=~/./g)
{
$^O=$"x75;
substr($^O,sin(++$a/8)*32+32,1)=$_;
substr($^O,sin($a/4)*14+32,1)=$_;
print"$^O$/";
select $b,$b,$b,0.05;
}
</code><br><br>
That's about all we can do. From here, it should be fairly simple to divine what's happening. <code>$^O</code> gets set to 75 spaces. Then, the position of the next characters are determined by the <code>sin</code> function and placed into <code>$^O</code> with the <code>substr</code>. <code>$^O</code> is then printed followed by the local line-break character. The script then sleeps for 5 ms before printing the next line.<br><br>
I hope I gave a good explanation. I know I skipped over several steps, but it should be apparent from step to step what I've changed. Anything that didn't change I didn't include from the original script. Yes <code>$pi</code> was tampered with, but I'd only expect PM users to notice that it's only good to the first 5 digits. :)<br><br><a href="/index.pl?node=Guildenstern">Guildenstern</a><br><em>Negaterd character class uber alles!</em>
77619
77619