Brief introduction on reverse engineering Crystal binaries.
Crystal is a “new” Ruby-syntax-based programming language, born in 2014. The main diference is, that this is not a Ruby implementation, this is another compiled programming language, but its syntax is based in ruby, so Crystal != Ruby.
You can learn more about Crystal here: crystal
Any new compiled programming language results interesting from a reverse engineering perspective, malware is becoming more and more based on this kind of compiled programming language, whose syntax is easier than C or C++, but mantaining the ability to run standalone.
A Crystal Hello World example, looks like this:
puts 'Hello world!'
Yes, just like Ruby. To compile this, let’s save it as hello.cr
and execute the Crystal compiler: crystal build hello.cr
. This should create a hello
executable with the following characteristics: hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
A dinamically linked, non-stripped binary. Cool!
IDA analysis.
Let’s load this newly created binary using IDA Free 7.0 for Linux, (keep calm radare2 fanboys). Something catch my attention when load finished:
Maaaaaaan 2055 functions?!!! Calm down buddy, if you take a look at other compiled languages, like Golang, this is normal. Modern compiled languages, import everything they need to be cross-platform, so lot of functions are included in a single binary to be able to compile binaries for Windows, Linux and OSX using a single compiler.
So where’s the program itself?
By default, IDA show us to the first function basic blocks executed in the program.
Ok cool, so this function just calls another function: main_0
, which also calls another function main_user_code
And main_user_code
just calls another function __crystal_main
Let’s then analyze this __crystal_main
function, opening their basic blocks view, something really ugly happen:
… what the hell man, where the fuck is our application code? Just at the end!
There you can see the loading of our “Hello world!” string, which is at off_9A530, and a call to puts
function which seems to be a wrapper for puts_0
function, which really executes the output operation and shows our string in stdout.
Ok, so the workflow seems to be:
main
-> main_0
-> main_user_code
-> __crystal_main
and, at the end, our script code is executed.
Let’s see how conditionals and classes works at Crystal creating a simple script with the following code:
class MyHelloClass
def initialize(number=0)
@number = number
end
def test_random
if @number < 4
puts "A is lower than 4"
else
puts "A is GREATER than 4"
end
end
end
puts "Now, an if sentence will appear based on rand numeric value"
num = rand(6)
a = MyHelloClass.new(num)
a.test_random
Ok simple, let’s compile it crystal build hello2.cr
and open it using IDA, this time going directly to __crystal_main
buttom, where our code should be.
There it is, first, rand is called, which is, again a wrapper for Random::PCG32 function identified in IDA as new_98
Then, a call to new_101
is done, when inspecting this is our MyHelloClass::new
function, which is the wrapper for the initialize
function in our class. In Ruby, the initialize
function is the constructor of the class.
As you can see in this basic block, memory is created for our new object using _crystal_malloc_antomic64
function, a wrapper for GC_generic_malloc
which, after lot of operations, is a malloc itself.
Then, a call test_random
is done, remember, Crystal compiler does not strip binaries by default so function names remain intact.
Here it is our conditional, and our puts
calls on each condition. Cool!
Radare2, show us function names processed, so it’s a bit easier to identify the binary work flow with a single s sym.__crystal_main
pdf
call.
That’s all, thanks for reading, and hope this post can be helpful for someone facing this kind of binaries for the first time.
Please, feel free to contact me if you see any mistake, also my written english is not the best, so sorry for those whose eyes explode while reading this.
See you!