Objective-C calls disappearing in MLIL and HLIL
Version and Platform (required):
- Binary Ninja Version: 3.4.4271, 3.5.4299-dev
- OS: macOS
- OS Version: 13.4
- CPU Architecture: M1
Bug Description: Take the following assembly:
00082a5c f44fbea9 stp x20, x19, [sp, #-0x20]! {__saved_x20} {__saved_x19}
00082a60 fd7b01a9 stp x29, x30, [sp, #0x10] {__saved_x29} {__saved_x30}
00082a64 fd430091 add x29, sp, #0x10 {__saved_x29}
00082a68 1f2003d5 nop
00082a6c e16d1b58 ldr x1, sr_bioResource {sl_bioResource, "bioResource"}
00082a70 b30c0094 bl _objc_msgSend
00082a74 fd031daa mov x29, x29 {__saved_x29}
00082a78 cf0c0094 bl _objc_retainAutoreleasedReturnValue
00082a7c f30300aa mov x19, x0
00082a80 1f2003d5 nop
00082a84 616d1b58 ldr x1, sr_hasPearlSupport {sl_hasPearlSupport, "hasPearlSupport"}
00082a88 ad0c0094 bl _objc_msgSend
00082a8c f40300aa mov x20, x0
00082a90 e00313aa mov x0, x19
00082a94 bc0c0094 bl _objc_release
00082a98 e00314aa mov x0, x20
00082a9c fd7b41a9 ldp x29, x30, [sp, #0x10] {__saved_x29} {__saved_x30}
00082aa0 f44fc2a8 ldp x20, x19, [sp], #0x20 {__saved_x20} {__saved_x19}
00082aa4 c0035fd6 ret
In LLIL, all looks good:
0 @ 00082a5c sp = sp - 0x20
1 @ 00082a5c [sp {__saved_x20}].q = x20
2 @ 00082a5c [sp + 8 {__saved_x19}].q = x19
3 @ 00082a60 [sp + 0x10 {__saved_x29}].q = x29
4 @ 00082a60 [sp + 0x18 {__saved_x30}].q = x30
5 @ 00082a64 x29 = sp + 0x10 {__saved_x29}
6 @ 00082a6c x1 = [&sr_bioResource].q
7 @ 00082a70 call(_objc_msgSend)
8 @ 00082a74 x29 = x29 {__saved_x29}
9 @ 00082a78 call(_objc_retainAutoreleasedReturnValue)
10 @ 00082a7c x19 = x0
11 @ 00082a84 x1 = [&sr_hasPearlSupport].q
12 @ 00082a88 call(_objc_msgSend)
13 @ 00082a8c x20 = x0
14 @ 00082a90 x0 = x19
15 @ 00082a94 call(_objc_release)
16 @ 00082a98 x0 = x20
17 @ 00082a9c x29 = [sp + 0x10 {__saved_x29}].q
18 @ 00082a9c x30 = [sp + 0x18 {__saved_x30}].q
19 @ 00082aa0 x20 = [sp {__saved_x20}].q
20 @ 00082aa0 x19 = [sp + 8 {__saved_x19}].q
21 @ 00082aa0 sp = sp + 0x20
22 @ 00082aa4 <return> jump(x30)
However, in MLIL, hasPearlSupport has disappeared:
0 @ 00082a70 _objc_msgSend(self, "bioResource")
1 @ 00082a78 x0 = _objc_retainAutoreleasedReturnValue()
2 @ 00082a7c x19 = x0
3 @ 00082a88 x0_1 = _objc_msgSend()
4 @ 00082a8c x20 = x0_1
5 @ 00082a90 x0_2 = x19
6 @ 00082a94 _objc_release(x0_2)
7 @ 00082a98 x0_3 = x20
8 @ 00082aa4 return x0_3
It's also gone in HLIL:
00082a70 _objc_msgSend(self, "bioResource")
00082a78 int64_t x0 = _objc_retainAutoreleasedReturnValue()
00082a88 char x0_1 = _objc_msgSend()
00082a94 _objc_release(x0)
00082aa4 return x0_1
Steps To Reproduce: Please provide all steps required to reproduce the behavior:
- Load the above assembly code
- Go to Plugins -> Objective-C -> Analyze Structures (optional, also happens without this but it makes the ILs cleaner)
- Compare the LLIL, MLIL and HLIL
If necessary, I can provide the binary privately.
Expected Behavior:
The hasPearlSupport call should have been retained.
Could you please provide the binary to @peter in Slack or here?
Closing this issue because we haven't been able to reproduce the issue. If anyone has a binary that exhibits this problem and can provide it and point us in the right direction, please attach it (or email it to us) and reopen this issue.
Binary Ninja Version: 4.1.5041-dev Personal (8ab0888f) OS: MacOS
Hi, i've got same behaviour due analysis of mach-o binaries. The binary obfuscated, but some of the cases is kinda clear but nevertheless BN still generating empty calls (objc_msgSend())
And as you may see, the signature for objc_msgSend is set:
This can be fixed by manually overriding every call to exact amount of arguments (like https://github.com/nshp/binaryninja-printf).
For example call at 0x039c7f4 from first screenshot can be fixed by overriding call site type to void* _objc_msgSend(id self, uint8_t* sel):
Steps to reproduce:
- Open attached binary
- Navigate to
0x039c7f4and switch to MLIL/HLIL
Here is binary: bin.zip
Confirmed that I can reproduce this:
I was using 4.1.4997-dev. Wondering if maybe the workflow has an edge-case or something and is missing a fixup? Or, perhaps this could be a core bug where something isn't propagating? For both of the _objc_msgSend calls in the picture, we have int64_t _objc_msgSend() as the type applied.
Here is kinda different example from clean binary, but mb it still can be helpful to investigate root cause:
I overwrote call site types of both msgSend's (at 0x1000222ac and 0x1000222bc), but for some reason HLIL just ignores the second one (and use its own deducted signature):
Binary: bin.zip
From glancing through this binary on latest dev, it appears the issues detailed here have been resolved.
TypeLibraries should be applying to _objc_msgSend which should resolve the initial issue with or without the Objective-C workflow running. This applies the `id(void*,char*) type to msgSend by default.
Additionally, the Objective-C workflow (enabled by default) should automatically be overriding calltypes in all _objc_msgSend calls based on the amount of arguments in the selector.
I threw in the provided binaries. It appears to have been resolved in both of these I additionally went through the list of xrefs to _objc_msgSend and validated every proper msgSend call seems correct. There were some msgSend calls with garbage arguments in the first one, but I have to assume that's some sort of obfuscation.
Here is the region of code screenshotted in the most recent comment, on current dev:
I'm marking this issue as closed again, please let us know if you're still experiencing issues.