This time I was handed an OSX compiled application called RedDelicious. First, I simply ran it (not smart, but I never claimed to be), and got the following window popup:

So I entered some text into the window and clicked Submit, which gave me the message “Try harder…” From this I assumed that I would have to submit the right key in order to get a success message and hopefully the key for the challenge. So, now I wanted to disassemble the binary and see what happens when I click “Submit”.

In IDA, the first thing I noticed is that most functions start with “__T”, which tells me I’m dealing with a Swift compiled binary, since that is the prefix for all symbols in Swift. Swift is great at making ugly, huge function names, so rather than messing around with demangling them or anything too ugly, I had one lead of the “Try harder…” string from when I entered a wrong key. I looked in the strings window and found references to that function and went back from there:

Then I saw the same function both referencing the strings “Try harder…” and “C0ngr4tz!”, so I knew I was on the right track. The function that references them looks like this:

At the bottom where the code flow splits in two, each path has the same code with a different string reference, so I knew I was in the key check function. Now to figure out how to make it say “C0ngr4tz!”

Swift’s compiler treats variables very similar to C++, passing a reference to “this” as an argument to functions, and then using it to find other class references. The class jump table for this class is NSViewController, found at 0x100008090. We’ll need this in order to fix up the calls used in the function. After cleaning up all of Swift’s object oriented code and Automatic Reference Counting (ARC), we can dumb this function down into some simpler pseudocode:

check_key:
    a = entered_key
    a = bb64(a)
    a = xxor(a, "av9vex8pocs4id2")
    a = bb64(a)
    a = xxor(a, " abracadabra")
    a = bb64(a)
    if a == " LyY8TiwwJighJzRSNycvJyU3LzQ1GTc0JlA2ACcGBTcuUSc3JBkZLSoaS1EzUwotBwsDDTQbEiY3Mw0SNDcZVjcLKywjCTpKPApWTw==":
        label = "C0ngr4tz!"
    else:
        "Try harder..."

This gives us a pretty clear idea of what’s going on, but we’ll have to check each of these functions to figure out what they do. After analysis, we find that they do the following different functions:

  • bb64 – Base64 encode the passed in argument

  • xxor – XOR the passed string with the provided key

So, if we write a quick little python script, we can get the key:

import base64

def xxor(plain, key):
    enc = ""
    for i in range(len(plain)):
        enc += chr(ord(plain[i]) ^ ord(key[i % len(key)]))
    return enc

a = "LyY8TiwwJighJzRSNycvJyU3LzQ1GTc0JlA2ACcGBTcuUSc3JBkZLSoaS1EzUwotBwsDDTQbEiY3Mw0SNDcZVjcLKywjCTpKPApWTw=="
a = base64.b64decode(a)
a = xxor(a, "abracadabra")
a = base64.b64decode(a)
a = xxor(a, "av9vex8pocs4id2")
a = base64.b64decode(a)
print a

And the key is: PAN{My_m0th3r_told_m3_2b3_w4ry_of_F@uns}