SANS Holiday Hack Challenge 2021: Yara rule analysis walkthrough

2022-01-08  Cyber security

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:

  1. Change the Yara rule so that it no longer matches on the program
  2. 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:

grep rule_135 rules.yar -A 30

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!

Looking for the comments? My website doesn't have a comments section because it would take a fair amount of effort to maintain and wouldn't usually present much value to readers. However, if you have thoughts to share I'd love to hear from you - feel free to send me a tweet or an email.