Is it possible to create an object file using gcc
that cannot be reverse engineered to its source code ?
-
1if a machine can read it... so can a human. you can make it more difficult for the human... but in the end, they can/will still read it.– SnakeDocCommented May 1, 2014 at 17:09
-
stackoverflow.com/questions/4111808/… , stackoverflow.com/questions/1025494/obfuscating-c-c-code– Ciro Santilli OurBigBook.comCommented May 27, 2015 at 10:52
4 Answers
AFAIK that is not possible. There are other things you can keep in mind however:
Use of the GCC optimization flags will help make the code look much less readable to a human. When you compile with the highest level of optimization gcc -O3
the compiler will move things around such that the "flow" might not be at all what you expect.
You can also use the flag -static
which will force gcc to take small functions and make them inline. This will embed them into your code instead of showing as function calls.. it will make them harder to distinguish.
One thing to keep in mind is too it's important to get rid of any unneeded symbols. Gcc offers -fvisibility=hidden
and -fvisibility-inlines-hidden
to help with this. You can also pass the -s
flag to gcc to strip symbols away.
I think that's about all you can do with gcc to help prevent reverse engineering. Additionally you can use code obfuscation, but there are issues there as well unless you implement it yourself, if you use a readily available method or tool to prevent reverse engineering, there is probably already a tool to counter it.
Keep in mind that the final executable will have information in it as well such as what version of gcc it was compiled with. This too can be removed with the strip
command.
If I have an executable (myprog
) I can run objdump
on it to check some information:
mike@mike-VirtualBox:~/C$ objdump --full-contents --section=.comment myprog | head
myprog: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 20285562 756e7475 2f4c696e GCC: (Ubuntu/Lin
0010 61726f20 342e362e 332d3175 62756e74 aro 4.6.3-1ubunt
0020 75352920 342e362e 3300 u5) 4.6.3.
Oops, you can see what version/compiler I used. Well, we can fix that:
mike@mike-VirtualBox:~/C$ strip -R .comment -R .note myprog
mike@mike-VirtualBox:~/C$ objdump --full-contents --section=.comment myprog | head
objdump:
section '.comment' mentioned in a -j option, but not found in any input file
myprog: file format elf64-x86-64
There are other portions you can strip as well, such as .note.ABI-tag
but you do lose portability
-
2I wouldn't recommend stripping
.note.ABI-tag
as it will prevent running the executable on FreeBSD or another OS with Linux emulation support.– Igor Skochinsky ♦Commented Mar 20, 2013 at 13:34 -
1@IgorSkochinsky - a good note for portability, I wasn't thinking about that at the time, but have updated now. Thanks.– MikeCommented Mar 20, 2013 at 14:45
-
1
-
1BTW, I'm not sure why the recommendation about the variable names. If you do it properly, there should be no variable names in the final binary, except possibly publicly exported ones, and those usually do need to have proper, readable names.– Igor Skochinsky ♦Commented Mar 26, 2013 at 17:56
-
1Igor is correct. Those names should be destroyed by the compiler when the binary object is created. In that case, there's no difference. In the case where you're shipping binaries with heavy duty debug symbols in them, you have much bigger problems than what you've named your variables. Commented Mar 27, 2013 at 6:48
Short answer: No.
Long answer: On the (Im)possibility of Obfuscating Programs by Boaz Barak, Oded Goldreich, Rusell Impagliazzo, Steven Rudich, Amit Sahai, Salil Vadhan, and Ke Yang.
Medium answer: If you give your program to a user that control the platform where your program will be executed, there is no way to prevent the reverse-engineering of it. The only thing you can hope for is to force the user to have a black-box analysis approach of your software (meaning that the user will only be able to observe the output of your program on chosen input).
But, even this black-box analysis is extremely difficult to enforce without an additional piece of hardware (eg smartcard) as the user is supposed to be able to take intermediate snapshots of the memory during the execution of your program.
-
2Additionally regarding Hardware Security: Google "There are no secrets in silicone" Commented Mar 20, 2013 at 14:07
-
1Don't forget that at some point you are going to need to debug the damned thing too. The more you obfuscated and rearrange your binary the harder it will be to analyze should something go wrong in the field. It becomes especially trixy if an unobfuscated version works perfectly but the obfuscated version BSODs due to unforseen timing or other interactions introduced by the obfuscation itself.– ModocCommented Mar 20, 2013 at 15:37
Well, it might be impossible to RE the file to the exact original source code (e.g. there's no way to recover comments or preprocessor macros), but that's probably not what you meant to ask.
It's definitely always possible (though sometimes difficult) to produce an equivalent source code, which behaves the same as the compiled code. With some extra work it might be even possible to produce code which compiles to exactly the same bytecode (as long as there was no additional post-processing of compiled binary). This presentation described some of the approaches for this, but I can't find the slides.
While it's not possible to obfuscate object files, it is possible to obfuscate the underlying assembly file. There is no such thing as name obfuscation in C++ since references are by address, not by name. Using full optimization (-O3 -Ob2 -flto) can also make it hard to reverse engineer your code. Also, you can also use VMProtect/Denuvo to encrypt and obfuscate your executable.
You may find those posts useful
https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-c-c-source-in-gcc