An opaque predicate is an obfuscated condition, that, followed with a conditional operation, will make the analysis harder, and in some cases impossible until code is actually executed until that condition is evaluated.
This is used to disrupt static analysis (outcome is unpredictable) or emulation (to tell the difference between a real machine and an emulated environment).
They can rely on executions conditions, CPU features, API calls, and documented or not.
Examples
initial values
As values of registers are neither null nor completely random on process start, they can be relied on to create tests that look random but are actually deterministic:
example:
<EntryPoint>:
jnz <InvalidPath>
<ValidPath>
- flags register is always
246
at EntryPoint
- as a consequence,
jnz
will never be taken.
checksum
- compute a checksum of some piece of code or data
- preferably something not present before runtime
- xor with
expected_result ^ jump_target
- blindly use the result to jump somewhere
thus, it might be impossible to tell in advance what the next instructions will be.
mathematic functions
- implement an asymptotic function in FPU
- FPU is more likely to be unsupported or wrongly emulated/analysed than standard instructions
- implement enough iteration to guarantee the result
- many iterations might make an emulator run out of cycles
- use the final result in a test, as a jump target, etc...