I don't understand why they would be actually wrong
compilers convert high level code in human readable form (like C
) to low level code (so that machine could understand it). During compilation most of the semantic as well as syntactic information gets lost due to language transformation, multiple optimizations, etc. Debug symbols may preserve some information (as they are for debug purpose and do not contribute to the actual functioning of the code), but they are generally stripped in COTS binaries. Thus it is sometimes hard (np-hard?) to recover all the information. Consider following program:
int main() {
int a[10];
a[4] = 4;
}
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-32], 4
mov eax, 0
pop rbp
ret
The program is compiled without optimizations, and you can see that the information related is permanently lost (although, you can try to predict the array based on stack size, but it is impossible to conclude that it is indeed an array).
Does decompilation not really work if you are starting from
hand-written assembly?
It may or may not. If a binary is compiled using standard compiler like gcc or llvm, then such compilers use certain format (calling conventions, optimization or code representation style, etc.). But in handwritten assembly, you can essentially do anything (use custom format, different calling conventions, etc). Thus, it is hard to predict the intension of the programmer.
Read more about decompilation correctness in this recently published paper:
Zhibo Liu and Shuai Wang. 2020. How far we have come: testing
decompilation correctness of C decompilers. In Proceedings of the 29th
ACM SIGSOFT International Symposium on Software Testing and Analysis
(ISSTA 2020). Association for Computing Machinery, New York, NY, USA,
475–487. DOI:https://doi.org/10.1145/3395363.3397370