Numerical Signatures (with a Bit of Magic)

Posted by Mariia Mykhailova on 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:

  1. 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).
  2. Read a number from this string as unsigned long long, but write it to a double variable.
  3. 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

Freelance Jobs

blog comments powered by Disqus