How to make LLDB a real debugger
These days the de facto debugger in macOS is LLDB. Apple’s old gdb fork doesn’t work anymore and the GNU gdb version is better these days but still quite meh (in the past it couldn’t deal with fat binary targets and I still think this holds true). So we are all essentially stuck with LLDB, warts and all. I also hate the lack of a gdbinit style output but Deroko started that project and I improved it with lldbinit.
Besides its horrible long command line syntax which is so unpopular that gdb-compatible commands were introduced, my biggest problem with it has been the lack of x86 hardware breakpoint support. While hardware breakpoints might not be needed to debug applications within Xcode, they are essential to any serious reverse engineer dealing with arbitrary untrusted targets such as malware, packers, obfuscators, and DRM. It has been a serious blocker for me against some targets and a source of immense frustration because it should be a basic debugger feature.
Last week I finally got fed up enough to dive into the LLDB C++ codebase and finally try to implement this feature. Instead of just posting a patch, this post is a journey into LLDB internals and how I implemented this feature. Hopefully it will help others exploring the LLDB codebase, which seems unfriendly because of the lack of really good documentation into its architecture. Maybe this could lead to further improvements and make LLDB more reverse engineer friendly.[Read More]
Crafting an EFI Emulator and Interactive Debugger
In 2016 I reversed Apple’s EFI firmware password reset scheme using SCBO files. There was an old rumor that these files were able to unlock firmware password locked Macs (and even a sketchy video about a universal SCBO able to unlock any Mac). That post is available at Apple EFI firmware passwords and the SCBO myth.
All the interesting computing action happened at the EFI execution level. I made good reversing progress with static analysis, but dynamic analysis with a debugger would make the job much easier. I love debuggers because they allow you to quickly test ideas and cut corners while reversing a target. Reading disassembly listings for long periods is tiring. (U)EFI debuggers can be found in the market but they are usually quite expensive (a couple thousand USD).
My solution was to create an emulator and debugger based on Unicorn. At the time I was working a lot with Unicorn so it was natural to use it to solve this problem (“if all you have is a hammer, everything looks like a nail”). After I wrote the blogpost some people directed me to some emulators (TianoCore EmulatorPkg and efiperun). I never tried them to see if they contained an interactive debugger like I wanted. The pain wasn’t big since this was a couple of days project and it was quite fun to write.[Read More]
Keygenning Carbon Copy Cloner Keychain Password
Passwords are a modern annoyance and their diversity is something you can’t avoid if you want a minimum amount of account security (don’t forget to turn on those 2FA options, avoiding SMS versions if possible). They get more annoying when you set a super smart new password with that smug feeling that it is such a great password that you will never forget about it (or something crappy you set in a rush). Usually you can’t remember it already in the next day or in the next week, since in a month it is totally wiped out from your memory.
This time my victim was Carbon Copy Cloner (CCC). When you generate a backup you can select an encrypted sparse bundle (disk image) as destination, and save its password in the application private keychain.
Some time ago I created some backups in a hurry and used the encrypted sparse bundle option as destination. Of course I used a super smart password and now I couldn’t remember it. Carbon Copy Cloner was still able to make the backups to that image but I couldn’t open it myself (well it is mounted during a backup but that is not fun enough to write a blogpost about!). I knew CCC had a private keychain somewhere in the system (
/Library/Application Support/com.bombich.ccc/CCC-global.keychain to be precise) so my goal was to click Keychain Access show password radio button to recover the password.
The problem is that the private keychain is locked with a password and I couldn’t find any information about this password. Is it dumb enough to be hardcoded? Or is it something smarter and generated per user/machine/etc? Well the latter is the obvious answer now since this post titles gives it up.
Given that CCC has a privileged helper tool, it is a pretty good assumption that it will be responsible for managing the private keychain (because it runs with higher privileges and protects keychain access from regular users). So load up
/Library/PrivilegedHelperTools/com.bombich.ccchelper into your favorite disassembler. While waiting for disassembly to complete we can try to guess what to look for.
If CCC is using macOS keychain infrastructure then we should be able to see Keychain related APIs in this binary.
$ nm /Library/PrivilegedHelperTools/com.bombich.ccchelper|grep -i keychain U _SecKeychainCopySearchList U _SecKeychainCreate U _SecKeychainFindGenericPassword U _SecKeychainFindInternetPassword U _SecKeychainGetStatus U _SecKeychainItemCopyAttributesAndData U _SecKeychainItemCreateFromContent U _SecKeychainItemDelete U _SecKeychainItemFreeAttributesAndData U _SecKeychainItemFreeContent U _SecKeychainItemModifyAttributesAndData U _SecKeychainLock U _SecKeychainOpen U _SecKeychainSetSearchList U _SecKeychainSetSettings U _SecKeychainSetUserInteractionAllowed U _SecKeychainUnlock
SecKeychainUnlock appears to be a good first candidate to poke around. Apple’s API documentation has everything we need to know about this:
OSStatus SecKeychainUnlock(SecKeychainRef keychain, UInt32 passwordLength, const void *password, Boolean usePassword); password A buffer containing the password for the keychain. Pass NULL if the user password is unknown. In this case, this function displays the Unlock Keychain dialog to prompt the user for the keychain password.
A cleartext password is passed to
SecKeychainUnlock to unlock the keychain. Took longer to disassemble than to find what we need to attack! IDA gives us the following cross references and we can see a very suggestive function name (strip the symbols!).
__stubs:100168D76 _SecKeychainUnlock proc near ; CODE XREF: _openAndUnlockCCCKeychain+30C __stubs:100168D76 ; _openAndUnlockCCCKeychain+626 __stubs:100168D76 jmp cs:_SecKeychainUnlock_ptr __stubs:100168D76 _SecKeychainUnlock endp
Tip: to strip symbols in Xcode the “Deployment Postprocessing” build option must be set to Yes, otherwise the binary will not be stripped.
If you poke around
openAndUnlockCCCKeychain you will understand that the password is being created at the function
kp. It returns a NSString object. So right now it is very easy to recover the unknown CCC keychain password. Just attach with a debugger to the privileged helper process, and breakpoint on the address after the call to
kp. Print the object in
rax register and voila the password is all there (a long mumbo jumbo of weird characters, impossible to bruteforce). To trigger the breakpoint just quit CCC and open it again (the helper process is still running in the background and the debugger is attached). That’s it, it really takes longer to disassemble than to recover the password. The helper process is not SIP protected so the debugger can be attached without any problems.
To test the password, copy the keychain to somewhere else, change permissions to current user and open the keychain. Insert the password, and voila it unlocks. Go to saved keychain items, click show password and our mission is complete. The password I had set was a really dumb one, and I was trying all the complex stuff I could remember of. Ah the joy of new passwords rush!
Well this wasn’t that much fun, so I got curious about the password generation algorithm. Time to poke around the
kp function. The function isn’t very complicated so I will not lose much time with details. It collects the following information about the machine where it is running:
- Hardware model name (via CTL_HW/HW_MODEL sysctl)
- Number of CPUs (via sysctl)
This gives a strong hint that the password is specific to each machine where CCC is executed (a positive thing!). With this information some transformations are done and a 64 characters password is generated. The
kp function is called when the password is necessary (just from the
openAndUnlockCCCKeychain function) but remains constant per machine. Given this it is very easy to build a keygen. The source for mine is available here carbon_copy_cloner_keychaingen. The code is pretty much a direct translation from the disassembled code and could be improved/optimized. I opted out to sync it with the disassembly in the comments so you could try to understand what is going on.
After all this I have a problem with this solution…
Creating a private keychain that contains passwords to encrypted backups with a password that is out of my choice and constant per machine is something I don’t really like. This password is very easy to keygen or recover with a debugger. I assume we need to run the keygen in the target machine (can IOPlatformUUID and/or IOPlatformSerialNumber be known without running code?) or a debugger (for which we need admin privileges).
I understand those saved encrypted backups passwords to be at higher risk of disclosure since I don’t control the password that guards them.
Of course there are (valid) reasons for this design - easy usage and automatic backups. It is after all a software product with wide customer audience and not just experts - regular people just want stuff to work (it is already a huge step forward if they bought backup software and actively execute backups).
You can opt out for not saving the password in the keychain. But the incentives to do it are there and most users will follow them without fully understanding the risks involved. The flip side of the coin is that I could have lost my encrypted backups because I didn’t save their password in the keychain. Personally I am biased against macOS keychain, and never save any important passwords there. I view it as some sort of a single point of failure and malware is usually interested on its contents (if you use it, don’t use the login keychain for those secrets, create a new one that is only unlocked when you really need it).
I prefer to lose data than have it accessed by unknown third parties!
Reversing and Keygenning qwertyoruiop's Crackme
I was bored this weekend and decided to take some rust out of my reversing skills before they disappear for good. I have spent the past two years or so mostly writing C code (secure C is more like an asymptote but that is why it is a fun challenge) and barely doing any serious reverse engineering and security research. So I decided to revisit some unfinished business with qwertyoruiop’s crackme. I had a look when he originally sent it but got distracted with something else at the time and never finished it. I couldn’t find any public write-up about it so I decided to write one. It is mostly targeted to newcomers to reverse engineering and macOS. You can click the pictures to see the full size version.[Read More]