Vector35 / Vector35/binaryninja-api
Improve support for 64 bit values in 32 bit binaries
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 1.3k
- Forks
- 298
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 19
Description
Currently in order to get best decompiler output, I need to define 2 32 bit variables in the example below. It uses crc64 and some kind of key scheduling algorithm that uses 64 bit values.
08048f42 uint32_t hash_part1
08048f42 uint32_t hash_part2
08048f42 hash_part1, hash_part2 = crc64(0, 0, key, strlen(key))
...
key_schedule(hash_part1, hash_part2, 16, state)
....
crc64 and key_schedule prototypes are like these:
uint64_t crc64(uint32_t hash1, uint32_t hash2, char* data, uint64_t size)
void key_schedule(uint32_t hash_part1, uint32_t hash_part2, int32_t fixed16, uint32_t* state)
For example there is a bit shifting in key_schedule that uses these two hash value:
int32_t hash_part1_ = hash_part1
hash_part1_ = hash_part1_ u>> 1 | hash_part2 << 31
Which could be simple writed like hash >>= 1.
When I try to set crc64 and key_schedule prototypes into these:
uint64_t crc64(uint64_t hash, char* data, uint64_t size)
void key_schedule(uint64_t hash, int32_t fixed16, uint32_t* state)f
It still returns two values from crc64 and calls key_schedule like this:
hash_part1, hash_part2 = crc64(0, key, strlen(key))
key_schedule(hash.d, 16, state)
And bit shifting look like this:
int32_t eax_1 = hash:4.d
int32_t hash_part1_ = hash.d
hash_part1_ = hash_part1_ u>> 1 | eax_1 << 31
Another example in same binary that does bit counting if ((0 | (value.d & 1)) != 0) { is very interesting:
08049701 uint64_t value
08049701 value.d = ptrace(PTRACE_PEEKDATA, parent_pid, regs.ebx, nullptr)
08049725 value:4.d = ptrace(PTRACE_PEEKDATA, parent_pid, regs.ebx + 4, nullptr)
08049727 int32_t counter = 0
080497aa while ((value.d | value:4.d) != 0) {
08049750 if ((0 | (value.d & 1)) != 0) {
08049779 counter = 0(0xb82d3c24, counter, value:4.d)
08049758 }
08049782 int32_t edx_7 = value:4.d
0804978e value.d = value.d u>> 1 | edx_7 << 0x1f
08049794 value:4.d = edx_7 u>> 1
0804978c }
Which could be optimized into this:
08049701 uint64_t value
08049701 value.d = ptrace(PTRACE_PEEKDATA, parent_pid, regs.ebx, nullptr)
08049725 value:4.d = ptrace(PTRACE_PEEKDATA, parent_pid, regs.ebx + 4, nullptr)
08049727 int32_t counter = 0
080497aa while (value) { // or value != 0
08049750 if ((value & 1) != 0) {
08049779 counter = 0(0xb82d3c24, counter, value:4.d)
08049758 }
08049782 value >>= 1 // or value = value >> 1
0804978c }
I think that there is a great opportunity for improving these outputs. Which would make output way more understandable and shorter.
Binary:
break.zip
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 examining the attached break.zip binary and the crc64, key_schedule, and 64-bit bit-counting examples described in the issue. Compare the current decompiler output with the requested 64-bit expressions; done means these cases produce concise, semantically equivalent 64-bit operations without manually split variables.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers, reverse-engineering
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100