Numerical Signatures (with a Bit of Magic)

Posted byon January 31, 2011

I've always been fascinated by programming magic - small tricks which make seemingly meaningless code do something unexpected. The most famous of such tricks are "signatures", which output a short text (usually author's name). My previous post featured several unusual ways of printing text using esoteric programming languages, and (surprisingly) it helped someone to make their new-year greetings something special. But real magic is doing such things in common everyday languages, like C++ or Java. In this writeup I will show several ways to print short text using only numeric constants as raw data.

Disclaimer. Tricks given in C++ are based on low-level memory manipulations, thus the results may vary depending on platform and compiler. I'm using gcc 4.4.1 on 32-bit Ubuntu, and it all works fine for me, but the codes are not too portable.

C++ favors marginal manipulations with memory, pointers, bitwise representation of numbers and stuff like that, so obfuscations like representing a string as a number are almost common for this language. The simplest example follows:

#include <stdio.h> int main() { int A = 2037539149 ; printf(( char *)&A); }

How does it work? The first (and the only one which is really necessary) parameter of printf function is char * format, which describes the format of the output. Usually it is a constant string, and variable part of the output is formed using later parameters. However, using simply a char * variable works as well, though the compiler warns that "format not a string literal and no format arguments". (char *)&A treats the pointer to varible A as a pointer to character array, regardless of what the type of variable A really is. After realizing this, the things are easy: put into A bytes which will be interpreted as the required word: for "Mary" it will be 0x4D 0x61 0x72 0x79 -> hexadecimal 0x7972614D (bytes are reversed, since characters are printed from lowest order byte to highest order) -> decimal 2037539149.

The limitation of this method is that it can output only 4 intended characters, after that things go really random - the "string" we output has no end-of-string character, so it proceeds to next bytes in memory. For a clean job, you should output 3 characters you want and end-of-string after them. Replacing the data type with unsigned long long allows to extend the message to 8 characters (or 7 + end-of-string):

#include <stdio.h> int main() { unsigned long long A = 8751164009814452552ULL ; printf(( char *)&A); }

Let's complicate the task and move from integer numbers to floating-point ones; less people understand their intrinsic details, so this increases obfuscation level. The simplest example is:

#include <stdio.h> int main() { double A = 2.222663600523023e-313 ; printf(( char *)&A); }

How does this work? In exactly the same way as previous ones, except for that the constant to output is trickier to construct. To output "Mary" + line feed, we need bytes 0x4D 0x61 0x72 0x79 0x0A placed in memory. To find a constant which is written using these bytes, one can use the following hack:

Write the bytes to a string as a hexadecimal number, same as before: "A7972614D" (decimal works the same, but converting the bytes to it is an extra step). Read a number from this string as unsigned long long, but write it to a double variable. The resulting double variable print with maximal possible precision, for example, using STL tools.

#include <stdio.h> #include <iostream> #include <iomanip> #include <limits> using namespace std; int main() { double a; sscanf( "A7972614D" , "%llx" , ( unsigned long long *)&a); cout << setprecision (numeric_limits< double >::digits10 + 1 ) << a << endl; }

If desired, the code can be complicated some more, for example, the printed value can be given not immediately but as a result of some calculation. It would be really cool to get some text from magic constants of Pi, E, golden ratio etc. This particular writeup has been inspired with a lovely recursive signature like this (the constant is fixed to print my name):

#include <stdio.h> double x = 0.003609087829883 , y; int main() { return(*( char *)&x?x*=y=x,main():printf(( char *)&y)); }

After adding some whitespace and some debug output one can find out that this snippet recursively squares x and prints the last non-zero power of it (once again as a string). A text of 4 characters is represented with a constant of order of magnitude 10-300, so the square of this constant really becomes 0. The initial constant in the code is calculated as a square root (applied several times) of text's constant.

A lot of languages deny the programmer that level of liberty in memory manipulation, so one has to use something more traditional - representing the number in non-decimal base. Was my name Ada, I could have done it with hexadecimal, but Mary requires a base of at least 35, and preferably 36:

public class Magic { public static void main ( String [] args) { System . out . println ( Integer . toString ( 1040398 , 36 )); } }

Sincerely yours,

1446440069272325681930

blog comments powered by Disqus