SANS Holiday Hack Challenge 2021: Yara rule analysis walkthrough
Over the Christmas break I took part in an annual tradition - the SANS Holiday Hack Challenge! For 2021 the team had put together a fresh set of challenges for this festive CTF, and now that the deadline for submissions and subsequent embargo has passed, I thought I’d share a write-up of a challenge that appeared - from the in-game chat window at least - to catch a few people out.
This challenge is all about Yara rules, which detect malware based on a series of conditions set out in a rule file. As set out in the screenshot below, Santa’s elves are having problems running an application that measures the sweetness levels of the candy they’re manufacturing. It’s heavily hinted that it’s being blocked because it’s matching a Yara rule, and that we might be able to change the program to bypass it.
To start, let’s try running the app using ./the_critical_elf_app
to see what we get…
What exactly are we seeing here? Well, our app has been blocked from executing because it has matched a Yara rule - rule_135
, to be precise. To get around this rule-based protection we have two options:
- Change the Yara rule so that it no longer matches on the program
- Change the program so that it no longer matches the Yara rule
In this challenge our user account does not have the privileges to amend Yara rules, so the second option is our only choice. Our first step will be to work out why the program is matching the rule.
rule_135
If we cd
into a folder called yara_rules
, we can see a file called rules.yar
that contains all the Yara rules in use. Viewing its contents with nano
or cat
would take an age to scroll through, so instead we can use a grep
command that will return the 30 lines following a match on rule_135
:
What does this show us? It turns out rule_135
is looking for a single string in the file: candycane
(in this case the condition
clause means it’s searching for this string only - we’ll see some more complex examples later on in the challenge). Now we know what we’re looking for, we can use emacs
to open the_critical_elf_app
and search for the offending string.
With a little patience and scrolling, we can see that the string candycane
appears in the file. You might be wondering why in the screenshot above I’ve changed it to candycand
rather than deleting it entirely. That’s because we should try to alter the program as little as possible - if we change the number of characters, it is possible that references to sections later in the file may become inaccurate and the program may fail to run at all. Code is fragile stuff (something easily learnt from experience).
Let’s save our changes and try running the_critical_elf_app
again…
Oh no! While our adjustment has allowed execution to progress beyond the check for rule_135
, it’s now being blocked because it matches rule_1056
. I guess it’s back to rules.yar
for us…
rule_1056
Running another extended grep
on the Yara rule file shows us that rule_1056
requires a match on two strings, represented by the hex 6c 6962 632e 736f 2e36
and 726f 6772 616d 2121
. This is trickier, because those two don’t appear in their current form in the_critical_elf_app
…
To find what’s matching the rule, we first need to use GCHQ’s CyberChef tool to convert the hex from rules.yar
to ASCII text. As shown below, after being passed through the from hex
filter they come out as libc.so.6
and rogram!!
. If Yara finds both of these strings, execution will be blocked.
The important thing to note here is that both strings need to match for Yara to block anything. One is not enough. This works in our favour when we return to emacs
and examine the file, because libc.so.6
looks like it’ll be required for the program to run.
Meanwhile, This is critical for the execution of this program!!
looks like a comment, so as before, let’s try changing a single character and see what happens.
Well, we’re a step closer to a solution, at least. When we run the file with ./the_critical_elf_app
, we now receive an error because the program has matched Yara’s rule_1732
. Another rule to investigate…
rule_1732
When we grep
for the contents of rule_1732
, we can see that this rule is a little more complex than those we’ve seen before. First of all, our eyes are drawn to the 20 different strings this rule looks for. The condition
clause says the program must match ten of them to be blocked. But there are more conditions that must be met - including that the file size is less than 50kb.
My first thought was to take a similar approach to the previous rules and to change enough of the file to avoid matching ten of the strings, but this proved more challenging than I thought. While strings like its_a_holly_jolly_variable
might be easy enough to substitute out, terms like GLIBC_2.2.5
are more likely to be essential for the program to run. All my attempts either didn’t change enough to evade detection by Yara, or changed too much and broke the app.
I then turned my attention to the other conditions. The file size was initially about 16kb - could I bump it up to more than 50kb? I decided the best way to do this was to add some padding to the file, but encoding issues meant I couldn’t nano
or echo
in a bunch of nonsense without breaking the program.
I obviously needed a more creative approach… It was clear I needed to tackle the problem using emacs
, but after some Googling regarding the clunky Linux terminal copy and paste options I was no closer to a solution and running out of time. Sure of the answer but not the method, I took some inspiration from an old episode of The Simpsons to come to an outside-the-box but very practical solution…
That’s right - I just fired up emacs
, scrolled to the end of the document, and left my water bottle resting on the space bar until enough characters had been added to push the file over the 50kb minimum. It took a while (in truth I went and handled some other stuff while it was running), but after saving the file and using ls -l
to check it was now more than 50kb, I ran the_critical_elf_app
one last time and…
Mission accomplished! I’m sure there were more graceful ways to reach the same outcome, but I’ll put this one down as more proof that a decent understanding of the problem and creative thinking can be just as important in cyber security as any deep technical knowledge in many situations.
And if you’re wondering what that hex means, it comes out as Jolly Enough, Overtime Approved
.
If you found this walkthrough interesting, please consider following me on Twitter, and don’t forget to sign up for the next SANS Holiday Hack Challenge circa December 2022!