Library / SDK
DosX-dev/obfus.h avatar
DosX-dev/obfus.h

obfus.h is a single header that rewrites your C control flow at compile time, and it needs TCC

Macro-header for compile-time C polymorphic obfuscation (tcc, win x86/x64)

1,876 stars163 forksCNOASSERTION

At a glance

What is it?
obfus.h is a macro-only obfuscation header for Windows x86 and x64, built around TinyCC 0.9.28rc, that turns if, switch and loop statements into a tangled graph of indirect transitions. The hard constraint is the compiler: if your build is GCC, Clang or MSVC, you have to restructure around a TCC-compiled DLL rather than just adding an include.
Who is it for?
obfus.h fits a Windows developer shipping a native component whose logic you would rather competitors not read, and who can isolate that component behind a TCC-built DLL interface. It does not fit a cross-platform codebase, a Linux or macOS build, or a project whose build system cannot be pointed at TinyCC, and the author recommends against it in production outside crackme and CTF work when fake signatures are involved.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The compiler requirement is the real API constraint

Start with the thing that decides whether you can use this at all. obfus.h is a macro-only library designed specifically for TinyCC 0.9.28rc on Windows x86 and x64, and the README points to a separate TinyCC-builder repository for the complete compiler package.

Most C projects do not build with TCC. If yours uses GCC, LLVM/Clang or Visual C, the header is not a drop-in, and no amount of macro definition will change that.

The README's recommended architecture for a larger project follows directly from this constraint. Isolate the logic you want protected into C DLLs compiled with TCC and obfuscated with obfus.h, then let the main application stay in C#, C++, another language, or C compiled with GCC, Clang or Visual C, calling those DLLs through their exported interfaces. That boundary is also what makes the tool usable at all, since it confines the unusual compiler to the part of the codebase where unusual output is acceptable.

Integration itself is trivial, which is the appeal:

c
#include "obfus.h"

That single line is the whole setup. The protection is baked into the output binary rather than applied afterwards, and IntelliSense keeps working, with no extra tools and no code generation step.

What actually gets obfuscated

The feature list is broad, so it is worth separating the mechanisms that change your code from the ones that add noise around it.

Function call obfuscation makes call targets harder to follow. Control flow code mutation, described as turning code into spaghetti, is the core of the tool. Strings hiding keeps specified strings in a file and collects them dynamically at execution time, so string literals do not sit in the binary where a reviewer expects them. Anti-decompilation techniques aim to visually break the output of popular decompilers.

Then there are three that are about confusing analysis rather than protecting logic. Anti-debugging mechanisms are built in, virtualization turns math operations into virtual machine commands that are hard to follow, and fake signatures add the signatures of various packers and protectors. The README warns specifically against the last of these outside crackme and CTF contexts, because fake protector signatures can trigger antivirus detections and cause tools such as Detect It Easy to flag the binary as suspicious.

Windows API protection is the feature most likely to matter to a desktop application, since common GUI and system calls are protected automatically with no extra setup.

Control Flow Explosion and the automatic keyword coverage

The mechanism behind the control-flow protection is described as Control Flow Explosion: straightforward conditions and loops expand into a tangled graph of branches, indirect transitions and fake functions. Polymorphic instruction sequences carry state and select continuations, which means you cannot simply strip them out without breaking execution, because the removed pieces are load-bearing.

Automatic protection transforms a specific list of keywords, and the list is worth reading as documentation of scope: `if`, `else`, `case`, `break`, `switch`, `while`, `for`, `return`, `continue`, `default` and `do`. Everything in that list is rewritten without you marking anything.

For explicit insertion instead of automatic coverage, two macros are provided, `BREAK_STACK_CFLOW;` and `STACK_PROXY_FUNCTIONS;`, and there are two switches to turn protection off, `OBFH_DISABLE_CONTROL_FLOW` for the automatic control-flow layer and `OBFH_DISABLE_ANY_OBFUSCATION` for everything.

Because the expansion varies with the source code, small edits reshape the generated instructions, constants and control-flow paths. That is a maintenance property as much as a protective one: a diff in your logic produces a much larger diff in the binary, which makes binary comparison a poor regression signal for protected builds.

OBFH_SEED is a build knob, not a password

All options must be defined before including the header, and the seed is the one you will touch most:

c
#define OBFH_SEED                     123456789u // Choose compile-time protection variants

It is an unsigned 32-bit build seed with a default of `0u`, and changing it varies the generated protection while leaving your program's behaviour alone. The README is careful about what it is not: it is not a secret and not a password, and identical binaries also depend on the source, the compiler and the build settings. So treating the seed as key material would be a mistake; treating it as a diversification knob is the intended use.

A command-line build can also use defines:

bash
tcc "app.c" -w  -D OBFH_DISABLE_CONTROL_FLOW  -D OBFH_BETTER_ANTIDEBUG  -D OBFH_FAKE_SIGNATURES

Older option names such as `OBFH_BUILD_SEED` still work but emit a `#warning`, and if both the old and new name are defined the `OBFH_*` option takes precedence. That is a deprecation done at compile time rather than at release time, which is the friendly version.

The option set and what each switch costs

The documented options separate into three groups: build settings, additional strengthening, and disabling.

On the strengthening side, `OBFH_BETTER_CONTROL_FLOW` is described as stronger control-flow protection with slower execution, which is the honest trade stated plainly. `OBFH_BETTER_ANTIDEBUG` adds hardware-breakpoint checks to the anti-debugging protection, which means a debugger using hardware breakpoints rather than software ones is what it is aimed at. `OBFH_FAKE_SIGNATURES` adds the fake protector and packer signatures, and carries the crackme/CTF-only warning.

On the disabling side, `OBFH_DISABLE_ANY_OBFUSCATION` for debugging sessions, `OBFH_DISABLE_CONTROL_FLOW` for the control-flow layer specifically, `OBFH_DISABLE_ANTIDEBUG` to drop the debugging protection, and `OBFH_DISABLE_PDATA_DECOYS` to turn off the additional x64 fake functions.

That last one is x64-specific, which is a reminder that this header has architecture-dependent behaviour and that x86 and x64 binaries are not simply the same protection at two widths.

Daily Crackmes and the honest limits the README states

The repository publishes a daily crackme under a rolling release tag, with four difficulty levels named Easy, Medium, Hardcore and Extreme. Each challenge has its own generated verification logic rather than just a different password, and the README frames them as a way to see the protection working in real binaries without setting up a compiler. The scheduler is set for 13:00 Moscow time, with the caveat that actual publication time depends on GitHub Actions being in the mood.

The project's own statement of limits is worth quoting in spirit rather than repeating: obfus.h significantly raises the barrier to reverse engineering but is not a panacea, and protecting trade secrets also requires internal mechanisms, so obfuscation should be one layer of a protection strategy rather than the whole of it.

The intended-use section places it as a full-featured tool rather than a proof of concept, for protecting selected native components containing sensitive logic, and it states a position on use: the project is intended to protect lawful software including commercial applications and crackmes, the author opposes malicious use, and projects involving malicious activity receive no support. That statement is explicitly not a licence condition.

The licence itself is a custom one that GitHub cannot classify, so if you are shipping this in a commercial binary, read the LICENSE file rather than assuming terms.

Editorial conclusion

obfus.h fits a Windows developer shipping a native component whose logic you would rather competitors not read, and who can isolate that component behind a TCC-built DLL interface. It does not fit a cross-platform codebase, a Linux or macOS build, or a project whose build system cannot be pointed at TinyCC, and the author recommends against it in production outside crackme and CTF work when fake signatures are involved. Verify first that your toolchain is TinyCC 0.9.28rc on Windows x86 or x64, then build once with OBFH_DISABLE_ANY_OBFUSCATION to confirm the rest of your code compiles before turning protection on.

Frequently asked questions

What compiler does obfus.h require?

It is designed specifically for TinyCC 0.9.28rc on Windows x86 and x64, with the compiler package distributed through the TinyCC-builder releases. For larger projects the README recommends isolating protected logic into C DLLs built with TCC and calling them from the main app.

What does OBFH_SEED do?

It is an unsigned 32-bit build seed, defaulting to 0u, that selects among compile-time protection variants while keeping program behaviour the same. The README states it is not a secret or a password, and identical binaries also depend on source, compiler and build settings.

Should I use OBFH_FAKE_SIGNATURES in production software?

No. The README reserves it for crackme and CTF challenges and warns that fake protector and packer signatures can trigger antivirus detections and cause tools such as Detect It Easy to flag the binary as suspicious or malicious.

Which C keywords get automatic control-flow protection?

if, else, case, break, switch, while, for, return, continue, default and do are all transformed automatically. For explicit insertion you can use BREAK_STACK_CFLOW; or STACK_PROXY_FUNCTIONS; instead.

How do I turn obfuscation off while debugging?

Define OBFH_DISABLE_ANY_OBFUSCATION before including the header. More targeted switches exist as well: OBFH_DISABLE_CONTROL_FLOW, OBFH_DISABLE_ANTIDEBUG and OBFH_DISABLE_PDATA_DECOYS.

What are the Daily Crackmes in the obfus.h repository?

They are automatically generated and built challenges at four difficulty levels, published under a rolling release tag, each with its own generated verification logic. The README notes the schedule is set for 13:00 Moscow time but actual publication depends on GitHub Actions.

Official sources

  1. DosX-dev/obfus.h on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dosx-dev-obfus-h.svg)](https://hysenlabs.com/projects/dosx-dev-obfus-h)