avast / avast/retdec

Using "--config" option does not generates the correct LLVM IR

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

Description

1. As we run **retdec-decompiler.py xxx.elf --stop-after bin2llvmir**, a xxx.elf.json file will be generated during the process, which by default will be used to generate xxx.elf.ll (LLVM IR file) later.

2. According to **retdec-decompiler.py**, if I understand correctly, "--config" gives users the option to specify the json config file to be used to generate the LLVM IR file.

3. In order to test if "--config" works properly, I ran the command **retdec-decompiler.py xxx.elf --stop-after bin2llvmir --config path/to/the/xxx.elf.json/that/was/generated/in/step1**. With this command, I explicitly asked retdec to use the json file that is the same as the one that would be automatically generated. In theory, a same LLVM IR file should be generated since essentially an identical json file is used despite that one command has "--config" option, while the other does not. However, the LLVM IR generated in step 3 is different from the one generated in step 1, which can be told by the decompiled main() function explained below.

In binary, the range of main() function is 0x8018ab8 - 0x801aee3.
The code blocks are (in the gap between any two code blocks are data due to optimization):
0x8018ab8 - 0x8018d91
0x8018e3c - 0x8018f15
.............
0x801ab78 - 0x801aee3

With the command in step 1, the decompiled main() function is as follows, which seems to be correct as at the end of the function, there is a branch to 0x8018e3c which is exactly the second code block. **However, I didn't find any branches to 0x8018f20 which is the third code block in the LLVM IR, so as other following code blocks. This might be another failure to look into**.
```
define i32 @main(i32 %argc, i8** %argv) {
dec_label_pc_8018ab8:
%cpsr_z.global-to-local = alloca i1, align 1
%sl.global-to-local = alloca i32, align 4
........
%v0_801aa90.pr = load i1, i1* %cpsr_z.global-to-local, align 1
br i1 %v0_801aa90.pr, label %dec_label_pc_8018e3c, label %bb544
bb544: ; preds = %bb543
store i32 1, i32* @r1, align 4
br label %dec_label_pc_8018e3c
}

```

With the command in step 3, the main() function was misdecompiled as **multiple** functions, which obviously is incorrect.
```
define i32 @main(i32 %argc, i8** %argv) {
dec_label_pc_8018ab8:
%tmp = ptrtoint i8** %argv to i32
store i32 %tmp, i32* @r1, align 4
store i32 %argc, i32* @r0, align 8
%stack_var_0 = alloca i32, align 4
%v0_8018ab8 = load i1, i1* @cpsr_n, align 1
br i1 %v0_8018ab8, label %bb, label %.thread
.thread: ; preds = %dec_label_pc_8018ab8
store i32 134318784, i32* @lr, align 4
br label %dec_label_pc_8018ac0
bb: ; preds = %dec_label_pc_8018ab8
%v1_8018ab8 = load i32, i32* @r0, align 8
%v2_8018ab8 = inttoptr i32 %v1_8018ab8 to i32*
store i32 %v1_8018ab8, i32* %v2_8018ab8, align 4
......
._crit_edge: ; preds = %bb4, %bb5
ret i32 %v1_8018ac4
}

define i32 @function_8018ac8(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) {
dec_label_pc_8018ac8:
store i32 %arg4, i32* @r3, align 4
.......
}

define i32 @function_8018b20() {
dec_label_pc_8018b20:
store i32 134318884, i
..........
}

define i32 @function_8018b2a(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) {
dec_label_pc_8018b2a:
%cpsr_c.global-to-local = alloca i1, align 1
......
}
........................................
```

**Why I wanted to use "--config" option:**
I found that the json file generated by retdec was not very accurate, e.g. some functions' start/end address and some globals are misidentified. Thus, I modified the json file to make it consistent with the binary. In this case, I must use "--config" to let retdec use the my modified more accurate json file.

**My attempts:**
I tried to hard code the json file path in **retdec-decompiler.py** and **retdec-color-c.py** in various ways , but none of them worked.

Any thoughts/help would be appreciated!

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the two retdec-decompiler.py invocations from the issue and compare their LLVM IR, then inspect how --config is handled in retdec-decompiler.py and retdec-color-c.py. Verify whether the supplied JSON is actually used. Done means --config produces the same IR as the automatically generated configuration and supports the user's modified function and global information.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
compilers, 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.