Vector35 / Vector35/binaryninja-api
Types auto-detected from demangled symbol names are wrong for methods
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 1.3k
- Forks
- 298
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 19
Description
Binary Ninja Version
2.4.3105-dev
Describe the bug
Binary Ninja appears to attempt to set the type of symbols based on the type information in their mangled names. However, when handling C++ methods, Binary Ninja does not properly handle the implicit this-pointer passed as their first argument - it treats all methods as though they were static. A method Foo::x(char const *) will be considered to take a single char const* argument, but this is incorrect- there is also an implicit this.
This can severely break analysis in some cases because all calls to methods affected by this issue are missing their final argument (BN thinks the function has one less argument than it really does) and are mistyped (all types are off by one).
To Reproduce
Steps to reproduce the behavior:
Compile a binary, or use the one attached: argh.gz
(gzipped for silly GitHub reasons):
[nix-shell:~/binja-poc]$ cat argh2.h
class Foo {
public:
Foo() {};
int x(const char * somearg);
};
[nix-shell:~/binja-poc]$ cat argh2.cpp
#include "argh2.h"
int Foo::x(char const *somearg) {
return 7;
}
[nix-shell:~/binja-poc]$ cat argh.cpp
#include "argh2.h"
int main(void) {
Foo f;
f.x("hello world");
}
[nix-shell:~/binja-poc]$ g++ argh2.cpp -shared -o argh2.so
[nix-shell:~/binja-poc]$ g++ argh.cpp argh2.so -o argh
Open the resulting binary in Binary Ninja, and observe that the argument to Foo::x ("hello world") is missing from HLIL
00401050 int32_t main(int32_t argc, char** argv, char** envp)
0040105b void* fsbase
0040105b int64_t rax = *(fsbase + 0x28)
00401070 void var_11
00401070 Foo::x(&var_11)
0040107a *(fsbase + 0x28)
00401083 if (rax != *(fsbase + 0x28))
0040108c __stack_chk_fail()
0040108c noreturn
0040108b return 0
Note that the type of Foo::x is int64_t Foo::x(char const* arg1).
Expected behavior
Foo::x should be considered to take two arguments (on platforms with Itanium-like ABIs and mangling rules). Changing this manually by retyping the function to int64_t Foo::x(void* this, char const* arg1) results in the argument being correctly displayed:
00401070 Foo::x(this: &var_11, "hello world")
Version and Platform (required):
- Binary Ninja: Dev 2.4.3105-dev
- OS: NixOS
- Version: 21.11
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
Start by reproducing the issue with the attached argh.gz binary or the argh2.h, argh2.cpp, and argh.cpp example, then inspect the generated HLIL and the inferred type for Foo::x. Trace the demangled C++ method type handling from the relevant analysis entry point. Done means methods include the implicit this argument and calls display both this and the explicit argument correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- reverse-engineering
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100