Research
How to Protect a Go Program in 2026 — Recommended Stack, Measured Results, and Architecture Limits
Pin Go 1.26.5 + Garble v0.16.0, transform sensitive private packages, and sign last; keep connected value behind a calibrated 10-minute server capability; commercial tools remain POCs: VMProtect for offline use, Themida for Windows apps, WinLicense for licensing, Code Virtualizer for selected regions, and Virbox for multi-platform CLI; keep packers and hard-fail anti-analysis outside the default.

In this article
1 What to deploy now: the default protection stack for a Go product
Decision: as of July 26, 2026, every paid Go program should begin with the pinned Go 1.26.5 + Garble v0.16.0 release baseline; connected high-value features should then keep durable authority and critical execution on the server. Public commercial evidence currently supports an order for licensed POCs; no product has reached the production-evidence bar. Garble control flow also remains an experimental POC covering only the small, cold path formed by eligibility calculation and the caller's final decision. The table below can be turned directly into build, architecture, and procurement tickets.
Seven control points lie between a source commit and a paid operation: release cleanup; Go-native name and literal transformation; post-link metadata processing; loading or virtualization; integrity and runtime signals; differentiated releases; and server-side authority. The first three change discovery and understanding, the middle two change observation and modification at runtime, diversity reduces reuse across releases and customers, and the server boundary determines how much value a modified client can redeem. Every tool discussed later has one defined job at one of these points.
| Job | Current default or first POC | Target and placement | Evidence level | Pass and exit conditions |
|---|---|---|---|---|
| Release baseline for every paid Go program | Go 1.26.5 + Garble v0.16.0 | Transform only sensitive private packages. Start with names, paths, and release metadata; add -literals to text that directly exposes a paid path. Apply the platform signature after all post-processing. | Production baseline, requalified on version changes. A signed release and pinned source are reviewable; local artifacts passed 140 positive and negative entitlement controls plus static, Delve, performance, and reproducibility checks. | Release only if behavior controls pass, the seed reverses stacks, and performance and crash evidence stay within budget. On failure, restore the previous signed artifact and retain an ordinary control from the same commit. |
| Authority for connected high-value features | A 10-minute capability as the SOSEC starting value, calibrated locally within 5–15 minutes | Keep authorization decisions, replay windows, revocation, and critical business execution on the server. The client receives only a short-lived token bound to audience, account, device, and feature. | Production architectural default, calibrated per product. The controlled experiment verifies signed-entitlement authenticity; capacity and abuse behavior for a large live product require local measurement. | Test expiry, replay, revocation, concurrency, and network failure. During an outage, fall back to the promised basic, read-only, or short-grace mode; never silently mint durable authority. |
| General virtualization for valuable offline software | VMProtect 3.10.6 | Begin with one cold path covering both the inner eligibility calculation and the caller's final decision. Cross-platform or ARM64 products start here. | The next evidence gate is a licensed POC. Official material directly lists Go and the target platforms; the signed local demo reached only a wrapper workflow and did not produce a production-grade protected target. | Require a fixed project, license state, and hashes from the supplier. Stop on any accepted negative control, undiagnosable crash, update or signing failure, endpoint conflict, or budget overrun. |
| Whole-application Windows protection, loader, and packing | Themida 3.2.5.0 | Native Windows x86/x64 EXE or DLL. Establish compatibility with the smallest protection profile, then add loader, virtualization, or runtime controls one at a time. | The next evidence gate is a licensed POC. Official material lists Go gc; the local demo only confirmed that the CLI needs a GUI-created project and did not produce the current protected target. | The vendor project must build, update, and sign reproducibly. Exit if a GUI-only workflow cannot enter CI, legitimate customer behavior changes, or the final artifact cannot be diagnosed. |
| Protection integrated with vendor license and trial management | WinLicense 3.2.5.0 | Windows x86/x64 applications. Enter only when the product needs vendor-managed licenses, trials, hardware locks, and registration workflows. | The next evidence gate is a licensed POC. Current evidence consists of official product and Go-support material; this study has no local WinLicense artifact. | Run it in parallel with the buyer's existing signed entitlement. Stop procurement if migration, offline recovery, customer support, or key governance is weaker than the current system. |
| A few cross-platform, high-value code regions | Code Virtualizer 3.2.5.0 | Selected x86/x64/ARM64 regions on Windows, Linux, and macOS. Mark both eligibility and the caller path that consumes the result. | The next evidence gate is a licensed POC. Platforms, architectures, and Go gc have official support material; this study has no local protected artifact. | Accept only a small, cold region. Exit on missed placement, ABI or crash regression, hot-path budget failure, or inconsistent cross-platform behavior. |
| Multi-platform native and CLI vendor workflow | Virbox Protector Native 3.6.0.22848 | Products needing one vendor across Windows, Linux, macOS, ARM, and CLI integration. Begin with one real cold path. | The next evidence gate is a fixed, licensed POC. Official documentation and a download version can be pinned; this study has no local artifact with version, hash, signer, and license state fixed together. | First obtain a verifiable installer and license boundary. Exit if the project is not reproducible, high-false-positive hard failure cannot be disabled, or updates and signing are unstable. |
Garble is the only open-source project currently able to carry the default Go-native obfuscation baseline. gostrip has the narrower job of processing selected metadata in an existing Go artifact; Aurum-OBF remains a Windows targeted-string and overlay experiment; and the pinned alosgarble upstream commit did not build cleanly. UPX compresses files, -tiny removes panic, fatal, and debugging output, global anti-debug or anti-VM hard failure collides with EDR, CI, accessibility tools, and customer support, and whole-program virtualization spreads cost across low-value code. These options require a separate objective and do not enter a release automatically with Garble.
This report uses four reproducible proxies for "analysis cost": whether old name or literal entry points still match directly, whether Go-aware structure can be recovered, whether the original debugger workflow still works, and whether one result transfers across builds. It also measures owner-side file size, startup, hot-path, and reproducibility costs. Analyst-hours, time to a completed bypass, and adversarial results on a large product remain unmeasured. A parser exit therefore records that the corresponding automated route needs repair or replacement.
1.1 A build order, placement rule, and rollback plan an engineering team can use
The controlled entitlement path verifies an Ed25519 signature and claims in parseAndVerifyLicense, computes eligibility in featureGate, and makes the caller-side decision in allowPremium. Go defines the pcHeader and moduledata structures in go1.26.5/src/runtime/symtab.go lines 376–451; they retain function names, files, PCs, types, text ranges, and initialization relationships required by the runtime. src/debug/buildinfo/buildinfo.go lines 55–98 define readable embedded build information. Ordinary stripping leaves much of this Go-aware structural map, so the baseline treats names, paths, and literals as separate surfaces.
Signed Garble v0.16.0, commit 60a6019f196ece4da360038f905b6c154426a64a, exposes literal, tiny, and seed controls in main.go lines 113–128, while internal/literals/literals.go lines 39–60 rewrite literals into runtime expressions. Control flow has a different evidence level: pinned docs/CONTROLFLOW.md calls it experimental and requires GARBLE_EXPERIMENTAL_CONTROLFLOW=1; internal/ctrlflow/ctrlflow.go lines 100–135 accept function-level directives. The release ticket below keeps the stable baseline separate from that POC.
Every paid program: establish an operable open-source baseline
- Pin together
- Record Go
1.26.5, Garblev0.16.0, source and dependency commits, and the build container. Garble uses the Go found on PATH, so upgrade them as one compatibility set. UseGOGARBLEto restrict transformation to private packages instead of rewriting every dependency. - Build
- Start with
-buildvcs=false -trimpath -ldflags="-s -w -buildid=". For sensitive packages usegarble -seed=<stored-base64-seed> -literals build …. Keep an ordinary build from the same commit as the behavior, performance, and crash reference. - Order
- Finish source and resource changes, compilation, justified post-link work, commercial protection, and installer processing before Authenticode, Apple notarization, or platform signing. Any later byte change creates a new artifact that must be signed and accepted again.
- Retain
- Store the seed, reverse maps, symbols, input and output SHA-256, tool hashes, and an unprotected rollback artifact privately. Losing the seed removes the supported
garble reversepath during an incident.
Paid offline features: signed entitlement plus the caller decision
- Authority
- The client carries only the public key for a signature scheme such as Ed25519. Issuer private keys and long-lived symmetric secrets remain in controlled services. Claims bind at least product, feature, customer, expiry, and entitlement version; parse failures, missing fields, and bad signatures all take a deny path.
- Placement
- Treat eligibility calculation and the caller branch that consumes it as one protection unit. Transforming only a verifier helper leaves a cheaper final decision. Garble control flow currently belongs only in an experimental POC. It and commercial virtualization should cover a small, cold, stable, valuable slice and be measured at p50 and p95 on the real workload.
- Transfer
- Change the seed per release and add per-customer watermarks or differentiated builds only when artifact governance can support them. A result from one sample then transfers less directly to the next release or customer, while the release system assumes the map, signing, support, and rollback ledger.
- Offline ceiling
- The device ultimately receives long-lived local execution authority. High-value products can add TPM-backed keys, device certificates, hardware tokens, and periodic renewal, with explicit offline grace, machine replacement, clock anomaly, and customer recovery behavior.
Connected high-value features: keep redeemable authority on the server
- Token
- Issue a 5–15 minute capability bound to
audience, account, device, feature, expiry, and session or nonce. Refresh before expiry; keep replay windows, concurrency, rate, revocation, and risk state on the server. - Execution
- Keep premium data, models, rule sets, or critical computation on the server. Client obfuscation protects protocol details, caches, and finite offline assets, while every high-value request receives a fresh server authorization decision.
- Failure
- Preserve basic functionality during connectivity failure. Premium operations enter a product-defined short grace period, read-only mode, or explicit denial. A grace token still needs a bounded audience, device, and maximum life.
- Response
- Abnormal devices, replay, concurrency drift, or a leaked watermark trigger rate limits, challenges, revocation, and targeted updates. The client layers then create a response window the defender can use.
Commercial POC and final acceptance: test one job at a time
- Job boundary
- Select one job and its first POC from the opening table. Admit a backup only when that candidate lacks the target platform or a required capability, or meets an exit condition. Require the supplier to return a fixed installer, license state, project, commands, logs, and input/output hashes.
- Controls
- A valid entitlement succeeds; bad signature, expiry, wrong product, wrong feature, damaged encodings, and missing files reject. Then test name and literal recovery, inner and caller placements, debugger and memory observation, startup and hot path, crash, update, signing, and endpoint behavior on the final artifact.
- Rollback gate
- Any legitimate behavior change, negative-control acceptance, undiagnosable crash, budget overrun, failed update, invalid signature, or endpoint conflict removes that configuration from the release. Keep the previous signed artifact and a switch that disables each protection layer independently.
- Excluded by default
- UPX,
-tiny, gostrip, Aurum-OBF, global anti-debug hard failure, and whole-program virtualization each need a separate measured objective. Release evidence comes from the corresponding behavior, cost, and compatibility acceptance tests.
Every final artifact reruns the same behavior suite: a valid entitlement succeeds; bad signature, expiry, wrong product, wrong feature, empty customer, three damaged encodings, and a missing file fail in the prescribed way. The team then compares startup, hot path, crash observability, install/update behavior, and endpoint compatibility with the ordinary build. Release begins with a single-customer or low-volume canary. Disabling a protection layer produces a newly generated, signed, and hashed artifact; the team never patches an already signed file in the field.
1.2 One paid feature is found through four routes, and four layers cover different work
Consider a premium export feature. The first route begins with its name, error text, service URL, and package path; Garble's name and path rewriting, -literals, and release cleanup raise that discovery cost. The second route skips the inner verifier and follows whether the caller executes the export; control flow or commercial virtualization must include the cold path that finally consumes the result. The third route turns one analysis into a locator reusable across releases and customers; new seeds, differentiated builds, and watermarks make an old result expire sooner. The fourth route abuses an already entitled client; short-lived capabilities, device and replay controls, server execution, and revocation restrict the value it can keep obtaining.
The four layers have different jobs. Names, literals, and metadata change initial location. Code shape and placement change understanding and observation. Diversity changes batch transfer. Server architecture changes authority. A fully offline program can increase the first three costs and will still make the final allow-or-deny decision locally. That fact sets the spending order: close the cheapest scalable routes first, then move genuinely valuable authority and business capability out of the customer process.
2 Thirteen method families form five engineering layers around a Go program
The complete map is easier to use as five layers. The first reduces what the release gives away. The second changes names, data, and code shape before or during compilation. The third changes the generated executable and its loading path. The fourth observes or reacts to analysis and modification at runtime. The fifth controls how releases differ, how incidents are detected, and where authorization lives. These layers compose, yet each has a distinct recovery route and owner-side cost.
The thirteen families are build hygiene; Go-aware metadata; literals and resources; code shape; alternate code generation and boundary movement; build diversity and watermarking; packing and loaders; binary mutation and virtualization; anti-static measures; anti-dynamic measures; integrity and self-checking; secret and authority architecture; and release, detection, and recovery. Ephemeral code or data protection crosses loader, virtualization, and anti-dynamic work as a runtime placement pattern; it does not create a fourteenth family. PIE, DEP, CFG, CET, and platform code signing remain adjacent security baselines with separate acceptance tests. This boundary gives every method a stage, a recovery route, positive and negative controls, and an operating owner.
2.1 Release hygiene, Go metadata, and shipped data control the first discovery pass
Build hygiene includes -trimpath, -s -w, removal of unintended VCS and module details, an intentional build-ID policy, clean version resources, and exclusion of test endpoints, debug logs, sample credentials, and unused assets. The Go command documents -trimpath as removing file-system paths and documents -toolexec as a hook around toolchain programs. The Go linker documents -s as omitting the symbol table and debug information and implying -w. These are low-risk release controls. They reduce easy context; they do not remove every structure needed by the runtime.
Platform hardening belongs beside that baseline with a clear label. PIE/ASLR, DEP, CFG, and CET reduce memory-corruption exploitability. Microsoft describes CFG as restricting valid indirect-call targets. Code signing lets the platform verify that signed bytes have not changed and associate them with a publisher. Both are valuable product security controls. Their acceptance tests concern exploit mitigation, file identity, and execution policy. Reverse-engineering resistance requires separate evidence.
Go-aware metadata processing targets pclntab, moduledata, build information, function and file tables, type links, method names, and source positions. Garble changes names and paths through the compiler pipeline; gostrip performs narrow post-link processing. A private linker or post-linker can apply a more product-specific policy. Reflection, exported APIs, serialization, plugins, stack traces, profiler data, crash dumps, and version-sensitive runtime layouts limit what can safely disappear. The release must keep private symbols, maps, seeds, and exact artifact identity for support.
Literal, constant, resource, and data-layout transformation covers string splitting, runtime reconstruction, encrypted pools, per-use decoding, resource containers, and custom lookup tables. The useful target is cheap static search: service URLs, protocol markers, feature names, error text, and high-value constants. Base64 and a fixed XOR loop hide text from one representation. AES with a key stored beside the decryptor has the same authority ceiling. OS keystores, TPM-backed keys, hardware tokens, and white-box techniques can increase extraction or cloning cost. A value that the local process must consume still appears in a usable form during execution.
2.2 Code-shape transformation must survive Go's compiler before it can tax an analyst
Code-shape methods include inlining control, function splitting or merging, outlining, indirect calls, interface dispatch, control-flow flattening, opaque predicates, bogus branches, block reordering, constant blinding, mixed Boolean-arithmetic expressions, instruction substitution, data encoding, and custom stack or register layouts. Junk functions, decoy literals, and fake error paths try to increase search noise. A small interpreter with a private bytecode moves selected logic into light virtualization. Each technique must be judged on the final machine code and runtime behavior because Go can inline thin wrappers, fold constants, merge literals, and delete unreachable work.
Compiler and boundary diversification changes the code generator itself. A custom cmd/compile or linker pass, a -toolexec wrapper, assembly, cgo, or a C/C++/Rust library can move selected logic outside the usual Go source-to-binary path. TinyGo uses LLVM and generates a different runtime surface; its current compatibility table also shows that importability and passing the standard-library tests are separate, with packages such as debug/buildinfo and debug/gosym unavailable. Gccgo uses the GCC frontend and has a different runtime and toolchain, while the official Go page documents significant language and library-version limits. A changed binary shape can invalidate an old locator. It also adds ABI, GC, cross-compilation, dependency, crash, and upgrade work. An alternate compiler earns a place only after the real product passes compatibility and cost controls.
Build diversity and watermarking vary seeds, identifiers, literal encodings, block layouts, virtual instruction sets, and customer-specific marks. Their main job is transfer cost: one analyzed sample should produce less reusable automation for the next release or customer. Diversity also weakens reproducibility and cache efficiency unless the team records every seed, mapping, toolchain, customer assignment, and artifact hash. A watermark should support an evidentiary process and withstand ordinary repackaging; a plaintext customer ID serves only as a locator.
2.3 Packers, virtual machines, anti-analysis, and integrity move work into runtime
Packing and loader protection compress or encrypt sections, rebuild imports, and restore code or data during startup. A general compressor changes disk representation and size. A protection loader may add runtime decryption, import hiding, memory cleanup, and checks around the restored image. Evaluation therefore inspects the file before launch, the running memory image, available official unpacking, and generic dump-and-rebuild paths. Restoration of the underlying analysis surface is a stronger observation than byte-for-byte restoration and is enough to re-enable many earlier tools.
Ephemeral code and data protection narrows the observation window after loading. A protector can decrypt one function or asset immediately before use, change page permissions, execute it, erase the clear representation, and restore the protected form. Keys may be derived from a session, device relationship, or server challenge. The test asks how long usable bytes remain, how many threads can enter the region, whether a dump taken during execution contains them, and whether a hook can capture the output at its consumer. Go adds practical constraints: goroutine scheduling, stack growth, copies retained in GC-managed memory, panic paths, and concurrent callers can extend lifetimes or create crashes. This method can raise timing and instrumentation work; it also requires race, crash, suspend/resume, and update testing on every supported platform.
Binary mutation and virtualization operate below Go source names. Mutation substitutes instruction sequences and reshapes control flow. Virtualization translates selected functions into a custom instruction set interpreted by an embedded virtual machine. Per-build virtual machines can also raise transfer cost. The protected region should remain small, cold, stable, and valuable. A marker wrapped only around an inner signature check may leave its prologue or the caller's final decision as a simpler target; VMProtect's own manual discusses whole-function selection and protecting the business procedure that consumes a registration result. Placement is an engineering variable.
Anti-static measures hide imports, use indirect or table-driven dispatch, disturb code and data layout, and reduce catalog information that an analyzer expects. Acceptance records ordinary string and disassembly results, Go-aware recovery results, and a manual reachability path separately. Making one parser exit closes one automation route. A malformed executable crafted to crash a parser creates compatibility and ecosystem risk and falls outside the recommended set.
Anti-dynamic measures detect debuggers, breakpoints, hooks, instrumentation frameworks, injected modules, emulators, VMs, sandboxes, timing anomalies, and memory dumps. Watchdogs and paired processes can repeat those checks. Every signal has evasion and false-positive paths. Enterprise EDR, accessibility tools, compatibility layers, CI, crash capture, and legitimate customer debugging can look similar to analysis. Production designs use these signals for delay, risk scoring, and telemetry, with a support path for legitimate environments. Acceptance needs a hit control, a clean-environment negative control, failure recovery, and compatibility testing on the final release image.
Integrity and self-checking cover platform signatures, signed manifests, section or function hashes, resource validation, memory-page checks, distributed cross-checks, and remote challenges. The check, expected value, and failure branch reside somewhere. A client-resident implementation can be studied together with the code it measures, so distribution and redundancy increase work without changing final authority. Pipeline order matters: source transformation, compilation, post-link metadata work, commercial protection, resource processing, and packing must settle before the final platform signature. Internal integrity metadata must also bind the layout stage it expects.
Authorization and secret architecture completes the map. Signed offline licenses prevent unauthorized claim creation when issuer keys remain protected. Device keys and hardware tokens raise cloning cost. Short-lived leases, nonce and replay controls, account and device binding, revocation, rate and concurrency limits, and risk telemetry reduce the life and reach of a copied capability. Keeping premium computation, datasets, or model invocation on the server removes that value from the distributed executable. This family changes the authority budget and gives all client-side delay layers a response mechanism.
3 Go's runtime keeps a structural map after ordinary linker stripping
Go binaries are unusually self-describing because goroutine stacks, garbage collection, panic reporting, reflection, interfaces, and runtime symbolization need structured data. At Go 1.26.5, pcHeader carries function and file counts plus offsets to function names, compilation units, files, PC tables, and line tables. moduledata points to those tables and also records text ranges, types, type links, interface links, module names, initialization tasks, and related runtime state. A traditional native-symbol view captures only part of this surface.
The normalized baseline used -buildvcs=false -trimpath -ldflags="-buildid=". It was 3,626,496 bytes and exposed the module path, three decision-function names, and three business strings among seven declared markers. GoReSym identified Go 1.26.5, 373 user functions, roughly 2,361 standard-library functions, 11,943 types, and 1,025 strings. Redress recovered build and module context. Delve set a breakpoint by main.allowPremium, reached the source line, and read arguments.
Adding -s -w cut the file to 2,492,928 bytes. All seven markers remained. GoReSym returned the same 373 user functions and 11,943 types, and Redress retained the decision names and module information. Delve could no longer resolve the same source-name breakpoint, while the bad-signature control still ran under the debugger and exited with status 3. The result separates three surfaces: ordinary debug symbols, Go runtime topology, and runtime execution. Removing one entry route can still be useful; its acceptance claim should name that route.
3.1 The compiler-survival experiment removes several attractive source-level illusions
A second controlled program tested five small source tricks under the same go1.26.5 windows/amd64 toolchain. One build used normal optimization; the other used -gcflags=all=-N -gcflags=all=-l. The default artifact SHA-256 is 5226BC52FEF4186E27D15D0BEDB466F6FD61426F078506E2F9F46CABFFF0C9FF; the no-optimization artifact SHA-256 is 096C86C49A97CA72A0C5D6601A98CFFBC1E5D8EED9CE055EDC343D93C5B60D07. Both produced the same intended runtime output.
A marker split into two source constants appeared in the executable as the complete plaintext SOSEC-LAB-COMPILE-FOLDED. A decoy inside if false disappeared from both artifacts, including the build with ordinary optimization disabled. GoReSym found no main.naiveSplit, main.deadDecoy, or main.thinWrapper in the normal artifact; all three had function records when inlining was disabled. Go's pinned src/cmd/compile/internal/inline/inl.go lines 5–17 describe the two inlining passes and the -l control that the experiment exercises.
A //go:noinline wrapper survived in both builds. It preserved the intended function boundary and simultaneously created a stable boundary that tools could name. A runtime XOR decoder kept SOSEC-LAB-RUNTIME-DECODE out of both files and printed it correctly. The same executable carried the byte array, fixed 0x25 key, decoder loop, and plaintext use point. The method successfully defeats one static string query and adds no secret storage.
This produces a compiler-survival gate for every source obfuscator. First show the transformed construct in the released binary. Then show that the valid behavior still works and invalid behavior still fails. Next measure which earlier analysis route lost direct transfer. Finally count the performance, diagnostic, and maintenance cost required to keep the construct alive. A complicated source diff and a successful build close none of those later questions.
4 The controlled variants show where cost moves and where the same surface returns
The main experiment used one Ed25519 entitlement program, fixed time and input, separate writable caches, and ten exact-output controls for every artifact state. Evidence advanced in steps: public or repository claim; pinned version, source, release authenticity, and tool hash; successful output plus static inspection; valid and invalid runtime controls; then performance, debugger, unpacking, integrity, or compatibility evidence. The open-source core reached the final two levels. Commercial products remained at documentation, artifact-identity, or limited output-generation levels.
| Artifact or configuration | Measured change | Work it actually changes | Effect on the default |
|---|---|---|---|
-s -w release stripping | 3,626,496 fell to 2,492,928 bytes; all seven markers remained, GoReSym still recovered 373 user functions and 11,943 types, and the original Delve name breakpoint failed. | Removes ordinary debug-symbol entry points while retaining most Go runtime structure. | Keep as low-risk release hygiene; it does not replace Go-native obfuscation. |
| Base Garble v0.16.0 | 2,678,272 bytes; the module path and three business-function names lost direct matches, three business literals remained, GoReSym, Redress, and the original name breakpoint exited, and two builds matched. | Raises the cost of beginning from names, paths, and Go-aware parsers. | The sole open-source default; pin and upgrade it with the Go toolchain. |
Garble -literals | All seven selected markers left direct matching; the artifact grew to 5,578,752 bytes and still reconstructs plaintext at runtime. | Pushes cheap searches for URLs, protocol fields, feature names, and errors into runtime work. | Enable only for private packages and literals that directly expose a sensitive path. |
Garble -tiny | The artifact was 2,311,680 bytes and retained three business literals; panic, fatal, trace, and more position data disappeared. | Reduces diagnostics and some name entry points while removing evidence that support teams need in the field. | Exclude by default; admit only when the loss of diagnostics is accepted explicitly. |
gostrip df648e23621c | Ten controls passed, four of seven markers remained, GoReSym exited, and Redress no longer recovered the module path. | Narrows selected post-link metadata in an existing Go executable. | Run a separate objective-led POC and own per-Go-version, reflection, plugin, and panic-stack regressions. |
Aurum-OBF 9d703c54c923 | One URL and two strings changed and all ten controls passed; GoReSym still recovered 376 user functions, 11,943 types, the module path, and three business-function names. | Removes a few selected plaintext values and experiments with an overlay manifest. | Experimental candidate; keep out of production until error handling, reproducibility, updates, and platform work are complete. |
| UPX 5.2.0 | The stripped artifact compressed to 828,416 bytes and Garble literals to 1,647,104; packing hid directories, while official unpacking restored functions, types, strings, and decision names. | Compresses the file and adds a reversible unpacking step; startup p50 increased materially. | Use only for a size objective; do not count it as an anti-cracking baseline. |
| Experimental Garble control flow | Inner and caller placements passed ten controls; expanding to the caller widened the hot-path increase, and the cumulative build drifted by four .rdata bytes. | Moves the direct route to the caller decision into transformed code while adding performance, diagnostic, and artifact-identity cost. | Use only in an isolated cold-path POC; it is not a release default. |
Base Garble has the strongest open-source evidence in the census: the release is signed and pinnable, the mechanism is source-visible, and local artifacts completed functional, visibility, debugger, performance, and reproducibility checks. -literals moves selected static entry points into runtime expressions and fits a small amount of text that directly reveals a paid path. The maintainer documents that sufficient effort can still recover those values, so this result establishes only a changed search route.
-tiny and gostrip address different problems. The former deliberately trades away panic and trace evidence; the latter rewrites selected function-name entries and clears inline build information in an ordinary Go artifact. gostrip still needs per-version POCs for reflection, panic stacks, plugins, cross-platform behavior, and large programs. Aurum-OBF's internal/manifest/overlay.go lines 49–105 use an unkeyed SHA-256 footer on the ordinary path and HMAC only when an external authentication key is supplied; one CLI output mode returned null and another panicked, leaving production error and update semantics open.
Packed UPX artifacts made current GoReSym exit, while Delve returned "not an executable file" when launching either input; runtime debugging remained outside this test. Official upx -d on the stripped sample changed the file hash and restored Go 1.26.5, 373 user functions, 11,943 types, 1,025 strings, the module path, and three decision names. The Garble sample returned to the Garble-literals visibility boundary. UPX explicitly disclaims protection or encryption, fixing its role here as size optimization.
4.1 Placement changes both the analyst's route and the product's hot-path bill
This control-flow test used a Garble feature explicitly marked experimental, set GARBLE_EXPERIMENTAL_CONTROLFLOW=1, fixed block_splits=4 junk_jumps=16 flatten_passes=2, and combined the transformation with -literals -tiny. One artifact protected featureGate. The cumulative artifact protected featureGate and allowPremium. Both passed ten controls and removed direct matches for the chosen names, paths, and literals. The second placement forces a route aimed at the caller-side decision to enter transformed code as well. Its current production status remains an isolated POC.
Two performance runs rotated execution order. Each variant received two warm-ups and 15 independent hot-path processes, each verifying 5,000 valid entitlements. Startup received three warm-ups and 30 measured processes. Baseline hot-path p50 moved from 59.73 to 76.40 microseconds between runs on a shared host. Inner control flow added 6.16% and 6.27%. Inner plus caller added 29.80% and 13.20%. The stable inner increment and the wider cumulative range support one bounded result: broader placement increased cost and variability in this fixture. A real program needs the same test on its own cold and hot paths.
UPX concentrated cost at startup. The stripped packed artifact ran at 5.69× and 6.10× baseline startup p50; Garble literals plus UPX ran at 8.22× and 8.81×. Hot-path direction for those artifacts changed between runs, leaving no stable large signal there. A resident desktop application may pay unpacking once. A CLI, updater, serverless task, or ephemeral worker pays on every launch. File-size, startup, update, crash, and endpoint-security budgets therefore need separate fields.
The cumulative control-flow build also exposed a reproducibility boundary. Two fresh-cache outputs with the same seed and identical 4,985,344-byte size had different hashes. Four bytes differed in a runtime PC table in .rdata; .text and the other seven PE sections matched. Five debug-directory builds produced three generated-source hashes whose visible difference was the order of variable-type declaration groups. Pinned Garble internal/ssa2ast/func.go lines 1121–1149 group declarations through two maps, sort names within a group, and leave group order unsorted. This is repository-derived localization with no upstream confirmation. Teams requiring matching dual builds should hold that experimental parameter set until the drift receives an independently reviewed fix or an explicit artifact-identity policy.
5 The market census is broad at the method level and narrow at the production-evidence level
The public product and repository census closed on July 24, 2026. Direct inclusion required public support for Go source, Go gc output, or the current Go toolchain, plus a version or commit that could be fixed. Adjacent tools included general PE/ELF protectors, alternate compilers, compressors, and single-purpose transformations. Shellcode encoders, payload crypters, traffic and data obfuscation libraries, documentation-only repositories, unknown-origin binaries, and tools marketed through parser vulnerabilities were excluded with a recorded reason. The thirteen families form an engineering capability map; product and repository names form a dated public candidate ledger. Newly discovered peers can join that ledger while the method map, inclusion rule, and comparison basis remain stable.
Eleven GitHub search families covered names, descriptions, language, and topics for Go obfuscation, protectors, binary protection, anti-debugging, and anti-tamper. The broadest topic query returned 53 repositories. Deduplication and source reading found one mature Go-native baseline, several narrow current projects, legacy rewriters, anti-debug probes, and many unrelated data or payload tools. This establishes a repeatable search boundary. Production status additionally requires a fixed mechanism, behavior controls, measured analysis-surface change, and a maintainable release lifecycle.
Garble is the direct open-source baseline, with a signed v0.16.0 release, current Go support, active maintenance, and the deepest local evidence. gostrip is a narrow post-link metadata processor. Aurum-OBF is an experimental Windows source and overlay tool. alosgarble advertises symbol, literal, control-flow, integrity, decoy, ballast, and optional anti-debug features; its clean pinned commit 7e584f7e91b3 failed one documented build attempt because commandWeb was undefined. Results from a locally modified snapshot remain excluded from upstream attribution. go-obfuscation exposes a broad proof-of-concept menu, including string pools, opaque predicates, control-flow, simple VM, anti-debug, anti-DBI, anti-VM, integrity, and metadata changes. Its source describes text-based transformations, a simple VM, and incomplete platform testing, so it contributes method discovery and source-audit evidence.
Legacy and single-purpose projects fill narrower cells. gobfuscate stopped in its old GOPATH rewrite flow during one Go 1.26.5 compatibility attempt. mumbojumbo, gofuscator, monmind, obfuse, Doge-Obf, GoBfuscator, and obfuscatxor mainly implement source or string transformations. The reviewed GoBfuscator output carried its encoded AES key with the generated decryptor; obfuscatxor carried a local XOR key. GoDefender, buggi, SecureX, and small anti-debug repositories implement runtime environment probes. GoDefender is archived. These projects help enumerate literal, decoy, anti-debug, anti-VM, and sandbox methods. Their scope does not supply a full release-protection lifecycle.
Alternative code generation remains adjacent. TinyGo and gccgo produce materially different artifacts and runtime assumptions, and both carry compatibility boundaries documented by their maintainers. Assembly and cgo can isolate a small algorithm from Go-aware naming patterns while creating an ordinary native-analysis surface. These options belong in a product POC when portability and maintenance are already acceptable. A "protector" label additionally requires a fixed protection mechanism, behavior controls, measured analysis-surface change, and release-operations evidence.
An in-house protector is its own production route. A team can maintain a cmd/compile or linker pass, a -toolexec wrapper, a product-specific post-linker, a small interpreter, a per-build virtual instruction set, and a watermark service, all targeted at its own protocol and decision paths. In return, it owns regression work for every Go release, ABI and GC constraints, crash symbolization, cross-compilation, code signing, endpoint compatibility, build reproduction, and customer rollback. That trade has leverage only when the organization already has compiler or binary-engineering capability, public tools miss a specific threat-model need, and the annual maintenance budget exceeds a one-time procurement POC.
5.1 Public evidence can order POCs; production use still requires buyer testing
Every commercial product remains at a pre-production evidence level. VMProtect 3.10.6 publicly lists Golang, x86/x64/ARM64, Windows, Linux, macOS, and Android, with mutation, virtualization, combined modes, packing, memory protection, licensing, and watermarks. Its manual describes the upper limit of software protection, runtime restoration of packed code, performance classes, marker and whole-function selection, and placement around both registration and consuming business logic. The local 3.10.6.2770 demo installer had a valid signature, with its artifact identity retained in the public ledger; a default project generated a wrapper output and stopped at a demo dialog. Function selection, entitlement controls, and virtualization performance remain open POC cells, so the evidence earns VMProtect the first test for general offline protection.
Oreans currently publishes Themida, WinLicense, and Code Virtualizer 3.2.5.0. All three list Go gc. Themida and WinLicense protect native Windows x86/x64 applications, with WinLicense adding trial, registration, hardware-locking, and license management. Code Virtualizer targets selected x86/x64/ARM64 regions on Windows, Linux, and macOS. The official comparison separates those jobs, while the release material records Go string-encryption, macro-marker, and start-marker fixes. The locally pinned 3.2.4.34 Themida demo executables had valid signatures. A CLI-only attempt required a project produced through the GUI and generated no protected target. That result fixes only the demo workflow boundary; the other two product lines also have no local artifact evidence in this study.
Virbox Protector Native documents Go, PE/ELF/dylib targets, Windows/Linux/macOS/ARM, virtualization, string encryption, integrity, GUI, and CLI workflows. Its public download page listed 3.6.0.22848, dated June 29, 2026. This round obtained no local trial artifact with a fixed version, hash, signer, and license state, leaving the evidence at the documentation level.
Enigma Protector, Obsidium, StarForce Crypto, and Safengine remain general neighboring products because current public material provided no direct Go guarantee for this matrix. PELock targets 32-bit Windows and falls outside Windows/amd64. UPX is the reversible compression control. Pakkero and Kiteshield are Linux ELF academic or educational neighbors. ChaosProtector was excluded from safe testing because its public positioning included crashing analysis tools through CVEs and absolute anti-analysis claims, while no signed, fixed local artifact entered the evidence set.
A commercial purchase becomes decision-grade when the vendor protects the buyer's actual binary at the target Go release and platform. The return package needs a fixed installer, license state, project, commands, logs, input and output hashes, and support boundary. The buyer independently runs valid and invalid entitlements, name and literal recovery, both inner and caller placements, debugging and dump observations, startup and hot paths, crash recovery, installer and update behavior, final code signing, and endpoint security on the shipping image. Empty cells stay empty. Feature count and successful output generation occupy different evidence levels.
6 Controlled experiments turn the method map into product decisions
The Go metadata floor. Ordinary native stripping removes an important entry route and lowers file size. Go's runtime topology still exposes rich structure to Go-aware analysis. A release baseline should include stripping for hygiene, then measure the Go-specific surface separately. An analyzer failure after metadata rewriting means that exact automation needs repair or replacement. Runtime correctness, manual analysis, and other parsers remain separate checks.
The compiler-survival tax. Source text can look complex while the compiler emits a constant, removes a decoy, or erases a wrapper. Methods that prevent those optimizations create their own stable boundaries and runtime cost. This is why source-obfuscator feature lists need binary-level verification. The appropriate unit is a surviving transformation plus a broken earlier route, accompanied by its maintenance and diagnostic expense.
Placement elasticity. Protecting the cryptographic verifier alone can leave the eligibility calculation or caller decision exposed. Moving protection outward reaches more routes and costs more. The fixture's inner transformation produced a stable ~6.2% p50 increase, while inner plus caller produced a wider 13.2%–29.8% range. The engineering objective is a small protected slice that covers the decisive caller and keeps permanent cost out of hot service loops.
Analysis-surface restoration. A wrapper can make a static parser fail and still preserve the original structure underneath. Official UPX unpacking restored the stripped artifact's Go function and type counts without restoring its original hash. The analyst needs the surface, not the original bytes. Protective packers and runtime encryption demand a harder memory and loader POC, yet the same question applies: what exact analysis surface becomes available after execution?
Protection debt. Every method charges the producer on every release. Toolchain changes can break metadata rewriting. Fixed-seed transformations can still drift. Runtime defenses can collide with EDR and legitimate debugging. Tiny builds reduce crash information. Packing changes startup. Platform signing constrains order. Customer diversity multiplies artifact identity and support records. A method that adds one hour to analysis and one day to every release has negative leverage. The release budget must count both sides.
Together these findings create a practical score. Record the old discovery route, the new steps required, whether those steps transfer to another build, where the authority lives, and what the defender pays per release. This score avoids invented "days to crack" estimates, which vary with program size, prior knowledge, analyst skill, and available automation. It also produces acceptance tests the team can rerun.
7 Signed licenses establish authenticity; server state limits the value of a modified client
The controlled Ed25519 license demonstrates a strong and useful property. The client can reject a forged signature, expiry, wrong product, wrong feature, missing customer, malformed envelope, and missing file without carrying the issuer's private key. This stops fresh entitlement creation through simple editing. The public key, parser, semantic checks, eligibility value, caller branch, and premium code all ship in one customer-controlled process. Their local placement sets the authority ceiling.
A connected product can issue a short-lived capability bound to audience, feature, account, device context, expiry, and a nonce or challenge. The server stores replay windows, revocation, rate, concurrency, and risk state. Critical requests present the capability to server business logic; sensitive data, algorithms, or model execution stay behind that boundary. A copied token then has a narrow time and scope. A modified client can still misuse whatever interface the service intentionally exposes, so server authorization, abuse controls, and privacy governance remain necessary.
Hardware changes part of the offline problem. TPM-backed keys, device certificates, secure enclaves, and dongles can make extraction, copying, or use on another machine more expensive. Remote attestation can bind a server decision to measured device state. Local code still consumes a result and invokes a capability, so replay, caller placement, grace periods, and recovery paths require design. A fully offline, long-lived premium feature ultimately grants execution authority to the device. Product risk acceptance should state that limit and fund delay, differentiation, forensics, and update cadence accordingly.
7.1 Client protection supports segmentation and buys detection and response time
Garble can remove cheap name and path searches. Literal transformation can force runtime recovery. Caller-side control flow or virtualization can enlarge the region an analyst must understand. Per-customer builds and watermarks can reduce direct reuse and support leak attribution. Integrity and runtime signals can expose a subset of modification and automated-abuse patterns. These layers give the server time to revoke, rotate, rate-limit, update, and investigate. Their value increases when a single client compromise yields limited authority.
A weak-leverage design combines one global offline binary, one long-lived entitlement, one stable caller branch, one customer-neutral artifact, and no telemetry. A large protector may add significant first-sample work while the stable artifact and authority structure preserve a highly reusable result. Product teams should spend the first architecture budget on authority and segmentation, then apply client protections to the most scalable attack routes.
8 A 30-day rollout turns protection into a reversible release capability
Week 1 establishes the control. Select one real paid path and mark license parsing, eligibility calculation, the caller's final branch, and the code that delivers value. Remove issuer private keys, long-lived symmetric secrets, test endpoints, and debug-only assets; pin Go, dependencies, build flags, and an ordinary artifact. Define exact exit codes and output for valid entitlement, bad signature, expiry, wrong product, wrong feature, damaged input, and missing files. Record current startup, hot path, crash symbolization, install/update, and final signing behavior. Without that ordinary build, every later claim of "successful protection" lacks a comparison.
Week 2 ships the operable open-source baseline. Apply pinned Garble only to sensitive private packages, beginning with names and paths, then enabling -literals for text that directly exposes a feature. Rerun positive and negative entitlement and performance controls on every intermediate artifact. Preserve the seed, mappings, symbols, input/output hashes, and unprotected rollback build. Admit -tiny only after support accepts the loss of panic and trace output. UPX, gostrip, and anti-debug probes each require their own size, metadata, or telemetry objective; they do not ride into production as a Garble bundle.
Week 3 attacks one valuable cold path. Put experimental Garble control flow in an isolated POC and measure the inner eligibility helper and caller-side final branch separately. Compare each result with real-workload p50/p95, crash, and reproducibility budgets. For valuable offline software, choose one job and its first commercial POC from the opening table, requiring a repeatable project, version, license state, logs, and hashes from the supplier. Admit a second candidate only when the first lacks the target platform or exits evaluation; any legitimate behavior change, accepted negative control, broken update, or budget overrun ends that configuration during the same week.
Week 4 closes release and authority. Apply the platform signature only after every byte transformation, start with a single-customer or low-volume canary, and retain the previous signed artifact plus switches that disable each layer. Connected premium features begin moving short-lived capabilities, replay windows, device relationships, revocation, and critical execution to the server. Offline products document grace periods, renewal, machine replacement, and the ceiling of local authority. Release, detection, and recovery form the thirteenth method family and the control plane that keeps every other protection usable over time.
Every release manifest should bind Go version, GOOS/GOARCH, build flags, source and dependency commits, protector version and provenance, tool hash, seed or project, customer identity where applicable, input and output SHA-256, signing identity and timestamp, control results, static and debugger observations, unpacking or dump boundary, startup and hot-path results, crash recovery, endpoint-security state, and rollback artifact. Seeds, reverse mappings, symbols, private signing material, and watermark assignments belong in controlled storage. A lost Garble seed can close the supported stack-reversal path precisely when an incident needs it.
Endpoint compatibility needs a final-artifact test. The only Defender observation retained in this research is an earlier on-demand scan set with real-time, behavior, IOAV, and on-access protection disabled. It records platform/client 4.18.26060.3008-0, engine 1.1.26060.3008, signature 1.455.286.0, and six no-detection on-demand scans. A current restricted read returned access denied, leaving current runtime compatibility unmeasured. A production record includes engine, platform, signature version and time, real-time and behavior-monitoring state, scan mode, sample hash, and result on the exact final signed artifact.
8.1 The public ledger preserves the complete receipt behind each decision
The public experiment ledger (JSON) contains all 14 artifact identities, sanitized representative build and post-processing command templates, ten entitlement-control definitions, analyzer and Delve observations, performance receipts, reproducibility results, eleven market queries, candidates, and exclusion reasons. Its SHA-256 is 22CC8819516358293402FEA685B12304DB944F3FF5552B7D9B832E4BC02A9761. The private fixture, licenses, authorization modification, patch locations, and reusable machine-code signatures are absent from the public attachment.
The opening ticket table maps to the ledger's candidates, evidence status, and exit boundaries; the Chapter 4 artifact table maps to exact file identities plus static, Delve, performance, and reproducibility fields. The complete receipts retain every hash and command, while the narrative carries only results that change a default, POC order, or rejection condition. When a new Garble, Go, or commercial-protector version appears, add the same controls to the ledger before changing the opening ticket.
A mature Go protection program is a release chain that can be rebuilt, measured, signed, canaried, and rolled back. Client-side layers make location, understanding, and cross-version reuse more expensive; diversity, telemetry, and updates shorten the useful life of one result; and a server boundary limits the duration and scope of authority a modified client can redeem. Protection keeps positive leverage only when the team records both the new steps imposed on an attack route and the recurring cost added to every release.
Research record
9Evidence, objects, and sources
The material below preserves the identifiers and references used in this report.
9.1Research objects
Products, actors, techniques, affected objects, and control points discussed in the report.
Ed25519 entitlement verifier used for all 14 build and post-processing states
Commit at the signed v0.16.0 tag used for every Garble artifact
Official UPX 5.2.0 Win64 archive matched to its release digest
Fourteen executable states times ten exact-output entitlement controls
Comparison receipt binding both rotating-order performance runs
Pinned GoReSym and Redress results for every tested artifact state
Name-breakpoint and controlled-run observations under Delve v1.27.0
Fresh-cache dual builds and localization of cumulative control-flow metadata drift
Normal Go 1.26.5 build used for source-transformation survival checks
Public build, control, analysis, performance, reproducibility, and market-census attachment
9.2Event chronology
- Oreans 3.2.5.0 product lines published
Current Themida, WinLicense, and Code Virtualizer releases list Go gc support, with Go StrEncrypt and marker fixes in the release material.
- Aurum-OBF source pinned
Commit 9d703c54 supplies the source and overlay implementation reviewed for the experimental targeted-string artifact.
- UPX 5.2.0 released
The official Win64 archive and release digest become the pinned compression and unpacking control.
- VMProtect 3.10.6 released
The current release adds whole-function markers and continues published Golang, cross-platform, and ARM64 support; public downloads were refreshed on July 23.
- Virbox 3.6.0.22848 listed
The vendor download page establishes the current documented native-protection release; no fixed local trial artifact entered the matrix.
- gostrip source pinned
Commit df648e23 becomes the post-link Go metadata-processing object used in the experiment.
- SOSEC method census and experiments frozen
Thirteen method families, the public-market census, 140 entitlement controls, compiler-survival checks, static and debugger observations, official unpacking, two performance runs, and reproducibility localization are bound to source and receipt identities.
- Commercial POC order and public ledger refreshed
Current official versions were rechecked, first-test order was assigned by job across five product lines, commercial candidates remained subject to buyer POCs, and a sanitized evidence ledger was published.
9.3Sources and material
- Official Go command and build-flag documentationhttps://pkg.go.dev/cmd/go
- Official Go linker command documentationhttps://go.dev/cmd/link/?m=old
- Go 1.26 release noteshttps://go.dev/doc/go1.26
- Pinned Go 1.26.5 pcHeader and moduledata sourcehttps://github.com/golang/go/blob/go1.26.5/src/runtime/symtab.go#L376-L451
- Pinned Go 1.26.5 embedded build-information readerhttps://github.com/golang/go/blob/go1.26.5/src/debug/buildinfo/buildinfo.go#L55-L98
- Pinned Go 1.26.5 inlining implementation noteshttps://github.com/golang/go/blob/go1.26.5/src/cmd/compile/internal/inline/inl.go#L5-L17
- Official Go debugging guidancehttps://go.dev/doc/gdb
- Garble repositoryhttps://github.com/burrowers/garble
- Garble v0.16.0 signed releasehttps://github.com/burrowers/garble/releases/tag/v0.16.0
- Garble issue 984 on destructive and transformative featureshttps://github.com/burrowers/garble/issues/984
- Pinned Garble experimental control-flow documentationhttps://github.com/burrowers/garble/blob/60a6019f196ece4da360038f905b6c154426a64a/docs/CONTROLFLOW.md
- Pinned Garble literal transformationhttps://github.com/burrowers/garble/blob/60a6019f196ece4da360038f905b6c154426a64a/internal/literals/literals.go#L39-L60
- Pinned Garble control-flow entryhttps://github.com/burrowers/garble/blob/60a6019f196ece4da360038f905b6c154426a64a/internal/ctrlflow/ctrlflow.go#L100-L135
- Pinned Garble declaration-group generationhttps://github.com/burrowers/garble/blob/60a6019f196ece4da360038f905b6c154426a64a/internal/ssa2ast/func.go#L1121-L1149
- gostrip repositoryhttps://github.com/idaifish/gostrip
- Pinned gostrip metadata processinghttps://github.com/idaifish/gostrip/blob/df648e23621cec5bf8b01cb6696dd2afd3ef01d3/internal/gostrip.go#L12-L105
- Aurum-OBF repositoryhttps://github.com/adjisoft/aurum-obf
- Pinned Aurum overlay implementationhttps://github.com/adjisoft/aurum-obf/blob/9d703c54c923ea7d313c4a2876387723d3b932a1/internal/manifest/overlay.go#L49-L105
- alosgarble repositoryhttps://github.com/guno1928/alosgarble
- go-obfuscation proof-of-concept repositoryhttps://github.com/lukaszraczylo/go-obfuscation
- gobfuscate legacy source rewriterhttps://github.com/unixpickle/gobfuscate
- UPX repository and security-position statementhttps://github.com/upx/upx
- UPX 5.2.0 releasehttps://github.com/upx/upx/releases/tag/v5.2.0
- TinyGo standard-library compatibility matrixhttps://tinygo.org/docs/reference/lang-support/stdlib/
- Official gccgo installation and compatibility guidancehttps://go.dev/doc/install/gccgo
- OWASP MASVS resilience controlshttps://mas.owasp.org/MASVS/11-MASVS-RESILIENCE/
- Microsoft Control Flow Guard documentationhttps://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
- Microsoft code-signing and application-control guidancehttps://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/deployment/use-code-signing-for-better-control-and-protection
- VMProtect overviewhttps://vmpsoft.com/vmprotect/overview
- VMProtect user manualhttps://vmpsoft.com/vmprotect/user-manual/
- VMProtect release newshttps://vmpsoft.com/news/
- Themida product and platform pagehttps://www.oreans.com/index.php/Themida.php
- WinLicense product and license-management pagehttps://www.oreans.com/index.php/WinLicense.php
- Oreans product lines, platforms, and Go compiler supporthttps://www.oreans.com/index.php/CodeVirtualizer.php
- Oreans product comparisonhttps://www.oreans.com/CompareProducts.php
- Themida release historyhttps://www.oreans.com/ThemidaWhatsNew.php
- Virbox Protector Native documentationhttps://appshield.virbox.com/native-protect.html
- Virbox release download pagehttps://appsec.virbox.com/down.html