Weird ruby codes
A bit of Friday fun. Ruby is a very natural programming language, with a beautiful and intuitive syntax. But is it (always)?
I came across the following code from the 2018 TRICK competition recently:
'';eval(r=%q(->z{r="'';eval(r=\
%q(#{r}))[%q`#{z}`]";i=-040;30.
times{|n|(15+n%2*15-n/2).times{
r<<r[i+=(1.-n&2)*(32-n%2*31)]}}
i=r[524,0]=?\0;eval(r[479..-1])
c['"']}))[%q`GFEDCBA"+"[e\"'"'t
kE*;;\";" TRICK2018 ";tb,;{{r
2E0$ob[us@*0)[90,336])_#i\n}s#i
0H}>["t]];};o[1,?\n*8];ex"-}eac
1Hl<1[-1]*2*t=n%2];o[14-n,0)mvk
8M$<4,?\n];15.times{|n|;o[35ie2
!Pss.slice!(0,1)+x;sleep(0.0t;0
'W=%q"<<95<<$s<<95;o=->n,x{n.'1
;@[2]}|\e../,%@s="'%trick2018!8
eval$s=%q_eval($s.gsub!(/#{%@`]
The code is impossible to read and quite amazing in what it does. It re-print itself in as a spiral. I thought it was quite fun, so I started to look a bit more into it.
Re-print itself
Having a ruby code that re-print itself is quite easy. There are many ways to do it, but it could be as simple as:
eval s="puts 'eval s='+s.inspect"
However, the code is quite obvious in what it does.
Hide eval
So I started thinking, how can I obfuscate the “eval” in the code? One of the uncommon (for good reason) way to represent a string literal in ruby is to use:
?e
=> "e"
So you can represent “eval” as an array of strings: [?e, ?v, ?a, ?l].join
You can then invoke “eval” with send
:
send([?e, ?v, ?a, ?l].join, s="puts 'eval s='+s.inspect")
You can replace .join
by *''
on the array.
Scramble
However, it’s still quite obvious. Maybe I can scramble the letters?
{d:?l,c:?a,a:?e,b:?v}.sort.map(&:last)
is a lot less obvious. Still, if you’re good at anagrams, you’ll figure it out.
{g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)
is quite a bit more confusing.
You can then do something like:
send(s={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*'', s="puts 'eval s='+s.inspect")
Obfuscate
Or replace s
by _
(a valid variable name in ruby):
send(_={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*'', _="puts 'eval _='+_.inspect")
Of course the string "puts 'eval _='+_.inspect"
can be replaced by %(puts 'eval _='+_.inspect)
.
You can then reuse _
:
_={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*'';send(_, _=%(puts '#{_} _='+_.inspect))
Encode
You could also encode "puts 'eval _='+_.inspect"
as "cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0"
in Base64:
_={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*''
send(_, _=%(cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0).unpack('m')[0])
Here I also replaced %(cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0)
by %.cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0.
and used .unpack(?m)[-1]
to decode:
_={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*''
send(_, _=%.cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0..unpack(?m)[-1])
Finally
All the non-base-64 characters are ignored by unpack
, so you can replace %.cHV0cyAnZXZhbCBfPScrXy5pbnNwZWN0.
by %.cHV0c#"yAnZ%XZh bC-BfP_Scr"@Xy5p%bnN|wZWN_0.
for example.
_={g:?a,d:?v,m:?l,b:?d,c:?e}.sort[1..-1].map(&:last)*''
send(_, _=%.cHV0c#"yAnZ%XZh bC-BfP_Scr"
@Xy5p%bnN|wZWN_0..unpack(?m)[-1])
Not so natural, beautiful or intuitive anymore…
What is it useful for? Probably nothing, but it’s fun!
And the winner is
By the way here is the winner of a 2018 TRICK competition:
alias BEGIN for unless def class
super true or return defined? next
break while begin undef do end
rescue then retry else undef module
nil ensure case if yield __LINE__
self and redo elsif not __FILE__
alias END in end when __ENCODING__
end until false end
The code doesn’t do anything, but is valid ruby!