Skip to content

Repository files navigation

Shifting Codes

Python port of Pluto, Polaris, riscy-business, and VMwhere LLVM obfuscation passes using llvm-nanobind bindings, with a PyQt6 visualization UI.

Passes

Pluto (6 passes)

PassTypeDescription
SubstitutionFunctionReplaces arithmetic operations with equivalent but obscure sequences
MBA ObfuscationFunctionApplies Mixed Boolean-Arithmetic transformations using Z3-generated coefficients
Bogus Control FlowFunctionInserts opaque predicates and dead code paths
FlatteningFunctionTransforms control flow into a switch-based dispatch loop
Global EncryptionModuleXOR-encrypts global variable initializers with runtime decryption stubs
Indirect CallModuleReplaces direct function calls with indirect calls through function pointers

Polaris (8 passes)

Upgraded versions of four Pluto passes plus four new passes:

PassTypeDescription
Bogus Control FlowFunctionModular-arithmetic opaque predicates (upgraded from Pluto's trivial predicates)
FlatteningFunctionSwitch-based dispatch with dominance-based state encryption (upgraded from plaintext)
Global EncryptionModuleUse-based discovery with per-function decryption via shared helper (upgraded from single-site inline)
Indirect CallModulePer-call-site globals with add/subtract pointer masking (upgraded from shared GV, no masking)
Indirect BranchFunctionReplaces direct branches with indirect jumps through obfuscated jump tables
Alias AccessFunctionObscures local variable access through pointer aliasing and multi-level struct indirection
Custom CCModuleRandomly assigns non-standard calling conventions to internal functions
Merge FunctionModuleMerges multiple functions into a single switch-based dispatcher

VMwhere (2 passes)

PassTypeDescription
String EncryptionModuleXOR-encrypts string constant globals ([N x i8]) with per-function stack-local decryption at runtime
Anti-DisassemblyFunctionInjects crafted x86 inline assembly that desynchronizes linear-sweep disassemblers (IDA, Ghidra, objdump)
PassTypeDescription
VirtualizationModuleTranslates functions to RISC-V inspired bytecode and replaces them with an embedded interpreter (Phase 1: integer arithmetic)

Prerequisites

  • Python 3.12+
  • UV package manager
  • LLVM 21 development libraries installed (see llvm-nanobind for platform-specific instructions)

Installation

  1. Install UV (if not already installed):

    pip install uv
  2. Install the project (builds llvm-nanobind from source automatically):

    uv sync

    For local development with a local llvm-nanobind checkout, override the source in pyproject.toml:

    [tool.uv.sources]
    llvm-nanobind = { path = "../llvm-nanobind", editable = true }

Usage

Pluto passes:

fromshifting_codes.passesimportPassPipelinefromshifting_codes.passes.substitutionimportSubstitutionPassfromshifting_codes.passes.mba_obfuscationimportMBAObfuscationPassfromshifting_codes.passes.bogus_control_flow_plutoimportPlutoBogusControlFlowPassfromshifting_codes.passes.flattening_plutoimportPlutoFlatteningPassfromshifting_codes.passes.global_encryption_plutoimportPlutoGlobalEncryptionPassfromshifting_codes.passes.indirect_call_plutoimportPlutoIndirectCallPassfromshifting_codes.utils.cryptoimportCryptoRandomrng=CryptoRandom(seed=42)
pipeline=PassPipeline()
pipeline.add(SubstitutionPass(rng=rng))
pipeline.add(MBAObfuscationPass(rng=rng))
pipeline.add(PlutoBogusControlFlowPass(rng=rng))
pipeline.add(PlutoFlatteningPass(rng=rng))
pipeline.add(PlutoGlobalEncryptionPass(rng=rng))
pipeline.add(PlutoIndirectCallPass(rng=rng))
pipeline.run(mod, ctx)

Polaris passes:

fromshifting_codes.passesimportPassPipelinefromshifting_codes.passes.substitutionimportSubstitutionPassfromshifting_codes.passes.mba_obfuscationimportMBAObfuscationPassfromshifting_codes.passes.bogus_control_flowimportBogusControlFlowPassfromshifting_codes.passes.flatteningimportFlatteningPassfromshifting_codes.passes.global_encryptionimportGlobalEncryptionPassfromshifting_codes.passes.indirect_callimportIndirectCallPassfromshifting_codes.passes.indirect_branchimportIndirectBranchPassfromshifting_codes.passes.alias_accessimportAliasAccessPassfromshifting_codes.passes.custom_ccimportCustomCCPassfromshifting_codes.passes.merge_functionimportMergeFunctionPassfromshifting_codes.utils.cryptoimportCryptoRandomrng=CryptoRandom(seed=42)
pipeline=PassPipeline()
pipeline.add(SubstitutionPass(rng=rng))
pipeline.add(MBAObfuscationPass(rng=rng))
pipeline.add(BogusControlFlowPass(rng=rng))
pipeline.add(FlatteningPass(rng=rng))
pipeline.add(GlobalEncryptionPass(rng=rng))
pipeline.add(IndirectCallPass(rng=rng))
pipeline.add(IndirectBranchPass(rng=rng))
pipeline.add(AliasAccessPass(rng=rng))
pipeline.add(CustomCCPass(rng=rng))
pipeline.add(MergeFunctionPass(rng=rng))
pipeline.run(mod, ctx)

VMwhere passes:

fromshifting_codes.passesimportPassPipelinefromshifting_codes.passes.string_encryptionimportStringEncryptionPassfromshifting_codes.passes.anti_disassemblyimportAntiDisassemblyPassfromshifting_codes.utils.cryptoimportCryptoRandomrng=CryptoRandom(seed=42)
pipeline=PassPipeline()
pipeline.add(StringEncryptionPass(rng=rng))
pipeline.add(AntiDisassemblyPass(rng=rng, density=0.3)) # density: 0.0-1.0pipeline.run(mod, ctx)

Virtualization pass (riscy-business):

fromshifting_codes.passesimportPassPipelinefromshifting_codes.passes.virtualizationimportVirtualizationPassfromshifting_codes.utils.cryptoimportCryptoRandomrng=CryptoRandom(seed=42)
pipeline=PassPipeline()
pipeline.add(VirtualizationPass(rng=rng))
pipeline.run(mod, ctx)

Passes are registered via @PassRegistry.register and can be looked up by name:

fromshifting_codes.passesimportPassRegistrycls=PassRegistry.get("substitution")
all_passes=PassRegistry.all_passes()

Running Tests

# All tests
python -m uv run pytest tests/ -v
# Single test file
python -m uv run pytest tests/test_substitution.py -v
# Single test by name
python -m uv run pytest tests/test_substitution.py -k "test_add_substitution" -v

UI

Launch the PyQt6 visualization GUI:

python -m uv run python -m shifting_codes.ui.app

Project Structure

src/shifting_codes/
passes/ # Obfuscation passes (base classes, registry, pipeline)
utils/ # Shared utilities (crypto RNG, MBA solver, IR helpers)
riscybusiness_vm/ # RISC-V VM: ISA definition, bytecode compiler, interpreter builder
xtea/ # XTEA cipher — pure Python reference + LLVM IR builder
ui/ # PyQt6 GUI for visualizing pass transformations
vendor/
riscy-business/ # Git submodule — RISC-V VM reference (opcodes, encryption, shuffling)
tests/ # pytest test suite

About

Shifting.Codes

Topics

Resources

Stars

30 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages