Hackvent 2019: Day 14
Challenge
HV19.14 Achtung das Flag
Introduction
Let's play another little game this year. Once again, I promise it is hardly obfuscated.
Resources:
use Tk;use MIME::Base64;chomp(($a,$a,$b,$c,$f,$u,$z,$y,$r,$r,$u)=<DATA>);sub M{$M=shift;##
@m=keys %::;(grep{(unpack("%32W*",$_).length($_))eq$M}@m)[0]};$zvYPxUpXMSsw=0x1337C0DE;###
/_help_me_/;$PMMtQJOcHm8eFQfdsdNAS20=sub{$zvYPxUpXMSsw=($zvYPxUpXMSsw*16807)&0xFFFFFFFF;};
($a1Ivn0ECw49I5I0oE0='07&3-"11*/(')=~y$!-=$`-~$;($Sk61A7pO='K&:P3&44')=~y$!-=$`-~$;m/Mm/g;
($sk6i47pO='K&:R&-&"4&')=~y$!-=$`-~$;;;;$d28Vt03MEbdY0=sub{pack('n',$fff[$S9cXJIGB0BWce++]
^($PMMtQJOcHm8eFQfdsdNAS20->()&0xDEAD));};'42';($vgOjwRk4wIo7_=MainWindow->new)->title($r)
;($vMnyQdAkfgIIik=$vgOjwRk4wIo7_->Canvas("-$a"=>640,"-$b"=>480,"-$u"=>$f))->pack;@p=(42,42
);$cqI=$vMnyQdAkfgIIik->createLine(@p,@p,"-$y"=>$c,"-$a"=>3);;;$S9cXJIGB0BWce=0;$_2kY10=0;
$_8NZQooI5K4b=0;$Sk6lA7p0=0;$MMM__;$_=M(120812).'/'.M(191323).M(133418).M(98813).M(121913)
.M(134214).M(101213).'/'.M(97312).M(6328).M(2853).'+'.M(4386);s|_||gi;@fff=map{unpack('n',
$::{M(122413)}->($_))}m:...:g;($T=sub{$vMnyQdAkfgIIik->delete($t);$t=$vMnyQdAkfgIIik->#FOO
createText($PMMtQJOcHm8eFQfdsdNAS20->()%600+20,$PMMtQJOcHm8eFQfdsdNAS20->()%440+20,#Perl!!
"-text"=>$d28Vt03MEbdY0->(),"-$y"=>$z);})->();$HACK;$i=$vMnyQdAkfgIIik->repeat(25,sub{$_=(
$_8NZQooI5K4b+=0.1*$Sk6lA7p0);;$p[0]+=3.0*cos;$p[1]-=3*sin;;($p[0]>1&&$p[1]>1&&$p[0]<639&&
$p[1]<479)||$i->cancel();00;$q=($vMnyQdAkfgIIik->find($a1Ivn0ECw49I5I0oE0,$p[0]-1,$p[1]-1,
$p[0]+1,$p[1]+1)||[])->[0];$q==$t&&$T->();$vMnyQdAkfgIIik->insert($cqI,'end',\@p);($q==###
$cqI||$S9cXJIGB0BWce>44)&&$i->cancel();});$KE=5;$vgOjwRk4wIo7_->bind("<$Sk61A7pO-n>"=>sub{
$Sk6lA7p0=1;});$vgOjwRk4wIo7_->bind("<$Sk61A7pO-m>"=>sub{$Sk6lA7p0=-1;});$vgOjwRk4wIo7_#%"
->bind("<$sk6i47pO-n>"=>sub{$Sk6lA7p0=0 if$Sk6lA7p0>0;});$vgOjwRk4wIo7_->bind("<$sk6i47pO"
."-m>"=>sub{$Sk6lA7p0=0 if $Sk6lA7p0<0;});$::{M(7998)}->();$M_decrypt=sub{'HACKVENT2019'};
__DATA__
The cake is a lie!
width
height
orange
black
green
cyan
fill
Only perl can parse Perl!
Achtung das Flag! --> Use N and M
background
M'); DROP TABLE flags; --
Run me in Perl!
__DATA__
Solution
We are provided with some Perl code so we decide to run it. We realise we need the Tk module which seems to be some GUI library for Perl.
After running the code we are presented with a game which allows us to control the direction of a line with the letters N and M. We also see letters on the screen which look like parts of the flag!
So we start playing this game for fun but realise its very difficult to win the game ends when we hit the line or borders. Therefore, we give ourselves god mode by replacing $i->cancel();
with 1
. However, even if we cheat at the game there are just too many characters and it all gets too messy so we don't peruse this avenue any further:
Instead, we try to manually deobfuscate the Perl code. We don't need to deobfuscate the whole program, only the parts that spit the cyan coloured text.
Before we do this we use PerlTidy to clean up our code a little.
We follow the word cyan in the __DATA__ segment which we discover is tied to the $z
variable. In the call to createText
, we see that $d28Vt03MEbdY0
is variable holding the code reference with the flag text components. We'll use built in B::Deparse
to deparse this. However, it seems like the code actually mutates data so we cannot simply evaluate $d28Vt03MEbdY0
code twice. Therefore, we replace it with an empty string in the actual text to be displayed and print the text to the console instead. We also replace $q==$t&&$T->()
with $T->()
to ensure that the next component is displayed each frame regardless of any checks (i.e. interception check). Finally, we change the FPS in the repeat loop to 1
so the program executes and ends quickly.
Our new code looks like this (with new lines marked with a # new
comment):
use Tk;
use MIME::Base64;
use B::Deparse (); # new
my $deparse = B::Deparse->new; # new
chomp( ( $a, $a, $b, $c, $f, $u, $z, $y, $r, $r, $u ) = <DATA> );
sub M {
$M = shift; ##
@m = keys %::;
( grep { ( unpack( "%32W*", $_ ) . length($_) ) eq $M } @m )[0];
}
$zvYPxUpXMSsw = 0x1337C0DE; ###
/_help_me_/;
$PMMtQJOcHm8eFQfdsdNAS20 =
sub { $zvYPxUpXMSsw = ( $zvYPxUpXMSsw * 16807 ) & 0xFFFFFFFF; };
( $a1Ivn0ECw49I5I0oE0 = '07&3-"11*/(' ) =~ y$!-=$`-~$;
( $Sk61A7pO = 'K&:P3&44' ) =~ y$!-=$`-~$;
m/Mm/g;
( $sk6i47pO = 'K&:R&-&"4&' ) =~ y$!-=$`-~$;
$d28Vt03MEbdY0 = sub {
pack( 'n',
$fff[ $S9cXJIGB0BWce++ ] ^ ( $PMMtQJOcHm8eFQfdsdNAS20->() & 0xDEAD ) );
};
'42';
( $vgOjwRk4wIo7_ = MainWindow->new )->title($r);
( $vMnyQdAkfgIIik =
$vgOjwRk4wIo7_->Canvas( "-$a" => 640, "-$b" => 480, "-$u" => $f ) )->pack;
@p = ( 42, 42 );
$cqI = $vMnyQdAkfgIIik->createLine( @p, @p, "-$y" => $c, "-$a" => 3 );
$S9cXJIGB0BWce = 0;
$_2kY10 = 0;
$_8NZQooI5K4b = 0;
$Sk6lA7p0 = 0;
$MMM__;
$_ =
M(120812) . '/'
. M(191323)
. M(133418)
. M(98813)
. M(121913)
. M(134214)
. M(101213) . '/'
. M(97312)
. M(6328)
. M(2853) . '+'
. M(4386);
s|_||gi;
@fff = map { unpack( 'n', $::{ M(122413) }->($_) ) } m:...:g;
(
$T = sub {
$vMnyQdAkfgIIik->delete($t);
$t = $vMnyQdAkfgIIik-> #FOO
createText(
$PMMtQJOcHm8eFQfdsdNAS20->() % 600 + 20,
$PMMtQJOcHm8eFQfdsdNAS20->() % 440 + 20, #Perl!!
"-text" => "", # new
"-$y" => $z
);
print eval( $deparse->coderef2text($d28Vt03MEbdY0) ); # new
}
)->();
$HACK;
$i = $vMnyQdAkfgIIik->repeat(
1, # new
sub {
$_ = ( $_8NZQooI5K4b += 0.1 * $Sk6lA7p0 );
$p[0] += 3.0 * cos;
$p[1] -= 3 * sin;
( $p[0] > 1 && $p[1] > 1 && $p[0] < 639 && $p[1] < 479 )
|| $i->cancel();
00;
$q = (
$vMnyQdAkfgIIik->find(
$a1Ivn0ECw49I5I0oE0,
$p[0] - 1,
$p[1] - 1,
$p[0] + 1,
$p[1] + 1
)
|| []
)->[0];
$T->(); # new
$vMnyQdAkfgIIik->insert( $cqI, 'end', \@p );
(
$q == ###
$cqI || $S9cXJIGB0BWce > 44
) && $i->cancel();
}
);
$KE = 5;
$vgOjwRk4wIo7_->bind(
"<$Sk61A7pO-n>" => sub {
$Sk6lA7p0 = 1;
}
);
$vgOjwRk4wIo7_->bind( "<$Sk61A7pO-m>" => sub { $Sk6lA7p0 = -1; } );
$vgOjwRk4wIo7_ #%"
->bind( "<$sk6i47pO-n>" => sub { $Sk6lA7p0 = 0 if $Sk6lA7p0 > 0; } );
$vgOjwRk4wIo7_->bind(
"<$sk6i47pO" . "-m>" => sub { $Sk6lA7p0 = 0 if $Sk6lA7p0 < 0; } );
$::{ M(7998) }->();
$M_decrypt = sub { 'HACKVENT2019' };
__DATA__
The cake is a lie!
width
height
orange
black
green
cyan
fill
Only perl can parse Perl!
Achtung das Flag! --> Use N and M
background
M'); DROP TABLE flags; --
Run me in Perl!
__DATA__
We run the Perl program again and it prints out an interesting but working flag!
PS C:\Users\Mo\Desktop> perl .\day14.pl.tdy
HV19{s@@jSfx4gPcvtiwxPCagrtQ@,y^p-za-oPQ^a-z\x20\n^&&s[(.)(..)][\2\1]g;s%4(...)%"p$1t"%ee}
Flag:
HV19{s@@jSfx4gPcvtiwxPCagrtQ@,y^p-za-oPQ^a-z\x20\n^&&s[(.)(..)][\2\1]g;s%4(...)%"p$1t"%ee}
Bonus
This challenge also contained the solution to HV19.H4 Hidden Four.