Vector35 / Vector35/binaryninja-api
Stack clash protection using stack probing breaks good tracking of stack pointer
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 1.3k
- Forks
- 298
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 19
Description
Version and Platform (required):
- Binary Ninja Version: 4.2.6455 (2c8da1e)
Bug Description:
When programs are compiled with gcc's -fstack-check, stack probes are inserted.
When moving the stack pointer by more than a page, every 0x1000 bytes the stack is probed to prevent jumping over the stack guard page.
This probing is done in a loop.
Probably due to changes to rsp in a loop, binja looses track of the stack pointer which leads to a not that great decompilation output.
Test program
#include <stdio.h>
struct bar
{
int a;
int b;
long long c;
};
int main()
{
char foao[0x5000];
int foo = 22;
struct bar bar = {1, 23, 4};
int z3 = foo + bar.b;
puts("Hello");
printf("z3: %d", z3);
}
Stack probing loop:
0000000000001149 <main>:
1149: 55 push rbp
114a: 48 89 e5 mov rbp,rsp
114d: 4c 8d 9c 24 00 a0 ff lea r11,[rsp-0x6000]
1154: ff
1155: 48 81 ec 00 10 00 00 sub rsp,0x1000 <-- change stack pointer
115c: 48 83 0c 24 00 or QWORD PTR [rsp],0x0 <-- stack probe
1161: 4c 39 dc cmp rsp,r11
1164: 75 ef jne 1155 <main+0xc> <--loop
Steps To Reproduce:
Please provide all steps required to reproduce the behavior:
- Open the original binary in dogbolt.org: https://dogbolt.org/?id=fbbce786-f166-4ef3-9308-a25a3721af92#Ghidra=137&BinaryNinja=93 (notice the
*(i + ...) =) - Patch out the stack probes and the loop.
- See how the
*(i + ...) =disappears https://dogbolt.org/?id=48484467-f5ff-48ab-a735-c07d9140fe24#Ghidra=118&BinaryNinja=81 - For a more annoying example, open
loader(from DEF CON Quals 25'scallmerustchallenge) - https://dogbolt.org/?id=2968ec50-148d-4fc8-b51e-5888de471e7d#BinaryNinja=618&Hex-Rays=485&Ghidra=676
*(i + ...) = - https://dogbolt.org/?id=9a0d20ea-f192-4d52-bbb6-60125e6286e1#Ghidra=665&BinaryNinja=601&Hex-Rays=480
Expected Behavior:
Not all those *(i + ...) = but individual variables.
Binary:
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue in Binary Ninja with the supplied binaries and the provided stack-probing example in main, then compare the original and probe-patched decompilation outputs. Investigate how the stack-probing loop affects stack-pointer tracking; done means the affected stack locations are recovered as individual variables rather than *(i + ...) expressions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- reverse-engineering
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100