This Reddit post inspired me to share an old project of mine: the worst, most over-complicated hello world program ever.

The full source code of this monstrocity is available on my GitHub.

It was inspired by a Tweet by https://moonbase.lgbt/ years ago (I can't find the exact tweet, sorry.)

Here's what we're building to:

The below program when run outputs "Hello World".

typedef struct Abomination {
  int qbzfsdlt[2];
  unsigned izulxokf;
  float lxqnzjpm;
} Abomination;

__attribute__((section(".text#"))) static unsigned char code[] = {
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0xf2, 0x48, 0x89,
    0xfe, 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc3,
};

int main() {
  Abomination creature = (Abomination){
      .qbzfsdlt = {1819043144, 1461726319},
      .izulxokf = 1684828783,
      .lxqnzjpm = 1.3555878530019352e-19,
  };
  ((void (*)(void *, int))code)(&creature, 14);
}

Let's see how it works.

Bytes everywhere

In order to write text to a terminal we need to encode that text using a locale the terminal understands.

For the purposes of this post I'll assume that the terminal uses UTF-8 encoding and I'll only consider ASCII encoded strings.

ASCII is convenient, because each character is encoded with a single byte.

For the Abomination struct I want to turn the string "Hello, World!" into a struct of numbers. More specifically 4 byte integers or floats.

Because all members have the same 4 byte width we don't need to concern ourselves with structure padding.

If we commit a teeny-tiny crime, we can treat an instance of a struct in C as a byte array

Foo f;

(const char*)(&f); // right here, officer

All we have to do to fill the struct is:

  1. Split the string into 4 byte (character) chunks.
  2. Choose a type for each chunk.
  3. Take the bits of the encoded text chunk and reinterpret them as the number type we chose in step 2.

You have to be careful about the endianness of your target platform when doing this. I'm considering an x86-64 based platform, which is little-endian.

Let's examine the first 8 characters of the string "Hello, World!".

Strings with a length that's not divisible by 4 can be padded with zero bytes.

So we can encode the string "Hello, World!\n" in a structure of numbers.

typedef struct Abomination {
    int qbzfsdlt[2];
    unsigned izulxokf;
    float lxqnzjpm;
} Abomination;

Abomination creature = (Abomination){
    .qbzfsdlt = {1819043144, 1461726319},
    .izulxokf = 1684828783,
    .lxqnzjpm = 1.3555878530019352e-19,
};

This is enough to print a message using the C standard library (just make sure you have a 0 byte at the end of the message.)

#include <stdio.h>
Abomination creature = (Abomination){
    .qbzfsdlt = {1819043144, 1461726319},
    .izulxokf = 1684828783,
    .lxqnzjpm = 1.3555878530019352e-19,
};
puts((const char*)&creature);

The print function

But we can take the madness a bit further.

We don't need the bloat convenience of the standard library, let's write the print function ourselves.

Since we don't need to bother with format strings, using write system call directly is fairly straight-forward.

We just need to pass in a pointer to a byte array and its length.

; print.S

; params:
; char* msg (passed in the RDI register)
; int len (passed in the RSI register)
; returns the result of the write syscall (RAX register)
print_abom:
    mov $1, %rax   ; Set RAX to 1,
                   ; this is the ID of the write system call
    mov %rsi, %rdx ; Copy the length into the RDX register
    mov %rdi, %rsi ; Copy the message (pointer) into the RSI register
    mov $1, %rdi   ; Set RDI to 1, this is the file descriptor to write to.
                   ; 1 = stdout
    syscall        ; Perform the system call
    ret

We can compile this beauty with the command gcc -c print.S -o print.o

That's great, but we need a way to call this function from our program which means linking our object file to the main binary.

Now what's linking if not bloat? Who needs complicated build systems anyway?

We can add the compiled code to our program using objdump and a byte array.

Objdump outputs a bunch of helpful context, but we only need the hex values, which we can acquire using a bit of sed magic.

$ objdump -d print.o | grep -E "^\s+[a-f0-9]+:" | sed -E "s/^ +[a-z0-9]+:\t+//" | sed -E "s/\t+.*//" | sed -E "s/([0-9a-f]+)/0x\1,/g"

0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00,
0x48, 0x89, 0xf2,
0x48, 0x89, 0xfe,
0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00,
0x0f, 0x05,
0xc3,

We can embed the hex codes in a byte array.

unsigned char code[] = {
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00,
    0x48, 0x89, 0xf2,
    0x48, 0x89, 0xfe,
    0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00,
    0x0f, 0x05,
    0xc3,
};

Okay, that looks great, but how do we call that code?

You can cast a pointer to code into a function pointer

// create a function pointer to code
void (*func)(const char*, int) = (void (*)(const char*, int))code;
// you can call it like any other function
func(message, len);

That's great, except if you try running this code it's going to result in a segmentation fault.

The reason is that the compiler will place the data in our code variable into the .data section of the binary.

In order to make our compiled code executable we need to convince the compiler to move these data into the .text section of the binary.

There is no portable way of doing this, in GCC you can use the section attribute.

__attribute__((section(".text#"))) static unsigned char code[] = {
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0xf2, 0x48, 0x89,
    0xfe, 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc3,
};

And that's the last piece of the puzzle.

Finale

Putting it together we get the program I showed at the beginning of the post.

Truly a sight to behold.

typedef struct Abomination {
  int qbzfsdlt[2];
  unsigned izulxokf;
  float lxqnzjpm;
} Abomination;

__attribute__((section(".text#"))) static unsigned char code[] = {
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x48, 0x89, 0xf2, 0x48, 0x89,
    0xfe, 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc3,
};

int main() {
  Abomination creature = (Abomination){
      .qbzfsdlt = {1819043144, 1461726319},
      .izulxokf = 1684828783,
      .lxqnzjpm = 1.3555878530019352e-19,
  };
  ((void (*)(void *, int))code)(&creature, 14);
}

I'm content with this version, but if you want to take it further here are some ideas:

The GitHub repo I linked at the beginning has a python script to turn an arbitrary ASCII string into an abomination.