While trying to perform the patch diff outlined in Maddie Stone’s talk “What’s Up with WhatsApp” with Ghidra, I encountered multiple problems, but in the end managed to recreate the patch diffing process with Ghidra.
The problems and solutions outlined hopefully help others to get better patch diffs via Ghidra’s Version Tracking.
tl;dr:
@maddiestone forgot to include Ghidra in her patch diff comparison:
I therefore patch diff the CVE-2019-3568 patch in Ghidra.
9daaa009e08ac55168aeacdc34dd9c1d7a8f8a49048de949ddaf8a61997b324f libwhatsapp.so
ee09262fa8b535b5592960ca5ab41e194f632419f8a80ef2e41d36efdbe13f88
28dc66c34e92810ad3f0cb2f5b636773fb4d5fc5134f77b4ee986d9e1a6b4f80 com.whatsapp_2.19.134-452790_minAPI15(armeabi-v7a)(nodpi)_apkmirror.com.apk
d054ff7bce7777a94dc8b72cb5bd8a2ab3b188bcb81fcf8aafcf5720b85036c4 libwhatsapp.so
For those that haven’t read @maddiestone’s slides, she is talking about two vulnerable functions she refers to as:
Size check #1
:
0x51D30
= FUN_00061e34
(in Ghidra)0x51E34
= FUN_00061d30
Size check #2
:
0x52F00
= FUN_00062f00
0x52D0C
= FUN_00062d0c
Ghidra detects some functions as non-returning that are actually returning and hence breaks disassembly, I disabled Non-Returning Functions - Discovered
analyzer:
I previously ran the analysis with this analyzer active and it caused the Source and Destination Programs to have different number of non-returning functions. Ghidra’s Version Tracking Precondition Checklist will check for these and warn you. So always run the Precondition Checklist!!!
Specifically the issue manifests because Ghidra stops disassembly after a non-returning function. But it only detected non-returning functions in one of the programs:
During the wizard you can run some Precondition Checks. These make sure that the enough of the binaries has been analyzed and also performs some sanity checks, e.g., comparing the number of non-returning functions and reporting discrepancies. You should always run these and fix all errors and investigate any warnings.
In this case I got one warning because the libraries had a different amount of errors during analysis:
If you want pristine results you are encouraged to fix as many warnings as you can.
In the new Version Tracking Session you need to add, i.e., run Correlators. These Correlators compare the Source and Destination Programs and find matches, e.g., the Exact Function Bytes Match
Correlator finds matches between functions that have the exact same bytes pattern.
Ghidra’s Automatic Version Tracking Command runs the included Correlators in there supposed order, accepting matches along the way, but keeping false matches to a minimum.
After running the Automatic Version Tracking Command, while the Size Check #1 was matched, it was not automatically accepted:
Size Check #2 was not even matched at all:
However, I decided to run the Function Reference Match Correlator, even though, at least according to the manual, the Combined Function and Data Reference Match Correlator, should already include that correlator:
After this Size Check #2 was matched via the Function Reference Match Correlator:
I then manually accepted the Size Check #1 and #2 functions.
Ghidra does not offer a graph diff view.
The Decompile View in the Function Comparison Window also does not highlight the changes. The two Compile Views simply scroll with their lines being synced (via their line numbers!).
So the only included way to compare changes is via the Listing View:
It becomes quickly apparent that comparing patches via the Listing View is less clear than a graph diff view.
As a workaround, I colored changed basic blocks between the functions to provide a ghetto-tech graph diff view:
If you want to know more about the particularities of the CVE-2019-3568 patch and how to exploit the vulnerability see Maddie’s slides.
So in the end, you can make Ghidra match the two vulnerable functions. However, if you would not know what the functions are you are trying to attack it would be very hard to find them because (for unknown reasons) Ghidra seems to have issues with ARM disassembly resulting in actually near identical functions having seemingly large changes. For example:
So you are going to hunt ghost differences that boil down to Ghidra producing different disassembly for basically unchanged functions.
Maybe this can be controlled (like the non-returning function issues) by an analyzer settings. If you know, please, let me know!
I previously wrote an article about patch diffing CVE-2015-8126.
It can literally be done by running one correlator of my PatchDiffCorrelator project (there is even video proof).
It is super easy compared to this. So if you want to try Ghidra Version Tracking for patch diffing I recommend trying to follow that article.
The same ease of diffing can be exhibited for Windows patches. For example, I again ran one of my correlators on the rdpcorets.dll from the CVE-2019-1326 update and immediately received the following results:
Because the function was matched by name, I can confidently examine the changes more closely knowing that the match is accurate. Also SMSecurityExchangeInfo
is the only function with a symbol that has changes.1
On the case of libwhatsapp.so
I won’t be sure whether I’m looking at Ghidra disassembly differences, a mismatch between functions, or a real change.
That and the fact that the CVE-2019-3568 patch includes more changes makes it harder to patch diff without at least basic knowledge of libwhatsapp.so
beforehand.
Ghidra’s Version Tracking isn’t perfect.
But it can deliver results.
These results mostly depend on the quality of the pre-analysis. Hence it is crucial to properly analyze the candidate programs and fix and disassembly errors.
I am fully aware that I did not fix any disassembly errors and some issues I was seeing could very be related to those errors. I wasn’t really interested in this patch anyway, just wanted to see whether Ghidra could handle the diffing, so I wasn’t willing to manually fix 66 + 77 = 143 errors. I provided everything you need to recreate this. If you do and you get better results by fixing all errors, please, tell me!
Do you like to see a real Graph Diff View in Ghidra? Then voice your support for this feature request.
This is just a random example. I haven’t fully examined CVE-2019-1326, hence don’t know if the change in SMSecurityExchangeInfo is even interesting.↩