Vector35 / Vector35/binaryninja-api

Jump tables are quietly created when most targets are not code

Open
#2,381 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component: Core Impact: Medium
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

I found a weird jump table in an x86_64 binary that I can't really explain. Ghidra just gives up on analyzing this jump table, but Binja quietly resolves two of the possible branches without mentioning that there are 254 other possibilities (which are mostly nonsense).

I can't find anything wrong with the SignedValueRange for the jump target, so I'm not really sure how this is supposed to work in the real world. My best guess is that it doesn't actually work, and this is dead code. Regardless, I think Binja should fail more noisily when a bunch of jump targets go into the void.

Here's a minimal repro binary so you can see what I mean.

Edit: FWIW, I eventually figured out how this is supposed to work and found several other instances of it. This binary has glibc statically linked in, and this seems to be how it statically builds in the CPUID switching stuff (e.g. selecting between SSE memcpy, AVX2 memcpy, etc.). I guess they not-very-intelligently build out the actual CPU feature detection, and what they end up with is:

xor  rax, rax  ; Set "CPUID" external to the function
call memcpy    ; Call the function which switches on al (rax.b)

So this would be easily solved by interprocedural VSA, but that's a different matter. Manual UIDF is also a workaround.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked jumptab.elf repro and the jump-table analysis involving SignedValueRange. Compare the resolved branches with the other possible targets, then define completion as producing a clear diagnostic when most targets are invalid without breaking legitimate CPU-feature dispatch tables.

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
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.