Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A trick to prevent the compiler from constant folding out an expression

I have a string literal in my program, I'm trying to create an amateur checksum to ensure the string literal was not replaced in the portable executable.

To do this, I create a hash of the string literal, and store it as a integer literal in the program. Now I have two literals, one for the string and one for the hash.

In my code, I implement the checksum by using a function that hashes the string literal in the same way, I create a new runtime hash and check that hash against the hash literal.

The problem is of course, with compiler optimizations it may pre-compute the runtime hash, and then im checking a hash literal against a hash literal and the checksum will always return true.

So I'm looking for a trick to make the compiler think the string literal is a dynamic string that could be anything, so that it will not do the constant folding optimization on the runtime hash and my code will work correctly.

like image 824
Thomas Avatar asked Sep 06 '15 17:09

Thomas


1 Answers

You might perhaps declare the string literal as a const volatile, e.g.

const volatile char myliteral[] = "some literal string";

and you could also compute the hash at build time, e.g. have something in your build procedure to extract appropriate strings and separately compute the hash.

At last, if the string and its hash are in two different translation units (e.g. in file1.c and file2.c) you need link-time optimization to make the inlining happen at build time. With current GCC (i.e. GCC 4.9 or 5) you need to explicitly pass -flto at compile time and at link time to get link-time optimization, so if you don't do explicitly that (e.g. with CC=gcc -flto -O2 in your Makefile), it won't happen.

BTW, you might checksum the entire executable, or an entire shared library, or some given object file. Details are OS specific. On Linux see dlopen(3), dlsym(3), dladdr(3), dl_iterate_phdr(5), elf(5), proc(5)

Also, you could hash some random suffix substring of the initial literal (e.g. hash myliteral+random()%strlen(myliteral) at runtime) and keep and compare to the constant array of such partial hashes. The compiler is very unlikely to inline all of that!

I actually believe that it is not a real issue in practice: nobody would care about your executable, and nobody would spend time to decompile it.

BTW, you could generate a separate __timestamp.c file containing timestamp and checksum information (and I am doing that in my bismon project in summer 2018), and link it with your executable.

like image 197
Basile Starynkevitch Avatar answered Oct 24 '22 03:10

Basile Starynkevitch