1

The code below

if(str1 == "abc") {}

can be converted to

if(hash(str1) == 0x8732e) {} // assume hash("abc") == 0x8732e

to obfuscate the code.

But they are not equivalent when hash collision occurs; e.g., str1 = "xyz"'s hash value is the same as "abc".

That is true theoretically. But is it an issue in real-life when the method above is used to obfuscate code? Is it a well accepted obfuscation method?

5
  • 5
    You're saying "code" and "obfuscate code" but what you've provided is a method of obfuscating the value of a string -- and a somewhat poor one at that, as now the test is vulnerable to the collisions you mention. What are you really trying to accomplish?
    – alzee
    Aug 5, 2016 at 15:32
  • You can significantly reduce collisions by storing length of string with hash. Getting collision for two strings of same length is very unlikely.
    – Aria
    Aug 5, 2016 at 18:51
  • 2
    @Aria: Whether that's true or not depends on the hash function, but let's assume for now that it's true. The problem is, that dramatically narrows the search space for a brute-force attack on the hash. Unless your string is long enough that there are more collisions in strings of length 1 - (N-1) than there are in strings of length exactly N, you've made the attacker's job easier if you tell them the length. Depending on how predictable the string is (i.e. if you're picking from an already-narrowed range of options) revealing the length may dramatically speed the search
    – CBHacking
    Aug 5, 2016 at 18:57
  • 1
    Also posted on Crypto.SE. Please do not post the same question on multiple sites. Each community should have an honest shot at answering without anybody's time being wasted.
    – D.W.
    Aug 8, 2016 at 16:32
  • If this is for some sort of license key check, then be aware that someone who reverse engineered this code will simply patch the code to if (true) or something similar.
    – Lie Ryan
    Feb 21, 2019 at 9:28

2 Answers 2

4

The example hash digest you gave is wayyyyyyy too short (20 bits, or about a million possibilities), so you'd get collisions far too often and, worse, anybody who decompiled your program could trivially produce the correct strings (or, at least, strings that are acceptable due to hash collisions) just by brute-forcing the likely input space.

"That's a silly objection. It's just an example..." you might say, but it really isn't. I've found, and exploited, this exact type of weakness before. For example, there was a mobile app that used a 32-bit hash function on user inputs to try and hide what inputs would produce what outputs. It took under an hour to write, and run, a program that brute-forced the search space and found inputs that mapped to every hash digest the app was looking for.

In essence, this is much like trying to store passwords securely. There are definitely differences - passwords are rarely very long, while hardcoded strings in a program can be, and if you're performing the string equality test frequently then you can't afford for it to be as slow as a good password verify function would be - but a lot of the same parallels hold. Use a strong hash function, not just resilient to collisions and reversal but also ideally one that isn't so fast its possible to brute-force the whole search space. For short strings, use a salt so that people can't just look up the value in a rainbow table.

Now, as for actual obfuscation: this technique is one (of a great many) that obfuscation can use. It's usually not very effective, especially when implemented weakly (see my second paragraph), and has enough performance impact that it isn't usually used except selectively in places where the slowdown isn't a big deal. Obfuscation in general is a non-solution; at best it slows down reverse engineering enough that by the time the RE is complete the codebase is old enough nobody cares, without causing undue performance or program logic bugs in the meantime. In practice, though, it's usually not that good.

1

It's not useful

That doesn't really do a good job at obfuscating. If you check against specific strings, those strings probably will occur in the RAM at some point (even during normal usage). An attacker can simply hash the strings they find in the RAM of your program, find a collision, and replace the corresponding parts of the code with the string they found.

It's stupid

Furthermore, pretty much every reason to obfuscate code is stupid – but that's besides to point.

Don't do it

What you should see is that there is a risk of failure. Namely when a hash collision occurs. Because of the way hash functions are designed, for probabilistic calculations we can assume the output of the hash function to be random for every input we haven't tried yet.

If there are several hash values the hash of a varying string are compared to, you can calculate the rate of failure for that comparison using the approximative formula of the birthday paradox ](http://quicklatex.com/cache3/45/ql_670d776bee64464b0374f373c73fa445_l3.png) where [![]1
(source: quicklatex.com) is the size of the codomain of the hash function and
(source: quicklatex.com) is the number of different values the varying string will take.

Once you got that probability for every string comparison in your program, multiply them and call the number you get
(source: quicklatex.com) . The probability that the program will fail is ](http://quicklatex.com/cache3/f1/ql_68b660535c454533f648fe00f7bbccf1_l3.png). If the program will be executed [![]4
(source: quicklatex.com) times that way, the probability that it will fail is http://quicklatex.com/cache3/98/ql_9d24cd1aa3adc352b991541de5630a98_l3.png.

If you value the small amount of obfuscation more than you fear the consequences of your program failing with the probability of http://quicklatex.com/cache3/98/ql_9d24cd1aa3adc352b991541de5630a98_l3.png, do it. Otherwise don't.

2
  • some of the equation images return "404 not found"..
    – Amro
    May 20, 2017 at 9:36
  • Yeah, @UTF-8 if you're around, please repair the post. My bot usually makes good edits but failed rather miserably here.
    – Glorfindel
    Feb 21, 2019 at 9:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .