Derek Selander Profile picture
Oct 24, 2018 25 tweets 10 min read
In less than a week, v3 of the Advanced Apple Debugging book will be released! store.raywenderlich.com/products/advan…
Unfortunately, there's an annoying bug in Xcode 10's LLDB that crippled a couple chapters and prevented many LLDB scripts from executing. Since I should probably be a bit more social on the Tweeters during this time, here's a thread for the problem, find, and fix for this bug
Hopefully, this thread of debugging, reverse engineering, and extracting information out of a binary is a fun (hopefully?) read. If you're interested to learn more, the methodologies are discussed quite a bit in the book. So here we go....
Let's first discuss the problem:

In lldb-1000.11.37.1 (packaged with Xcode 10.0), LLDB will default to importing the MacOSK headers even if the target is an iOS Simulator or iOS app. This bug only appears (to my knowledge?) in a Terminal session. Let's attach LLDB to Safari Image
So far so good.... now execute a LLDB command to import the UIKit module Image
This fails because LLDB is looking in the wrong directory. Specifically it's looking at the path given by:

xcrun -sdk macosx -show-sdk-path

This is a minor inconvenience for most iOS devs who now can't call -[UIView frame] via LLDB, but it REALLY sucks for my dbg scripts Image
So the problem for me was I had a book that's coming out w/ a bunch of chapters that won't work due to this bug and a repo of scripts that are now broken with no specific time on when my radar would be addressed (I am just assuming it's Q1/Q2 2019 based upon past resolved radars)
So, how can I verify this is problem? I have no clue! The LLDB repo (available here github.com/llvm-mirror/ll…) is a BEAST. I have so much respect for the people who commit to that thing. When I am this clueless on where to start, I'll usually cast a wide net... using DTrace!
I first want to determine that LLDB is incorrectly referencing the MacOS SDK. To do that, there's a lovely script called opensnoop (originally authored by @brendangregg, also check out his DTrace book, it's amazing) that monitors the system calls of open* functions
This tweet compares Xcode 10's LLDB vs Xcode 9's LLDB:

sudo opensnoop -n lldb -t | grep "./Developer/Platforms" -A10

opensoop is told to monitor any processes named "lldb", print out the stack trace (-t), and only observe opens to the ./Developer dir

So we can definitely see Xcode 10.0's LLDB is opening the wrong SDK for some reason.

It's important to note that with Mojave, DTrace will only function if you disable SIP on your macOS.
Looking at the source code for LLDB, there's an enum that specifies the type of SDK to load called SDKType github.com/llvm-mirror/ll…
Since this is c++ code, we can use LLDB to set a breakpoint on a func that contains SDKType (Non stripped c++ functions will contain the param type) Image
You know it's going to be a "fun" day when you're using LLDB to debug LLDB

1. Sets up the lldb executable target
2. Set a regex dummy breakpoint on code that contains the phrase "SDKType" in the lldb process
3. Attach to an iOS simulator app (equivalent to "lldb -n MobileSMS") Image
LLDB has several ways to load code into the LLDB process

It can load Python code via the "command script" command (discussed extensively in the book) and can load executable (C/C++) code via the "plugin load" command. Perhaps we can augment existing code in LLDB
This means I am looking for a *SDKType* breakpoint that can get called later in the execution time since I need any injection code to be executed first. Maybe I could pull off a DYLD_INSERT_LIBRARIES var to augment some code, but I want this to be a bit more approachable...
Fortunately, check out what happens when I execute a "po @import UIKit" while that SDKType regex breakpoint enabled.

A breakpoint of interest gets tripped! Image
Look at the parameters passed into method: For this particular example, the RCX register will be the register holding the SDKType (assembly calling conventions are discussed in the book)

Cross referencing this value with the SDKType in the LLDB repo, we can see 0 is MacOSX ImageImage
So what if we changed this value to 1 to get the expected iPhoneSimulator? Using LLDB, that's totally possible

Then continue the application. Hmm.... no errors now! ImageImage
So that means if I can turn a 0 into a 1 in this method, all my headaches go away, my chapters will no longer be crippled, and my scripts will work

Let's get back to that breakpoint when executing that "po @import UIKit" method and check out how the SDKType parameter is resolved
After another setup execution of running LLDB to debug LLDB to debug the Simulator MobileSMS, that same breakpoint is tripped. Let's look at that stack trace again. See how "frame 0" has the SDKType param while "frame 1" has no parameter for the SDKType? Image
Inspecting the assembly on "frame 1" didn't produce anything (I'll spare you that dead end). Let's look at how this method is called

Jumping down to "frame 1", dump the disassembly leading up to calling the SDKType breakpoint function

Then navigating to where frame 0 is called ImageImage
You see that instruction on 0x102ff0154? That is saying call the address at

*(long *)(rax + 0x150)

What does the rax register hold? It's c++ vtable for the class PlatformMacOSX. Offset 0x150 references a method AddClangCompilerOptions

Do you notice something fishy? ImageImage
I sure didn't on my first pass! The reference to the stack trace and the *(long *)(rax + 0x150) are different methods! Let's inspect this new method

This sets RCX to 0 and does a tail call optimization so we don't see it in the stack trace! This is the problem method! Image
How can we resolve this? Well let's look at the memory in that RAX register...

It's both readable and writable! Meaning if we can find this address in memory, then we can overwrite it to a function we control! Image
This means that if we can find the desired function to go to, the problematic function to avoid, and the vtable for PlatformMacOSX, we can inject or own code to intercept this func. So without further ado here's github.com/DerekSelander/… which will let your override the SDK. Enjoy! ImageImageImageImage

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Derek Selander

Derek Selander Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(