ARM64 ELF Virtual Machine Protection System
Translate ARM64 native instructions into custom VM bytecode for function-level code protection
π¨π³ δΈζζζ‘£ β’ Features β’ Architecture β’ Quick Start β’ Usage β’ License
VMPacker is a Virtual Machine Protection (VMP) system for ARM64 (AArch64) Linux ELF binaries. It decodes target function's native ARM64 instructions into an intermediate representation, translates them into custom VM bytecode, and injects an embedded VM interpreter into the ELF file. At runtime, protected functions are executed by the VM interpreter instead of natively.
ARM64 Native Code β Decode β Translate β Custom VM Bytecode
β
Original ELF β Inject β VM Interpreter Stub
- 63 VM instructions β covering ALU, memory, branch, syscall, and more
- Table-driven decoder β pattern matching based on the ARM Architecture Reference Manual
- 121 ARM64 instructions supported (base A64 100% coverage), including:
- Arithmetic/Logic (ADD, SUB, MUL, AND, ORR, EOR, LSL, LSR, ASR, MVN, BIC, ORN, EON...)
- Multiply-Extend (MADD, MSUB, SMADDL, SMSUBL, UMADDL, UMSUBL, SMULH, UMULH, UDIV, SDIV)
- Data Movement (MOV, MOVZ, MOVK, MOVN)
- Memory Access (LDR, STR, LDP, STP, LDPSW, LDADD, CAS, LDAR, STLR, LDAXR, STLXR β various widths and addressing modes)
- Branch Control (B, BL, BR, BLR, RET, B.cond, CBZ/CBNZ, TBZ/TBNZ)
- Conditional Select (CSEL, CSINC, CSINV, CSNEG, CCMP, CCMN)
- Bitfield (UBFM, SBFM, BFM, EXTR)
- Bit Manipulation (CLZ, CLS, RBIT, REV, REV16, REV32)
- Carry Arithmetic (ADC, ADCS, SBC, SBCS)
- SIMD Load/Store (LD1, ST1)
- System/Barriers (SVC, MRS, MSR, ADRP/ADR, DMB, DSB, ISB, HLT, BRK, PRFM)
| Layer | Technique | Description |
|---|---|---|
| VM Protection | Custom ISA | Randomly mapped opcodes β reverse engineers cannot directly identify instruction semantics |
| OpcodeCryptor | Per-instruction opcode encryption | enc[pc] = op[pc] ^ (key ^ (pc * 0x9E3779B9)) |
| Bytecode Reversal | Execution order reversal | Instructions stored in reverse order; interpreter traverses backwards |
| Token Entry | 3-instruction trampoline | Original function replaced with tokenized entry, hiding actual bytecode location |
| Indirect Dispatch | Function pointer jump table | Filled at runtime on the stack, breaking IDA cross-references |
- Cross-platform desktop app built with Wails v2 (Go + Vue 3)
- Element Plus UI components
- Symbol function selection + manual function input (protect by address range)
- One-click protection with real-time log output
![]() |
![]() |
![]() |
| Function List | Analysis & Selection | Protection Options |
![]() |
![]() |
|
| Real-time Logs | Protection Complete |
vmp/
βββ cmd/vmpacker/ # CLI entry point
β βββ main.go # CLI argument parsing + orchestration
β βββ vm_interp.bin # Compiled VM interpreter (GCC, go:embed)
β
βββ pkg/ # Go core library
β βββ arch/arm64/ # ARM64 architecture support
β β βββ decoder.go # Table-driven instruction decoder (implements vm.Decoder)
β β βββ decode_*.go # Decode pattern tables (DP-IMM/DP-REG/Branch/LdSt)
β β βββ translator.go # ARM64 β VM bytecode translator
β β βββ tr_alu.go # ALU instruction translation
β β βββ tr_branch.go # Branch instruction translation
β β βββ tr_loadstore.go # Memory instruction translation
β β βββ tr_bitfield.go # Bitfield instruction translation
β β βββ tr_special.go # Special instructions (ADRP/ADR)
β βββ vm/ # VM ISA definitions
β β βββ types.go # Shared types + interfaces (Decoder/Translator/Packer)
β β βββ opcodes.go # 58+ VM opcode definitions (randomly mapped values)
β β βββ disasm.go # VM bytecode disassembler
β βββ binary/elf/ # ELF binary manipulation
β βββ packer.go # ELF VMP injection (PT_NOTE hijack, trampoline generation)
β βββ trampoline.go # Trampoline code generation
β
βββ stub/ # C VM interpreter (compiled to PIC flat binary)
β βββ vm_interp_clean.c # Interpreter main loop + entry points
β βββ vm_types.h # VM CPU context (vm_ctx_t)
β βββ vm_opcodes.h # C-side opcode definitions (synced with opcodes.go)
β βββ vm_decode.h # Bytecode read utilities
β βββ vm_token.h # Token encode/decode + descriptor table
β βββ vm_dispatch.h # Indirect dispatch jump table
β βββ vm_crc.h # CRC32 integrity check
β βββ vm_sections.h # Handler section scattering macros
β βββ vm_interp.lds # Linker script
β βββ vm_handlers/ # Modular instruction handlers
β βββ h_alu.h # Arithmetic/logic operations
β βββ h_mem.h # Memory access
β βββ h_branch.h # Branch/jump
β βββ h_cmp.h # Compare/conditional
β βββ h_mov.h # Data movement
β βββ h_stack.h # Stack (PUSH/POP)
β βββ h_system.h # System (SVC/MRS/BLR/BR/RET)
β
βββ vmp-gui/ # Wails GUI frontend
β βββ frontend/ # Vue 3 + Element Plus
β βββ backend/ # Go backend bindings
β
βββ build/ # Pre-compiled tools + test artifacts
The project uses an interface-driven modular architecture, making it easy to extend to new ISAs and binary formats:
// Architecture decoder interface β extensible to x86, RISC-V
type Decoder interface {
Decode(raw uint32, offset int) Instruction
InstName(op int) string
}
// Bytecode translator interface
type Translator interface {
Translate(instructions []Instruction) (*TranslateResult, error)
}
// Binary format injector interface β extensible to PE, Mach-O
type Packer interface {
Process() error
}graph LR
A[Input ELF] --> B[Locate Target Function]
B --> C[Extract ARM64 Instructions]
C --> D[Decode ARM64]
D --> E[Translate to VM Bytecode]
E --> F[XOR Encrypt Bytecode]
F --> G[Inject VM Interpreter]
G --> H[Generate Trampoline]
H --> I[Replace Function Entry]
I --> J[Output Protected ELF]
- Go 1.21+
- GCC (aarch64-linux-gnu-gcc) β to compile the stub
- Linux ARM64 or cross-compilation environment
git clone https://github.com/LeoChen-CoreMind/VMPacker.git
cd VMPacker
make all# Protect a single function
./vmpacker -func check_license -v -o protected.elf original.elf
# Protect multiple functions
./vmpacker -func "check_license,verify_token" -v -o protected.elf original.elf# Specify address range
./vmpacker -addr "0x4006AC-0x400790:main" -v -o protected.elf original.elf
# Mixed mode
./vmpacker -addr "0x4006AC-0x400790:main" -func verify -o protected.elf original.elf./vmpacker -info input.elf| Option | Default | Description |
|---|---|---|
-func |
β | Function name(s) to protect (comma-separated) |
-addr |
β | Protect by address (0xSTART-0xEND[:name]) |
-o |
input.vmp |
Output file path |
-v |
false |
Verbose output (show disassembly) |
-strip |
true |
Strip symbol table |
-debug |
false |
Generate ARM64 β VM bytecode debug mapping file |
-token |
true |
Token-based entry mode |
-info |
false |
Print ELF info only |
# Standard build (GCC)
aarch64-linux-gnu-gcc -Os -nostdlib -fPIC -ffreestanding \
-o stub.elf stub/vm_interp_clean.c \
-T stub/vm_interp.lds
aarch64-linux-gnu-objcopy -O binary stub.elf vm_interp.bingo build -o vmpacker ./cmd/vmpacker/cd vmpacker
make guiVMPacker defines a custom Instruction Set Architecture (ISA) with randomly mapped opcode values to increase reverse-engineering difficulty.
π For the complete opcode table with encoding details, see the Chinese documentation.
| Category | Count | Description |
|---|---|---|
| Data Movement | 3 | MOV_IMM64, MOV_IMM32, MOV_REG |
| Arithmetic/Logic | 21 | ADD, SUB, MUL, XOR, AND, OR, SHL, SHR, ASR, NOT, ROR, UMULH + _IMM variants |
| Memory Access | 8 | LOAD/STORE 8/16/32/64 |
| Branch/Jump | 13 | JMP, JE, JNE, JL, JGE, JGT, JLE, JB, JAE, JBE, JA, TBZ, TBNZ |
| Compare | 6 | CMP, CMP_IMM, CCMP_REG, CCMP_IMM, CCMN_REG, CCMN_IMM |
| Stack | 2 | PUSH, POP |
| System/Special | 8 | NOP, HALT, RET, CALL_NATIVE, CALL_REG, BR_REG, SVC, MRS |
| SIMD | 2 | VLD16, VST16 |
| Total | 63 |
- Full GUI Integration β Complete GUI β backend protection engine integration
- Hybrid Mode β Partial native execution + partial VM protection
- Dynamic Opcode Mapping β Generate unique ISA mapping per protection run
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-arch - Commit your changes:
git commit -m 'feat: add x86_64 decoder' - Push the branch:
git push origin feature/new-arch - Create a Pull Request
We follow Conventional Commits:
feat:New featurefix:Bug fixrefactor:Code refactoringdocs:Documentationtest:Tests
This project is licensed under the AGPL-3.0 License.
Why AGPL-3.0:
- β Strong Copyleft β Any modifications or derivative works must be open-sourced under the same license
- β Network Use Clause β Providing this software's functionality as a network service also requires source disclosure
- β Protects Core Technology β Prevents closed-source commercial use of the protection engine
- β Community Friendly β Free to study, research, and improve β improvements must be shared back
- β Commercial Licensing β For closed-source commercial use, contact the author for a commercial license
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This project is designed to provide legitimate intellectual property protection for software developers, helping to safeguard core algorithms and critical code in commercial software from unauthorized reverse engineering or theft.
User Notice:
- You must comply with all applicable laws and regulations in your jurisdiction when using this software
- It is strictly prohibited to use this software for any illegal purpose, including but not limited to: malware development, circumventing security audits, infringing on others' intellectual property rights, or compromising computer system security
- The author(s) shall not be held liable for any direct or indirect consequences resulting from any person's use of this software
- By downloading, using, or distributing this software, you acknowledge that you have read and agreed to the above terms
LeoChen β @LeoChen-CoreMind
Copyright Β© 2026 LeoChen. All rights reserved.




