plaidCTF 2014 - bbos (for350)

For PlaidCTF2014, Eindbazen and fail0verflow joined forces as 0xffa, the Final Fail Alliance.
Don't miss out on other write-ups at Eindbazen's site!
Forensics (350 pts)

You have traveled back in time, but look, hunting  The Plague is tough.
You're really just going back to relax for a while  without having to
worry about all that nonsense. As you walk in the park  you stumble
across someone's BlackBerry. Wow, people still use  BlackBerry phones
(time travel gets so confusing)? You figure you should  return it to the
owner, but you have a hard time getting inside. Figure  out what's on
the phone, and maybe we'll be able to return it to the rightful owner.

BlackBerry was this fancy pager thing, right?

Part 1

I’ve never touched a BlackBerry before, but myths of “enterprise”, “security” and “data protection” keep rushing through my mind. WE WILL ALL DIE DUE TO ENCRYPTION WITH TWOHUNDREDFIFTYSIX BIT SECURITY, or something like that.

So there’s an emulator. Surely it does JIT from the ARM code (BlackBerrys are ARM-based, after all), and if the BlackBerry software is implemented in a higher-level language (that may JIT itself on the device), debugging this with an x86 host debugger is going to be FUUUUN.

But don’t despair. Let’s fire up the emulator.

We start the “fledge” thingie, which appears to be a x86 windows application, by running 9930.bat, and are greeted by a loading screen on a virtual BlackBerry. Is this a regular BlackBerry boot screen, or is this the emulator loading up? I have no idea. A few second later we get this screen:

BlackBerry simulator lock screen

The message indicates that content protection is just about to cleansweep the device’s memory and remove all the secrets. Maybe that’s the attack - creating a memory dump before this happens? But I’m too slow for that when trying to attach the debugger, and it doesn’t start properly with a debugger already attached.

But let’s see what happens first. We can enter a password:

BlackBerry simulator password prompt

and are greeted with this screen:

BlackBerry simulator incorrect passsword

Uh oh, this thing is going to explode after a few more tries:

BlackBerry simulator password prompt 2/10

Let’s attach IDA to fledge.exe. Surely the emulated BlackBerry must be in memory, so even if all the something-to-ARM-to-x86 JIT-compiled instructions are hard to disassemble, memory should be fine. Let’s apply the strings theory (the strings theory is that strings is faster in finding gold nuggets than me), and search for… hm… “Password”.

debug020:0030852C aPasswordapi db 'PasswordApi',0
debug020:003091FC aDopasswordapi db ' &doPasswordApi',0
debug020:00309C10 aClassFledgePas db 'class fledge::PasswordApi',0
debug020:00390990 aClassCommonpas db 'class CommonPasswordApi',0
debug020:00394C70 aCommonpassword db 'CommonPasswordApi',0
debug020:00394CE8 aCommonpasswo_0 db 'CommonPasswordApi',0
debug020:00394EC8 aCommonpasswo_1 db 'CommonPasswordApi',0
debug020:003B2988 aWxpasswordentr db 'wxPasswordEntryDialog',0
debug020:003E26B0 aCommonpasswo_2 db 'CommonPasswordApi',0
debug020:003F0E18 aWxte_password db 'wxTE_PASSWORD',0
fledge.exe:00DDBACC aEnterPassword db 'Enter Password',0
fledge.exe:00F08A84 aRimsetpassword db 'RimSetPassword( %p, %p )',0
fledge.exe:00F08AA0 aRimsetpasswo_0 db 'RimSetPassword',0
fledge.exe:00F08ADC aRimgetpassword db 'RimGetPasswordFailureCount(  )',0
fledge.exe:00F08AFC aRimgetpasswo_0 db 'RimGetPasswordFailureCount',0
fledge.exe:00F08B18 aRimresetpasswo db 'RimResetPassword(  )',0
fledge.exe:00F08B30 aRimresetpass_0 db 'RimResetPassword',0
fledge.exe:00F08B44 aRiminitiateres db 'RimInitiateResetWithCode( %u )',0
fledge.exe:00F08B64 aRiminitiater_0 db 'RimInitiateResetWithCode',0
fledge.exe:00F08B80 aRimverifypassw db 'RimVerifyPasswordChallenge( %p, %lu, %p )',0
fledge.exe:00F08BAC aRimverifypas_0 db 'RimVerifyPasswordChallenge',0
fledge.exe:00F08E88 aRimverifypas_1 db 'RimVerifyPassword( %p )',0
fledge.exe:00F08EA0 aRimverifypas_2 db 'RimVerifyPassword',0
fledge.exe:00F08F40 aRimverifypas_3 db 'RimVerifyPasswords( %p, %p )',0
fledge.exe:00F08F60 aRimverifypas_4 db 'RimVerifyPasswords',0

fledge.exe is the x86-based emulator. We even see references to these strings from native x86 code. Let’s breakpoint them all, and re-enter a password, let’s say the string 2312.

First, we see that it calls RimGetPasswordFailureCount (at 007A9CE0) before displaying the password prompt. Wait - this is native x86 code. This is good news. This means that the password checking does not happen in crazy double-JIT’ed code. It means that this is not an emulator, but a simulator. It does not emulate an ARM cpu at all. It appears that the BlackBerry OS is running in JVM with native implementations of - the password API (among other things). And fledge.exe implements these in plain x86 code.

Next, we see that it reaches RimVerifyPasswords (at 007AB950). We trace the code, eventually reach 0089DB70, 10013E50 (fledge9930.dll’s RimVerifyPasswordsAPI; seems there is a device-specific version).

That code is interesting: There’s a magic 0x2801 constant here:

fledge9930.dll:10013DD0 loc_10013DD0:                           ; CODE XREF:j
fledge9930.dll:10013DD0 sub     esp, 80h
fledge9930.dll:10013DD6 push    80h
fledge9930.dll:10013DDB lea     eax, [esp+4]
fledge9930.dll:10013DDF push    eax
fledge9930.dll:10013DE0 push    2801h
fledge9930.dll:10013DE5 call    loc_104FD0B0
fledge9930.dll:10013DEA add     esp, 0Ch
fledge9930.dll:10013DED test    eax, eax
fledge9930.dll:10013DEF jnz     short loc_10013E07
fledge9930.dll:10013DF1 push    offset unk_68037B
fledge9930.dll:10013DF6 call    near ptr unk_104FCF72
fledge9930.dll:10013DFB add     esp, 4
fledge9930.dll:10013DFE xor     eax, eax
fledge9930.dll:10013E00 add     esp, 80h
fledge9930.dll:10013E06 retn

If we follow loc_104FD0B0, we reach a function that has a debug string of "NvGetRecordCopy". Could 0x2801 be an NV record ID?

We can see that this function fills in this structure:

260BFA30  02 00 01 00 3C 00 00 00  3E 27 0F 54 C6 EB 31 75
260BFA40  B4 EF 8B 20 08 07 95 EF  2E E1 55 89 FF FF FF FF
260BFA50  FF FF FF FF FF FF FF FF  01 00 00 00 0A 00 00 00
260BFA60  CF 2C B0 00 E9 97 92 B2  F0 F8 18 00 A8 2A B0 00
260BFA70  50 2A B0 00 90 8A 70 0D  00 00 00 00 60 8F F0 00

Damn, no plaintext password in sight. Let’s continue to trace.

A few instructions later, we reach this loop:

fledge9930.dll:10013C10 loc_10013C10:                           ; CODE XREF:j
fledge9930.dll:10013C10 mov     dl, [esi+ecx]
fledge9930.dll:10013C13 cmp     dl, [ecx]
fledge9930.dll:10013C15 jnz     short loc_10013C2A
fledge9930.dll:10013C17 add     eax, 1
fledge9930.dll:10013C1A add     ecx, 1
fledge9930.dll:10013C1D cmp     eax, 14h
fledge9930.dll:10013C20 jb      short loc_10013C10
fledge9930.dll:10013C22 pop     esi
fledge9930.dll:10013C23 mov     eax, 1
fledge9930.dll:10013C28 pop     ebp
fledge9930.dll:10013C29 retn

Hey, this is a memcmp()!. But it has a hardcoded compare length of 0x14 bytes. What is 0x14 bytes in size and doesn’t look like a plaintext password? A 160-bit SHA1 digest of a password!

Let’s look at the digests that it compares:

260BF9D8  DC A6 84 4C 09 9C E1 CA  BD 68 90 E2 F5 31 01 66
260BF9E8  B1 17 30 B8

What does hash to DCA6844C099CE1CABD6890E2F5310166B11730B8? Is it the secret password? Question: What is the fastest SHA-1 brute-forcer for dictionaries? Answer: google. “2312”? Wut? Fail, that was the password we have entered. But it confirms that it’s SHA-1.

Ok, let’s take a look at the other argument then:

260BFA38  3E 27 0F 54 C6 EB 31 75  B4 EF 8B 20 08 07 95 EF
260BFA48  2E E1 55 89

Got it! Good thing we can paste into the simulator. We’re greeted with a home screen now:

BlackBerry simulator home screen

Let’s just open the email or messages app, read the flag, and be home before dawn.

BlackBerry simulator no text messages

Except, there is no message. Nor email. But there is a contact!

BlackBerry simulator contact list

BlackBerry simulator Plaid CTF contact

fuckfuckfucky0uh4h4h4. Cha-ching 250 pts! And the rest? We’ll follow the link, and find a NAND dump.

Part 2

(This part was solved by Thice, one of our Eindbazen friends.)

Ok, now we got a raw NAND image. In the original 9930-nv.dmp, Thice found this:

0000053000: 00 01 01 28 03 00 00 00 10 CF FF EF 00 00 00 00
0000053010: 00 10 00 00 3C 00 00 00 6F 4A 98 6F 02 00 01 00
0000053020: 3C 00 00 00 3E 27 0F 54 C6 EB 31 75 B4 EF 8B 20
0000053030: 08 07 95 EF 2E E1 55 89 FF FF FF FF FF FF FF FF
0000053040: FF FF FF FF 00 00 00 00 0A 00 00 00 CF 2C B0 00
0000053050: E9 97 92 B2 F0 F8 18 00 4E 56 52 45 FF FF FF FF

Now, 01 28 rings a bell. Looking back, this is what NvGetRecordCopy loaded into memory when called with the argument 0x2801:

260BFA30  02 00 01 00 3C 00 00 00  3E 27 0F 54 C6 EB 31 75
260BFA40  B4 EF 8B 20 08 07 95 EF  2E E1 55 89 FF FF FF FF
260BFA50  FF FF FF FF FF FF FF FF  01 00 00 00 0A 00 00 00
260BFA60  CF 2C B0 00 E9 97 92 B2  F0 F8 18 00 A8 2A B0 00
260BFA70  50 2A B0 00 90 8A 70 0D  00 00 00 00 60 8F F0 00

So, let’s apply this knowledge to the NAND dump, searching for 00 01 01 28:

00000B0030: 00 01 01 28 01 00 00 00 F0 26 97 F6 00 00 00 00
00000B0040: D0 0F 00 00 3C 00 00 00 B1 59 BC A1 02 00 01 00
00000B0050: 3C 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF
00000B0070: FF FF FF FF 00 00 00 00 0A 00 00 00 00 00 00 00
00000B0080: FF FF FF FF 00 00 00 00 4E 56 52 45 FF FF FF FF

No dice. No password set. Let’s look further:

0000110030: 00 01 01 28 20 00 00 00 22 38 0F 37 00 00 00 00
0000110040: D0 0F 00 00 3C 00 00 00 B4 15 DB 72 02 00 01 00
0000110050: 3C 00 00 00 5B AA 61 E4 C9 B9 3F 3F 06 82 25 0B
0000110060: 6C F8 33 1B 7E E6 8F D8 FF FF FF FF FF FF FF FF
0000110070: FF FF FF FF 00 00 00 00 0A 00 00 00 00 00 00 00

YES. We got it. The SHA-1 of the flag for the second part is 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8. Let’s google it up and submit the flag… password? Fail.

But never mind. A few instances later we find:

00002E67F0: 00 01 01 28 38 00 00 00 C5 DD 4F 9F 00 00 00 00
00002E6800: 60 00 00 00 3C 00 00 00 C6 17 AD 80 02 00 01 00
00002E6810: 3C 00 00 00 AC 0C FE 7B D0 AE 22 B4 47 22 F1 A0
00002E6820: 1E CB 6C E1 02 CA 27 C5 FF FF FF FF FF FF FF FF
00002E6830: FF FF FF FF 00 00 00 00 0A 00 00 00 00 00 00 00

AC0CFE7BD0AE22B44722F1A01ECB6CE102CA27C5 resolves to BerryGood - which is correct. 100 more points for us.