WHAT THE HELL?
Okay, this was SUPER overwhelming to look at. I’ve never worked with yara before and now I have to deal with this mess?
After staring at this eyesore for a bit 3 patterns stood out:
- Conditions based on the
filesize
var which is = to 85 bytes - Arbitrary comparisons such as
uint8(62) > 1
- Hash comparisons such as
hash.md5(50, 2) == "657dae0913ee12be6fb2a6f687aae1c7"
Reading the documentation for yara we find that uintXX() is used to access data at a given position, it can be an offset or virtual address. Both 16 and 32 bit integers are considered to be little-endian (VERY IMPORTANT).
Alright then it seems we have the tools to begin solving this challenge.
Another pattern that becomes clear after reading yara docs is the use of and
to separate the conditions of each rule. We can use this to break the rule down to a more readable format.
After some more parsing I got this array of numbers.
85 individual offsets, with 6 conditions to be met each. This is slowly becoming more manageable
After some more parsing more patterns became clear which helped a lot since it made writing an interpreter for the conditions much simpler
At this point it’s pretty obvious that this is an 85 character string, each set of conditions gives you a byte of the string.
Since conditions that require a hash match are only 2 bytes long they’re trivial to bruteforce.
We’re also given conditions such as uint8(20) & 128 == 0
I admit initially I was trying to find the values through ALL the conditions, meaning those with multiple possible values which was a massive headache.
This is the script I used to get the flag, it’s not pretty but it does the job.