Nur geträumt is mostly a challenge about getting an old Mac disk image running in an emulator, and then poking around to get enough clues to solve a trivia problem. There’s no real reversing involved, but rather reading what is available from reading resources with Super ResEdit, a tool for reversing these old Mac application.
This challenge is a Macintosh disk image (Disk Copy 4.2 format, for those who need to know) containing a 68K Macintosh program. You must determine the passphrase used to decode the flag contained within the application. Super ResEdit, an augmented version of Apple’s ResEdit resource editor which adds a disassembler, is also included on the disk image to help you complete the challenge, though you will likely also need to do some outside research to guess the passphrase. This application can be run on any Macintosh emulator (or any real Macintosh from as far back as a Mac Plus running System 6.0.x up to a G5 running Classic). The setup of the emulation environment is part of the challenge, so few spoilers live here, but if you want to save yourself some headaches, Mini vMac is a pretty good choice that doesn’t take much effort to get up and running compared to some other options. This application was written on a Power Macintosh 7300 using CodeWarrior Pro 5, ResEdit, and Resourcerer (my old setup from roughly 1997, still alive!). It was tested on a great many machines and emulators, and validated to run well on Mac OS from 6.0.8 through 10.4. Happy solving! Be curious!
The download contains a Mac disk image:
$ file Nur\ geträumt.img Nur geträumt.img: Apple DiskCopy 4.2 image Nur getr\212umt, 1474560 bytes, MFM CAV dshd (1440k), 0x2 format
I’ll download Mini vMac from their downloads page. On running it, it complains that it needs a ROM:
Continuing from the start page, I’ll download the
System Startup file (here), and drag it onto Mini vMac. It shows an old-school Mac desktop:
I’ll drag the challenge
Nur geträumt.img file onto the emulator, and it shows up as a disk:
Double clicking it opens it as a folder with three items:
Desktop Folder is empty.
Super ResEdit 2.1.3 is the reverse engineering tool mentioned in the prompt.
Nur geträumt program fills the screen with a prompt asking for a password:
Entering a password and clicking “Try” (or pushing Enter) shows a flag value:
Byte By Byte
Playing around with different passwords, I can identify some properties of the result. For example, changing the last character above seems to update every forth character:
This implies there is some initial state of a password, and it’s being modified by my input on a cycle, something like:
plain[i] = enc[i] ? input[i % len(input)]
I don’t know what the operation is yet (hence the
Corroborating this is the fact that “diffpass” and “diffpassdiffpass” return the same result, but removing the last “s” changes a lot:
The third image is the same through the first round, but then gets out of alignment after the 16th character, where it starts back with the first “d”, and the others still have an “s” left.
The most common operation to use for encryption would be an XOR, so I’ll start there and see if I can prove or disprove it. With “a” entered as the password, the first letter in the output is “m”:
If it’s as simple as
plain = enc ^ input, then
m ^ a would give the encrypted value, so 12:
>>> ord('m') ^ ord('a') 12
If the theory is correct, then I can predict what would come from any other input. So a “$” would make a “(“:
>>> chr(12 ^ ord('$')) '('
I’ll note above that the second character XOR with “a” (because a one character input just XORs each byte with that character) results in “a”, which implies the encrypted password is null there. That’s validated as well, as the second output character with “$” is also “$”.
Recover (Almost) Full Encrypted Password
I can work down the input calculating the values of the encrypted password. I already found it starts with 12, then 0. I may need to change the input a bit to get an ASCII output I can XOR. For example, “a” returns a box for the 5th character, but “$” doesn’t. Changing the character while I work will allow me to get all the characters except for two:
12, 0, 29, 26, 127, 23, 28, 78, 2, 17, 40, 8, 16, 72, 5, 0, 0, 26, 127, 42, ?, 23, 68, 50, 15, ?, 26, 96, 44, 8, 16, 28, 96, 2, 25, 65, 23, 17, 90, 14, 29, 14, 57, 10, 4
The 21st and 26th characters aren’t normal 7-bit ascii:
All the other characters involve XORing numbers less than 127, meaning the top bit is off in both cases, and thus the result is off as well. If the encrypted number is greater than 127, than either I need to input something greater than 127 to turn that bit off and get ASCII, or the result is supposed to be greater than 127.
It turns out that apple introduced its own extended eight-bit ASCII codes in Mac OS. But I’ll skip this for now.
Recover Partial Password
With this, I can recover the part of the password that’s XORed to get the known part of the flag, “@flare-on.com”. I’ll load these numbers into a Python terminal (I’ll just use 255 for the two unknowns, and remember they are in there):
>>> ''.join([chr(e^ord(f)) for e,f in zip(enc[-13:], flag_end)]) ' du etwas Zei'
That’s…something? It looks German, which is the theme of the challenge. Googling it shows it’s something like “What time is it?”:
ResEdit is an old-school Mac dev tool for viewing Mac OS binaries, their assembly, and their resources.
Opening it shows a nice splash screen:
Then it opens a windows to ask me what I want to look at, and I’ll select
Nur geträumt. The result shows 12 options:
The code section shows three options:
The longest one called “Application” seems like the place to work. Clicking on it gives an assembly for the binary:
Looking at this assembly, it looks like perhaps the 68000 instruction set, though I’m not 100% sure. I could reverse this if I had to, but I won’t have to.
This option offers one 48-byte object named “99 Luftballons” (this is an important clue I’ll come back to):
Opening it shows the string which looks like it could be my buffer, and it says to try viewing it in hex:
Closing that, I’ll select the “99 Luftballons” row and go to “Resource” > “Open Using Hex Editor”:
This is the encrypted flag buffer, starting with a length (45 == 0x2D) and ending with a checksum (matching what was shown above):
I can update the
enc variable in Python for future references know that I know the two bytes > 127.
This one has a note (which I can’t view all at once because of the tiny Mini vMac window, but I’ll edit the image together for readability here):
Two huge hints in here:
- “1983 was a pretty good year for music”
- “maybe try asking the program if it has a bit of time for you; perhaps it will sing you a song”
The DATA option offers one 225-byte section. It’s got a lot of strings in it:
I feel like I should fine the initial buffer in this section, but I don’t.
dctb shows how the dialog is configured:
Nothing useful here, but neat.
DITL sends my system into a loop of errors because the image is not writable. I’m not sure if that’s because of how I set up, or normal, but I’ll have to kill Mini vMac to get out of the loop.
DLGX offers two sections of memory, both of which are very sparse.
With a bunch of clues picked up so far, and the prompt saying “you will likely also need to do some outside research to guess the passphrase”, I’ll turn to Google. The big hit is “99 Luftballons”:
This is a German song released in 1983 (which was one of the hints), so this is clearly the right path (here is the awesome 1980s music video, though I’ve always been a much bigger fan of the Goldfinger adaptation).
The lyrics for the song start with:
Hast du etwas Zeit für mich Dann singe ich ein Lied für dich Von neunundneunzig Luftballons, auf ihrem Weg zum Horizont
The first line matches up nicely with the partial password recovered earlier, “ du etwas Zei”.
On top of that, that line translates to “Do you have some time for me”:
As the hint says to ask the program if it has some time for me, I will:
My “u” in “fur” should be “ü”, which is causing the “i” to show up as “É”. Still, the flag is the second line of the song, so I can get it from there. Also, the site doesn’t accept it with the ü” in the flag, but when I replace that with a “u”, it works.