As Oli pointed out already in his answer, you can't get the very original source code of an executable.
During the compilation of a source code (compilation intended as in its typical wider acceptation, hence as the whole process that "transforms" a source code into an executable), lots of informations are lost.
The C preprocessor, for one, will do the following (among other things):
- Interpret, execute and remove preprocessor directives (
#
statements)
- Remove comments
- Remove unnecessary whitespace
On the other hand what isn't lost during the compilation of the source code is technically revertible to a functionally equivalent source code.
This is because:
- Binary instructions have a 1:1 corrispondency with assembly instructions; the assembling of an assembly source code is just a mere conversion of the assembly instructions to the binary instructions based on a table of corrispondencies; a single binary instruction is always identifiable and revertible to a single assembly instruction;
- Assembly instructions don't have a 1:1 corrispondency with C instructions; the compilation of a C source code is usually not just a mere conversion of the C instructions to the assembly instructions based on a table of corrispondencies, in fact it's often the opposite; usually a C instruction is converted into multiple (often different based on the compiler) assembly instructions; however, patterns of multiple assembly instructions are usually identifiable and revertible to a single C instruction;
There are tools called decompilers whose purpose is to try to revert an executable to a functionally equivalent source code; however the result is usually something far from the very original source code (and usually also uncompilable);
Consider this program:
#include <stdio.h>
#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered
/*
This comment and the comment above won't be recovered
*/
int main(int argc, char* argv[]) {
printf(MESSAGE);
return 0;
}
By compiling it into an executable and decompiling it into a source code again, this is more or less what you usually get back (in this specific case I used gcc
/ Boomerang):
// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
printf("Literal strings will be recovered");
return 0;
}
As predicted:
- Preprocessor directives are missing
- Comments are missing (aside from
// address: 0x80483fb
, which has been added by the decompiler)
- Unnecessary whitespace is missing (aside from newlines and tabulations, which have been added by the decompiler)
This is also a pretty good result; it's not rare to get inline assembly instructions into the code:
asm("assembly_instruction");
__asm__("assembly_instruction");
The bottom line is (as pointed out already in the other answers): you can't get the very original source of an executable*.
*However, depending on the executable and on your luck, you might be able to get something using a decompiler.
strings
filter program can be very useful in identifying what a particular binary program is or does because it will print all the embedded text strings longer than a specified length in a binary file and looking at the messages in a program sometimes tells you a lot about what it is and does.