binaryninja-api icon indicating copy to clipboard operation
binaryninja-api copied to clipboard

HLIL can't show arguments for a certain type of calls

Open seekbytes opened this issue 1 year ago • 2 comments

Version and Platform (required):

  • Binary Ninja Version: 4.1.558-dev
  • OS: macOS 15
  • CPU Architecture: m2

Bug Description: Some calls under Windows PE that are detected only in MLIL, when lifted to HLIL, do not show parameters/arguments while IDA does. The current issue seems to be related to the tracking of arguments in the stack that are not currently propagated into the call, but I'm currently not sure.

What I'm expecting is to have the arguments typed at the same level of the call.

Steps To Reproduce: Please provide all steps required to reproduce the behavior:

  1. Open binary
  2. Go to 0040181c
  3. Change view to HLIL
  4. See the issue

Screenshots/Video Recording:

  • MLIL of the calls: image
  • HLIL of the same portion of code: image

Binary: Binary has been sent via private message into Slack.

seekbytes avatar Jun 21 '24 08:06 seekbytes

Binary can be found internally with: mention resolve access.

emesare avatar Jun 21 '24 18:06 emesare

There is another related issue in this binary as well. Check address 0x402948

21 @ 00402948 int32_t var_29c_1 = 0x44

All of these temp stack vars at 29c should be eliminated.

If you patch out the SEH prolog/epilog calls in sub_402932, then elimination occurs properly, and the stack strings are recovered as well.

bpotchik avatar Jun 21 '24 19:06 bpotchik

I believe the core issue here is that the stack remains unresolved. You need to figure out the underlying reason that the stack isn't being adjusted properly and fix it. I think it would be good if we ultimately told the user that the stack is unresolved and we're operating in a degraded state.

plafosse avatar Jul 02 '24 14:07 plafosse

A quick triage points out that the issue is we are not terminating the control flow after a call to ExitProcess

Screenshot 2024-07-02 at 10 13 06 PM

Weird enough, the type of ExitProcess is correctly marked as no-return:

Screenshot 2024-07-02 at 10 14 18 PM

What makes the thing even more confusing is that if I manually override the call type at 0x401044 to void (uint32_t ) __noreturn = , then it works just fine

xusheng6 avatar Jul 02 '24 14:07 xusheng6

That looks really interesting! Thanks for the fast triage, happy to report more issues :) let me know so I can retest

I think it would be good if we ultimately told the user that the stack is unresolved and we're operating in a degraded state.

This would be much appreciated ^

seekbytes avatar Jul 02 '24 14:07 seekbytes

For what it's worth, you don't even have to specify the call-type at all since that is the defaults. Just right-click on the ExitProcess in that line and choose "override call type" and hit enter to select the default type and it resolves all the subsequent stack mis-alignment because it correctly understands execution will never continue.

psifertex avatar Jul 02 '24 14:07 psifertex

That at least gives you a work-around for now, but it's still a but that this is occurring at all.

psifertex avatar Jul 02 '24 14:07 psifertex

I tested and we are NOT always ignoring the no-return info from the external functions. I tested a few other paces and when there is a call to ExitProcess, we terminate the control flow properly. There is something peculiar with the control flow in this particular function -- those jumps back from the later part of the function is playing a role. If I remove them then it also works just fine

xusheng6 avatar Jul 03 '24 06:07 xusheng6

This is because we are NOT processing no-return properties if the call instruction becomes MLIL_CALL_UNTYPED at MLIL.

xusheng6 avatar Jul 03 '24 07:07 xusheng6