avast / avast/retdec

Bug in bin2llvmir Decoder

Open
#801 1 comment 0 reactions 0 assignees View on GitHub
bug C-bin2llvmir
Dominant language
C++
Stars
8.6k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

I try to translate the following ELF file:

[busybox.zip](https://github.com/avast/retdec/files/4867329/busybox.zip)

But in the decoder phase, the retdec just gets an error and exits:

屏幕快照 2020-07-03 10 48 18

The code block in address `0x4af640` is a part of unsolved switch case in address `0x4af63e`:

```llvm
; 0x4af637
store volatile i64 4912695, i64* @_asm_program_counter
%1085 = load i64, i64* @rsi
%1086 = load i64, i64* @rbp
%1087 = add i64 %1086, -1256
%1088 = inttoptr i64 %1087 to i64*
store i64 %1085, i64* %1088

; 0x4af63e
store volatile i64 4912702, i64* @_asm_program_counter
ret i64 undef
}

define i64 @function_4af640() {
dec_label_pc_4af640:

; 0x4af640
store volatile i64 4912704, i64* @_asm_program_counter
store i64 -120, i64* @rax
```

So the address `0x4af640` is marked as `LEFTOVER`, in the following `decoder` code snippet, the `0x4af640` is used to create a function:

```C++
llvm::BasicBlock* bb = getBasicBlockAtAddress(start);
if (bb == nullptr)
{
if (jt.getType() != JumpTarget::eType::LEFTOVER)
{
LOG << "\t\t" << "found no bb for jt -> skip" << std::endl;
return;
}

llvm::BasicBlock* tBb = nullptr;
llvm::Function* tFnc = nullptr;
getOrCreateCallTarget(start, tFnc, tBb);

...
}
```

However, in the later binary code, the `0x4af640` is used in other resolved switch cases, and will cause this error. I think maybe `getOrCreateCallTarget` is not suitable for this case, `0x4af640` should be a block after `0x4af63e`.

Something like this may potentially solve this problem, but we need to inspect it carefully:

```
else if (auto* b = getBasicBlockBeforeAddress(addr)) {

tBb = createBasicBlock(addr, b->getParent(), b);
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in the bin2llvmir decoder around getBasicBlockAtAddress() and getOrCreateCallTarget(), using the supplied busybox ELF and the 0x4af63e/0x4af640 switch-case sequence as the reproducer. Inspect whether getBasicBlockBeforeAddress() can represent 0x4af640 as a block after 0x4af63e without breaking resolved switch cases. Done means the decoder translates this ELF without the reported error and handles the target address consistently.

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.