Tag Info

Hot answers tagged

31

It is impossible to prevent reverse engineering for any program that runs on your computer. But you can make steps that make it harder... Program languages like Java and .NET are trivial to recreate human source code for, as they are byte code 'compiled'. Meaning the programming language is compiled into a set of tokens that are interpreted by a run time ...


15

Any program can be reverse engineered, because of the very simple principle that anything that a computer can execute has to be in a format where a person that understands machine code can read. (With the proper tools of course.) The real question is, how easy is it to reverse engineer? C is trivial to decompile; I've seen some surprisingly clean C code ...


10

Many anti-debugging techniques can be used to make reverse-engineering a hell of a task, but it's not impossible. Malware authors use them regularly, and many are applicable to any native machine code, including that compiled from C. A simple example that was really popular in the early years was inserting thousands of breakpoints to make running to a ...


6

The cleanup could be in an outer function, and then return can be used instead of goto: void main_func() { /* Set-up goes here */ handle x = ...; handle y = ...; void result = inner_func(x, y); /* Clean-up goes here */ CloseHandle(x); CloseHandle(y); } void inner_func(x, y) { if (condition1) return; if (condition2) ...


5

The compiler will generate code for everything. The linker may (and usually does) not include code of unused functions in the final executable. Implementation, of course, varies from linker to linker.


5

Indirectly, yes. To know what happens to the code in the header file one must understand how the compiler handles them. The #include directive The #include directive is a preprocessor directive. Even before the compiler starts to analyze and translate the code it will process all #includes by inserting the whole code in the given header file to the ...


5

Interestingly, the C standard defines what variadic function declarations should look like, but no guidance in how to implement them. The mechanics for accessing arguments to variadic functions are therefore implementation-dependent. GNU C provides this via stdarg.h.


5

Using function names to differentiate among n true/false behaviors will result in 2n functions. This is easy to manage when n is a small value like 2 or 3, but it gets out of hand very quickly with anything greater. The POSIX open(2) call has nine true/false variants, and if that were written as one function per combination, you'd be staring down 512 ...


4

You could try saying what you mean: if (!condition1 && !condition2 && !condition3 ) { // do stuff only if all checks passed } CloseHandle(x); CloseHandle(y); // etc. As various commenters have pointed out this is only readable/maintaibable if the condition tests are fairly simple where complex conditions are involved something like this ...


4

You can reverse engineer any program, the result will not be the original source code with comments, descriptive variable names, structure etc. but its functionality will be the same. You cannot prevent this, you can make it more difficult but you cannot not prevent it because at the end of day it will be instructions that the CPU will understand and thus ...


3

As the other answers say, if you can see the binary you can reverse engineer the function of the program, although possibly with difficulty. The cutting edge is therefore to prevent the user from getting at the binary. Old arcade systems did this by storing the program or critical parameters in battery-backed RAM linked to tamper switches. Open the case and ...


3

Don't let anyone else access the program. Run it in a secure* server you control, and let users interface with it only by providing the input over the network and receiving back the output. See http://en.wikipedia.org/wiki/Software_as_a_service The downside is that you now have to manage the server. *Securing a server is far from trivial. For truly high ...


3

It is a matter of terminology. IMHO, any break, continue, goto, return which is not in the body of an if or else or case is an inconditional jump. So obviously if (foobar) goto somelabel; is a conditional jump. In if (foobar) { x = something(); y = other(x); return; } I would believe that the return is conditional. Some people might ...


3

You could note the flow of information in the function definition: void my_function( /* in */ int a, /* in */ int b, /* out */ int* c, /* out */ int* d) { /* do something */ } This way, it's easy to see what happens. If you export this function, you will also include the comments in the prototype so that everybody could see the ...


3

The amount of variables (and hence, the magnitude of the combinatorial explosion) can be reduced with a more general and modular API. For example, instead of making Find support substrings, create a separate function that takes a substring out of a string. Instead of returning either the start of the end of the match, always return the start and make it easy ...


3

The requirement for an error code arises from the fact the new function now can have 3 outcomes instead of 2: the time struct is ok, it is not ok, or the passed argument is NULL. The contract you have in mind for your function is "do not pass a NULL value in, otherwise the program will crash or show some undefined behaviour", whilst your coworkers believe ...


2

Simple, at least in the U.S. You just put an anti-reverse-engineering clause in the program's EULA, and threaten to sue the pants off of anyone who cracks it (this is no joke; the DMCA actually lets you do so).


2

In C a typical way to simplify error checking and avoid deep nested if is: do { if (condition1) break; /* 1. do something... */ if (condition2) break; /* 2. do something else... */ if (condition3) break; /* 3. do something else... */ } while(0); /* Cleanup */ There are various opinion on this "idiom" (e.g. take a look at Do you consider ...


2

The compiler doesn't do anything with other object files. It merely compiles code to object files one translation unit at a time. It's the linker that takes your new object file, looks for symbols like "printf", and then "attaches" the implementation of printf from stdio.h's object file. In theory the linker could throw in the whole stdio.h object file, but ...


2

If someone can observe the program in operation, they can reverse-engineer it. Even if you could somehow prevent the user from accessing the internals of the program, they can perform black-box reverse engineering to build up a model of how the program reacts to various inputs.


2

I'd use a tool to document the code. E.g. with doxygen you can write: /** * \brief Performs something and stores result in \a c and \a d * * \param[in] a ... * \param[in] b ... * \param[out] c ... * \param[out] d ... * * Detailed description here. */ void my_function(int a, int b, int *c, int *d) { /* do something */ } The special ...


1

To make C almost impossible to reverse engineer? It is possible - write your C such that the entire logic is dependent on the input AT RUNTIME (perhaps now you have to protect your input, which hold the secret to your logic in the C program). So reading the C source code really has no meaning. How? One way: Using lots of function pointers. So ...


1

A trivial example of where the function calling fork is supposed to return in both the parent and the child is if the function calling fork is a simple wrapper function, and the caller of that function is the one that chooses what to do in the parent, and what in the child. A simple wrapper function might not make much sense for pure C, but POSIX C++ ...


1

Conditional means it may not be followed depending on some condition. Unconditional means that is program flow reaches that point it always will continue at the target. A if and a switch are a conditional jumps. At the end of the then clause of an if is an unconditional jump to after the else clause. breaks in a switch are also unconditional.



Only top voted, non community-wiki answers of a minimum length are eligible