Write “Efficient” Code
“We should forget about small efficiencies, say about 97% of the time; premature
optimization is the root of all evil.”
~ Donald Ervin Knuth (born: 1938-01-10 age: 71)
“More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other
single reason — including blind stupidity.”
~ W. A. Wulf (born: 1939-12-08 age: 69)
The safest way to disguise your obfuscation work then is to make it look as if your motive for it is making the program
run faster.
Code That Masquerades As Comments and Vice Versa
: Include sections of code that is commented out but at first glance does not appear to be.
for ( j=0; j<array_len; j+ =8 )
{
total += array[j+0];
total += array[j+1];
total += array[j+2];
total += array[j+6];
total += array[j+7];
}
Without the colour coding, would you notice that three lines of code are commented out?
namespaces
: Struct/union and typedef struct/union are different name spaces in C (not in C++). Use the same name in both name
spaces for structures or unions. Make them, if possible, nearly compatible.
typedef struct {
char* pTr;
size_t lEn;
} snafu;
struct snafu {
unsigned cNt
char* pTr;
size_t lEn;
} A;
Hide Macro Definitions
: Hide macro definitions in amongst rubbish comments. The programmer will get bored and not finish reading the comments
thus never discover the macro. Ensure that the macro replaces what looks like a perfectly legitimate assignment with
some bizarre operation, a simple example:
#define a=b a=0-b
Look Busy
: use define statements to make made up functions that simply comment out their arguments, e.g.:
#define fastcopy(x,y,z)
…
fastcopy(array1, array2, size); /* does nothing */
Use Continuation to hide variables
: Instead of using
#define local_var xy_z
break up "xy_z" onto two lines:
#define local_var xy\
_z // local_var OK
That way a global search for xy_z will come up with nothing for that file. To the C preprocessor, the "\" at
the end of the line means glue this line to the next one.
Arbitrary Names That Masquerade as Keywords
: When documenting, and you need an arbitrary name to represent a filename use "file ". Never use an
obviously arbitrary name like "Charlie.dat" or "Frodo.txt". In general, in your
examples, use arbitrary names that sound as much like reserved keywords as possible. For example, good names for
parameters or variables would be: "bank", "blank", "class", "const
", "constant", "input", "key", "keyword", "kind",
"output", "parameter" "parm", "system", "type",
"value", "var" and "variable ". If you use actual reserved words for
your arbitrary names, which would be rejected by your command processor or compiler, so much the better. If you do this
well, the users will be hopelessly confused between reserved keywords and arbitrary names in your example, but you can
look innocent, claiming you did it to help them associate the appropriate purpose with each variable.
Code Names Must Not Match Screen Names
: Choose your variable names to have absolutely no relation to the labels used when such variables are displayed on the
screen. E.g. on the screen label the field "Postal Code" but in the code call the associated variable "zip".
Don’t Change Names
: Instead of globally renaming to bring two sections of code into sync, use multiple TYPEDEFs of the same symbol.
How to Hide Forbidden Globals
: Since global variables are "evil", define a structure to hold all the things you’d put in globals.
Call it something clever like EverythingYoullEverNeed. Make all functions take a pointer to this structure (call it
handle to confuse things more). This gives the impression that you’re not using global variables, you’re
accessing everything through a "handle". Then declare one statically so that all the code is using the same
copy anyway.
Hide Instances With Synonyms
: Maintenance programmers, in order to see if they’ll be any cascading effects to a change they make, do a global
search for the variables named. This can be defeated by this simple expedient of having synonyms, such as
#define xxx global_var // in file std.h
#define xy_z xxx // in file ..\other\substd.h
#define local_var xy_z // in file ..\codestd\inst.h
These defs should be scattered through different include-files. They are especially effective if the include-files are
located in different directories. The other technique is to reuse a name in every scope. The compiler can tell them
apart, but a simple minded text searcher cannot. Unfortunately SCIDs in the coming decade will
make this simple technique impossible. since the editor understands the scope rules just as well as the compiler.
Long Similar Variable Names
: Use very long variable names or class names that differ from each other by only one character, or only in upper/lower
case. An ideal variable name pair is swimmer and swimner. Exploit the failure of most
fonts to clearly discriminate between ilI1| or oO08 with identifier
pairs like parselnt and parseInt or D0Calc
and DOCalc. l is an exceptionally fine choice for a variable name
since it will, to the casual glance, masquerade as the constant 1. In many fonts rn looks like an m. So how about a
variable swirnrner. Create variable names that differ from each other only in case e.g. HashTable and Hashtable.
Similar-Sounding Similar-Looking Variable Names
: Although we have one variable named xy_z, there’s certainly no reason not to have many other variables with
similar names, such as xy_Z, xy__z, _xy_z, _xyz, XY_Z, xY_z, and Xy_z.
Variables that resemble others except for capitalization and underlines have the advantage of confounding those who like
remembering names by sound or letter-spelling, rather than by exact representations.
Overload and Bewilder
: In C++, overload library functions by using #define. That way it looks like you are using a familiar library function
where in actuality you are using something totally different.
Choosing The Best Overload Operator
: In C++, overload +,-,*,/ to do things totally unrelated to addition, subtraction etc. After all, if the Stroustroup
can use the shift operator to do I/O, why should you not be equally creative? If you overload +, make sure you do it in
a way that i = i + 5; has a totally different meaning from i += 5;
Here is an example of elevating overloading operator obfuscation to a high art. Overload the '!' operator for a class,
but have the overload have nothing to do with inverting or negating. Make it return an integer. Then, in order to get a
logical value for it, you must use '! !'. However, this inverts the logic, so [drum roll] you must use '! ! !'. Don’t
confuse the ! operator, which returns a boolean 0 or 1, with the ~ bitwise logical negation operator.
Overload new
: Overload the "new" operator - much more dangerous than overloading the +-/*. This can cause total havoc if
overloaded to do something different from it’s original function (but vital to the object’s function so it’s
very difficult to change). This should ensure users trying to create a dynamic instance get really stumped. You can
combine this with the case sensitivity trick: also have a member function, and variable called "New".
#define
: #define in C++ deserves an entire essay on its own to explore its rich possibilities for obfuscation. Use lower case #define
variables so they masquerade as ordinary variables. Never use parameters to your preprocessor functions. Do everything
with global #defines. One of the most imaginative uses of the preprocessor I have heard of was requiring five passes
through CPP before the code was ready to compile. Through clever use of defines and ifdefs, a master of obfuscation can
make header files declare different things depending on how many times they are included. This becomes especially
interesting when one header is included in another header. Here is a particularly devious example:
#ifndef DONE
#ifdef TWICE
// put stuff here to declare 3rd time around
void g(char* str);
#define DONE
#else // TWICE
#ifdef ONCE
// put stuff here to declare 2nd time around
void g(void* str);
#define TWICE
#else // ONCE
// put stuff here to declare 1st time around
void g(std::string str);
#define ONCE
#endif // ONCE
#endif // TWICE
#endif // DONE
This one gets fun when passing g() a char*, because a different version of g() will be called depending on how many
times the header was included.
Compiler Directives
: Compiler directives were designed with the express purpose of making the same code behave completely differently. Turn
the boolean short-circuiting directive on and off repeatedly and vigourously, as well as the long strings directive.
Red Herrings
Pepper your code with variables that are never used and methods that are never called. This is most easily done by
failing to remove code that is no longer used. You can save the code on grounds someday it may need to be revived. You
get bonus points if these drone variables and methods have names similar to actual worker ones. The maintenance
programmer will inevitably confuse the two. Changes made to drone code will happily compile, but have no effect.