This commit is contained in:
2026-05-31 11:23:07 +01:00
parent 1d51b29b92
commit 5ea458fb06
18 changed files with 1367 additions and 220 deletions
+2
View File
@@ -0,0 +1,2 @@
build/
*.exe
+51 -6
View File
@@ -54,9 +54,9 @@ make transformer
``` ```
Normal Obfuscated Normal Obfuscated
Size: 2707026 3063458 Size: 2707026 3081170
Symbols: 2864 58 Symbols: 2864 58
Strings: 15335 4302 Strings: 15335 4264
Secret leaks: 1 (LIC-*) 0 Secret leaks: 1 (LIC-*) 0
Function names: visible 0 (good) Function names: visible 0 (good)
``` ```
@@ -249,6 +249,43 @@ Replaces simple functions with a custom stack-based bytecode VM.
| SWAP | 0x1A | i8 | Swap stack positions | | SWAP | 0x1A | i8 | Swap stack positions |
| ROT | 0x1B | none | Rotate top 3 | | ROT | 0x1B | none | Rotate top 3 |
**Junk opcodes:** The compiler inserts random junk opcodes (0x1C-0x1F) at ~33% probability between real instructions. The VM silently consumes them via the `default` case, breaking linear disassembly. Use `CompileWith(program, CompileOpts{NoJunk: true})` for deterministic output.
### 10. Anti-Disassembly Injection
Injects junk `[N]byte` variable declarations at ~15% per statement to confuse disassemblers and decompilers.
```go
// Injected junk — valid Go, but semantically dead
var _j1 = [7]byte{0x4e, 0x6f, 0x70, 0x65, 0x21, 0x00, 0x00}
var _j2 = [12]byte{0xde, 0xad, 0xbe, 0xef, ...}
```
These produce opaque byte sequences in the binary that disassemblers cannot reliably skip.
### 11. Junk String Injection
Adds 4-10 fake string constants per file to dilute the `strings` output and increase noise for analysts.
```go
var _js1 = "xK9mP2vL8nQ4wR7yT"
var _js2 = "aB3cD5eF7gH9iJ1kL"
```
These strings have no semantic effect but increase the string table from ~200 to ~4000+ entries, making secret extraction harder.
### 12. Function Pointer Dispatch
Wraps function calls through function pointer variables to obscure call targets.
```go
var _fptr0 = checkLicense_obf4721 // function pointer variable
//go:noinline
func checkLicense(args ...interface{}) interface{} {
return _fptr0(args...)
}
```
## Runtime Protection Packages ## Runtime Protection Packages
### Syscall Obfuscation (`pkg/syscallobf`) ### Syscall Obfuscation (`pkg/syscallobf`)
@@ -257,7 +294,8 @@ Hides syscall numbers from static analysis using XOR-encoded dispatch.
- **Encoding:** Each syscall number is XOR'd with a random `uint64` dispatch key generated once via `sync.Once` - **Encoding:** Each syscall number is XOR'd with a random `uint64` dispatch key generated once via `sync.Once`
- **Linux (`syscall_linux.go`):** Wraps `ptrace` (101), `getpid` (39), `kill` (62), `open` (2), `close` (3), `read` (0), `lseek` (8), `mmap` (9), `mprotect` (10) via `syscall.RawSyscall` - **Linux (`syscall_linux.go`):** Wraps `ptrace` (101), `getpid` (39), `kill` (62), `open` (2), `close` (3), `read` (0), `lseek` (8), `mmap` (9), `mprotect` (10) via `syscall.RawSyscall`
- **Darwin (`syscall_darwin.go`):** Returns `ENOSYS` stubs (platform-specific implementation pending) - **Darwin (`syscall_darwin.go`):** Real implementations via encoded SYS_* constants using `syscall.RawSyscall6` — `ptrace`, `sysctl`, `kill`, `getpid`, `mmap`, `mprotect`
- **Windows (`syscall_windows.go`):** `NtQueryInformationProcess`, `NtSetInformationThread` via `ntdll.dll` LazyDLL; `kernel32` ops; `NtProtectVirtualMemory` for mprotect
The anti-debugging package uses these for stealthy `/proc/self/mem` and `/proc/self/maps` access. The anti-debugging package uses these for stealthy `/proc/self/mem` and `/proc/self/maps` access.
@@ -268,12 +306,17 @@ The anti-debugging package uses these for stealthy `/proc/self/mem` and `/proc/s
| Check | Platform | Description | | Check | Platform | Description |
|-------|----------|-------------| |-------|----------|-------------|
| `checkPtrace()` | Linux | Reads `/proc/self/status` for non-zero `TracerPid` | | `checkPtrace()` | Linux | Reads `/proc/self/status` for non-zero `TracerPid` |
| `checkPtrace()` | Darwin | `sysctl` P_TRACED flag check + `ptrace(PT_DENY_ATTACH)` |
| `disableCoreDump()` | Linux | Writes "0" to `/proc/self/coredump_filter` | | `disableCoreDump()` | Linux | Writes "0" to `/proc/self/coredump_filter` |
| `checkTiming()` | All | 1M loop iterations must complete in <200ms (detects single-stepping) | | `checkTiming()` | All | 1M loop iterations must complete in <200ms (detects single-stepping) |
| `checkEnv()` | All | Checks for `GODEBUG`, `DELVE_LISTENER`, `DEBUGINFOD_URL`, `RR_LOG_FILE`, `_JAVA_OPTIONS`, `LD_PRELOAD`, `DYLD_INSERT_LIBRARIES` | | `checkEnv()` | All | Checks for `GODEBUG`, `DELVE_LISTENER`, `DEBUGINFOD_URL`, `RR_LOG_FILE`, `_JAVA_OPTIONS`, `LD_PRELOAD`, `DYLD_INSERT_LIBRARIES` |
| `checkParentProcess()` | Linux | Reads `/proc/<ppid>/comm`, matches against 12 debugger names | | `checkParentProcess()` | Linux | Reads `/proc/<ppid>/comm`, matches against 12 debugger names |
| `checkFunctionPrologues()` | Linux | Reads `/proc/self/mem` at function addresses, checks for JMP hooks (0xE9, 0xEB, 0xFF 0x25) and INT3 breakpoints (0xCC) | | `checkFunctionPrologues()` | Linux | Reads `/proc/self/mem` at function addresses, checks for JMP hooks (0xE9, 0xEB, 0xFF 0x25) and INT3 breakpoints (0xCC) |
| `scanForBreakpoints()` | Linux | Parses `/proc/self/maps`, reads executable regions, flags ≥8 consecutive 0xCC bytes | | `scanForBreakpoints()` | Linux | Parses `/proc/self/maps`, reads executable regions, flags ≥8 consecutive 0xCC bytes |
| Windows anti-debug | Windows | 5 API-based checks + PEB direct read + hardware BP scan + ThreadHideFromDebugger |
| Hook detection | Darwin | Function prologue scanning via reflect pointers, ARM64 B/BR hook detection, INT3 cluster scanning |
| Hook detection | Windows | `ReadProcessMemory` prologue scanning |
| Integrity check | Windows | PE `.text` section SHA-256 hashing via `debug/pe` |
**Background goroutines:** **Background goroutines:**
- `AntiAttach()` — polls `checkPtrace()` every 500ms, exits with code 66 on detection - `AntiAttach()` — polls `checkPtrace()` every 500ms, exits with code 66 on detection
@@ -333,8 +376,10 @@ Flags:
-indirect Indirect function dispatch (default true) -indirect Indirect function dispatch (default true)
-bogus-cfg Bogus control-flow injection (default true) -bogus-cfg Bogus control-flow injection (default true)
-flatten Control-flow flattening (default true) -flatten Control-flow flattening (default true)
-vm Virtualize simple functions into VM bytecode (default true) -vm Virtualize simple functions into VM bytecode (default true)
-buildid Inject unique build ID constant (default true) -buildid Inject unique build ID constant (default true)
-anti-disasm Inject anti-disassembly junk variables (default true)
-junk-strings Inject fake strings to dilute strings output (default true)
-seed int Build seed for polymorphic output (0 = use current timestamp) -seed int Build seed for polymorphic output (0 = use current timestamp)
``` ```
@@ -383,7 +428,7 @@ The `make compare` target verifies all of these are hidden in the obfuscated bin
# Run all package tests # Run all package tests
go test ./pkg/... go test ./pkg/...
# VM tests (22 tests: arithmetic, bitwise, comparisons, jumps, callouts, determinism) # VM tests (23 tests: arithmetic, bitwise, comparisons, jumps, callouts, determinism, junk opcodes)
go test ./pkg/vm/ -v go test ./pkg/vm/ -v
# Syscall obfuscation tests # Syscall obfuscation tests
@@ -402,6 +447,6 @@ go vet ./...
## Limitations ## Limitations
- **Text-based transformation:** The transformer operates on source text, not Go AST. This limits what can be reliably transformed (e.g., type inference for variable hoisting is heuristic). - **Text-based transformation:** The transformer operates on source text, not Go AST. This limits what can be reliably transformed (e.g., type inference for variable hoisting is heuristic).
- **Darwin syscall stubs:** `pkg/syscallobf` returns `ENOSYS` on macOS. Linux is the primary target for runtime protections.
- **Garble required:** Stage 2 depends on `mvdan.cc/garble` for name mangling, literal encryption, and binary stripping. - **Garble required:** Stage 2 depends on `mvdan.cc/garble` for name mangling, literal encryption, and binary stripping.
- **Simple function virtualization only:** The VM currently handles len-comparisons and arithmetic. Complex control flow is not virtualized. - **Simple function virtualization only:** The VM currently handles len-comparisons and arithmetic. Complex control flow is not virtualized.
- **Windows integrity check:** PE `.text` section hashing works but is less battle-tested than ELF/Mach-O paths.
Binary file not shown.
+56 -37
View File
@@ -8,38 +8,58 @@ import (
"os" "os"
"time" "time"
) )
var _junkData = [...]string{
"Mozilla/5.0 (Windows NT 10.0)",
"Bearer eyJhbGciOiJIUzI1NiJ9",
"192.168.1.1:8080",
"Mozilla/5.0 (Windows NT 10.0)",
}
var _ = _junkData
var _buildID = "BUILD_1780185895842347000_5717911B" // polymorphic build marker
var _buildID = "BUILD_1780222823944864000_67EC3928" // polymorphic build marker
var _ = _buildID var _ = _buildID
func getVersion() string { return getVersion_obf2511() } var _fptr0 = getVersion_obf1861
func getBuildID() string { return getBuildID_obf7656() } //go:noinline
func processRequest(userID string) { processRequest_obf1301(userID) } func getVersion() string { return _fptr0() }
func generateToken(userID string) string { return generateToken_obf5646(userID) } var _fptr1 = getBuildID_obf7802
func validateLicense(key string) bool { return validateLicense_obf9184(key) } //go:noinline
func maskString(s string) string { return maskString_obf9182(s) } func getBuildID() string { return _fptr1() }
var _masterSeed = [32]byte{0xF0, 0x9C, 0xC8, 0x1C, 0xD9, 0x25, 0xA4, 0x69, 0xFE, 0xED, 0xA1, 0x92, 0xD6, 0x1A, 0x62, 0xF1, 0x0C, 0xA7, 0xD0, 0xB9, 0xC3, 0x3B, 0xB4, 0xE0, 0x41, 0x5F, 0x79, 0x14, 0x1F, 0xBB, 0xE1, 0xC5} var _fptr2 = processRequest_obf4807
//go:noinline
func processRequest(userID string) { _fptr2(userID) }
var _fptr3 = generateToken_obf1103
//go:noinline
func generateToken(userID string) string { return _fptr3(userID) }
var _fptr4 = validateLicense_obf1490
//go:noinline
func validateLicense(key string) bool { return _fptr4(key) }
var _fptr5 = maskString_obf3138
//go:noinline
func maskString(s string) string { return _fptr5(s) }
var _masterSeed = [32]byte{0xCE, 0x9B, 0x3F, 0xDB, 0x78, 0xEB, 0xEF, 0xB1, 0xEB, 0x54, 0x01, 0x8E, 0x4E, 0x79, 0x40, 0xFA, 0xAF, 0x5D, 0xE3, 0xBB, 0x25, 0xDD, 0xD4, 0x98, 0x7A, 0x75, 0x36, 0x0D, 0xE8, 0x75, 0x54, 0x4D}
var _encEntries = []strenc.Entry{ var _encEntries = []strenc.Entry{
{Ciphertext: []byte{0x97, 0xFC, 0x87, 0x6E, 0x07, 0xCF, 0xED, 0xBC, 0xA2, 0xCF, 0x6D, 0x5F, 0xE9, 0x9C, 0x51, 0x81, 0xEA, 0x72, 0x61, 0x41, 0xE0, 0x06, 0xC1, 0x62, 0x99, 0xFE, 0xB7, 0x72, 0xA0, 0x7C, 0x7D, 0xEC, 0x74, 0xF7, 0xA1, 0x88, 0xFE, 0x91, 0x69, 0xE1, 0x6A, 0xA4, 0x71, 0x73, 0xAB, 0x88, 0xBB, 0x91, 0xE5, 0x6E, 0x74, 0xBC, 0x56, 0xD5, 0x16, 0x88, 0x84, 0x96, 0x53, 0x56, 0xCA, 0x2D, 0x98, 0x1D, 0xB7, 0x3B, 0x15, 0xD3, 0xF7, 0x39, 0xCC, 0x73, 0x35, 0xE5, 0x72, 0x5F, 0x4E, 0x72, 0xB4, 0x51, 0x81, 0xA9, 0x9E, 0x5D, 0x1A, 0xF4, 0x53, 0x86, 0x81, 0x1C, 0x20, 0x00}, IV: [16]byte{0x97, 0xFC, 0x87, 0x6E, 0x07, 0xCF, 0xED, 0xBC, 0xA2, 0xCF, 0x6D, 0x5F, 0xF8, 0x65, 0x80, 0x84}}, {Ciphertext: []byte{0xD6, 0x41, 0xFB, 0xEB, 0xC1, 0xCC, 0x4D, 0xA9, 0xC5, 0x02, 0xCF, 0xD6, 0x0E, 0x24, 0x8D, 0xA8, 0x38, 0xA3, 0xF4, 0x70, 0xBB, 0x7D, 0xF3, 0xC2, 0xBA, 0xEA, 0xFA, 0x7E, 0x47, 0xB4, 0x9B, 0x55, 0xDB, 0x00, 0xB2, 0xBA, 0x81, 0xAF, 0x3C, 0xB0, 0xFE, 0x5B, 0x5B, 0xAB, 0xFF, 0x54, 0x43, 0x47, 0xB1, 0x36, 0x8E, 0xF2, 0xCC, 0x22, 0x5B, 0x25, 0x84, 0x74, 0xED, 0xC7, 0xCB, 0xC0, 0x02, 0x0B, 0xE9, 0x53, 0x63, 0xC8, 0x0A, 0xE9, 0x13, 0x1F, 0x6F, 0x90, 0x79, 0x7C, 0xCC, 0x89, 0xDE, 0x9E, 0xC6, 0xFB, 0xFA, 0x3B, 0x3A, 0x59, 0x6F, 0xC8, 0x9C, 0x9C, 0x6F, 0x77}, IV: [16]byte{0xD6, 0x41, 0xFB, 0xEB, 0xC1, 0xCC, 0x4D, 0xA9, 0xC5, 0x02, 0xCF, 0xD6, 0x0C, 0x65, 0xE0, 0x32}},
{Ciphertext: []byte{0x67, 0xDC, 0x11, 0xFA, 0xDC, 0x10, 0x70, 0xA5, 0x8B, 0x78, 0xB7, 0x0B, 0xB2, 0x90, 0xB2, 0x38, 0xEB, 0x1D, 0xFD, 0x3F, 0x25, 0xA9, 0xE7, 0x28, 0x8A, 0x58, 0x82, 0x98, 0xDF, 0xB3, 0xE0, 0x65, 0x82, 0x22, 0x84, 0x91, 0x0E, 0xE0, 0x71, 0xF5, 0x6A, 0x7B, 0x2D, 0xEC, 0x8B, 0x67, 0x34, 0xB2, 0x71, 0xEE, 0x0C, 0xC4, 0xA2, 0x4E, 0x6C, 0x8C, 0x81, 0xCB, 0x41, 0x88, 0x90, 0x28, 0xDA, 0x78, 0x70, 0x45, 0x7A, 0xBB, 0xBD, 0xAD, 0x38, 0x06, 0x15, 0xCA, 0xF4, 0xA7, 0x36, 0xE8, 0xA9, 0x88, 0x8E, 0xFF, 0x72, 0x27, 0x96, 0x87, 0x92, 0xD1, 0x81, 0x0C, 0x7C, 0x80}, IV: [16]byte{0x67, 0xDC, 0x11, 0xFA, 0xDC, 0x10, 0x70, 0xA5, 0x8B, 0x78, 0xB7, 0x0B, 0x1F, 0xC3, 0xF1, 0xEA}}, {Ciphertext: []byte{0x3B, 0x4C, 0x29, 0xDE, 0x96, 0x06, 0xE2, 0xA0, 0xFD, 0x10, 0x94, 0x59, 0x3F, 0x1A, 0xC9, 0xF9, 0xF3, 0x86, 0xD9, 0xA7, 0xDB, 0xB1, 0x2B, 0x0D, 0x2E, 0x65, 0x53, 0x45, 0xCB, 0xA9, 0x89, 0x2E, 0x10, 0x1C, 0x5C, 0x6A, 0x50, 0x47, 0xC4, 0xEB, 0x8C, 0xE7, 0x89, 0x62, 0xEE, 0x5B, 0xA1, 0x7E, 0x52, 0xC5, 0xF6, 0x58, 0xA1, 0x70, 0x60, 0xAA, 0x8C, 0xAA, 0xBF, 0xA0, 0x06, 0xC0, 0xA7, 0x5B, 0x0E, 0xE8, 0x42, 0xA6, 0x40, 0xC8, 0xDD, 0x52, 0x39, 0x73, 0x9D, 0x97, 0xE0, 0x36, 0x03, 0x65, 0x4B, 0x26, 0x9A, 0x7A, 0x10, 0x99, 0x35, 0x71, 0xFF, 0xF9, 0xE1, 0x06}, IV: [16]byte{0x3B, 0x4C, 0x29, 0xDE, 0x96, 0x06, 0xE2, 0xA0, 0xFD, 0x10, 0x94, 0x59, 0x26, 0x50, 0x2C, 0x68}},
{Ciphertext: []byte{0x80, 0xA2, 0x11, 0x9A, 0xE8, 0xEB, 0x2C, 0x1D, 0x2B, 0xBE, 0x8D, 0x1E, 0xD9, 0x87, 0x84, 0x25, 0xCD, 0xF5, 0x8E, 0xF7, 0xA2, 0xF2, 0x71, 0x01, 0x8A, 0xCC, 0xF3, 0x86, 0xC7, 0x93, 0x1B, 0xF6, 0xAC, 0xF0, 0x45, 0xA4, 0x62, 0x9F, 0xF7, 0x2B, 0x1C, 0x24, 0x4F, 0x82, 0xCA, 0x08, 0xC3, 0x9C, 0xB0, 0x2E, 0xFA, 0xAE, 0xF6, 0x27, 0x71, 0xDB, 0xE2, 0xC9, 0x50, 0x6E, 0x20, 0xA9, 0x39, 0x8A, 0x2D, 0x2C, 0x12, 0x24, 0x2C, 0x57, 0x16, 0x0A, 0x52, 0xB6, 0x4D, 0x12, 0xA0, 0x4F, 0x7F, 0x5D, 0x0F, 0xF0, 0xB0, 0x41, 0x5C, 0x57, 0x46, 0x4C, 0x7D, 0xAC, 0xB1, 0x00}, IV: [16]byte{0x80, 0xA2, 0x11, 0x9A, 0xE8, 0xEB, 0x2C, 0x1D, 0x2B, 0xBE, 0x8D, 0x1E, 0x82, 0xA5, 0xF5, 0x72}}, {Ciphertext: []byte{0x5B, 0xC1, 0xE8, 0x85, 0xEC, 0x06, 0xFA, 0x30, 0x76, 0xFC, 0xAD, 0xDE, 0x3D, 0x59, 0x79, 0x0B, 0x74, 0x1F, 0xAB, 0xCA, 0xAA, 0xA2, 0x38, 0x8A, 0xC5, 0x89, 0x36, 0xBC, 0x69, 0x6D, 0x86, 0xF2, 0x85, 0xB0, 0x7C, 0x65, 0x95, 0xF4, 0xE3, 0x72, 0x36, 0xD3, 0xC7, 0xC0, 0x7A, 0xF1, 0x1D, 0xA8, 0xDA, 0x80, 0xD7, 0xC9, 0x1B, 0xA5, 0x0B, 0x6C, 0xFB, 0xC9, 0xCF, 0x46, 0x19, 0xB9, 0x40, 0xB0, 0x20, 0x26, 0x74, 0xAE, 0x89, 0x52, 0x92, 0x42, 0x3F, 0x2B, 0x7C, 0xAF, 0x9C, 0x7F, 0x6F, 0x65, 0x1B, 0x28, 0xFB, 0x8D, 0x20, 0xB0, 0x47, 0xD5, 0xB4, 0xB4, 0x4B, 0x65}, IV: [16]byte{0x5B, 0xC1, 0xE8, 0x85, 0xEC, 0x06, 0xFA, 0x30, 0x76, 0xFC, 0xAD, 0xDE, 0x8D, 0xAA, 0x77, 0x1E}},
{Ciphertext: []byte{0xAE, 0x47, 0xCD, 0xAD, 0x46, 0x2C, 0xD7, 0xC2, 0xF4, 0x37, 0x25, 0xC9, 0x14, 0x8E, 0x90, 0xBD, 0x63, 0xA8, 0x0C, 0xA5, 0x86, 0x02, 0xE0, 0x9C, 0xCD, 0x70, 0xFC, 0x20, 0x51, 0x01, 0x0E, 0xCF, 0x7D, 0xD2, 0xB4, 0x6B, 0x07, 0xE9, 0x2A, 0x6E, 0x89, 0x2F, 0xAC, 0x7A, 0x07, 0xCA, 0x0B, 0x50, 0x12, 0x8F, 0x69, 0x29, 0xC4, 0x58, 0xB0, 0x0E, 0x6E, 0xBF, 0x0C, 0xBD, 0x9B, 0x8B, 0xC0, 0x10, 0xB8, 0x7F, 0x89, 0x7F, 0x85, 0xF8, 0x04, 0xFF, 0x24, 0xE8, 0x68, 0x12, 0x6D, 0xBC, 0x2E, 0xF3, 0xD0, 0xD5, 0x4A, 0x38, 0x1C, 0x12, 0x28, 0xD5, 0x1D, 0x55, 0xC8, 0xF6}, IV: [16]byte{0xAE, 0x47, 0xCD, 0xAD, 0x46, 0x2C, 0xD7, 0xC2, 0xF4, 0x37, 0x25, 0xC9, 0xE9, 0x58, 0x3C, 0x30}}, {Ciphertext: []byte{0x31, 0x75, 0x43, 0xA2, 0x25, 0x22, 0xFC, 0x95, 0xDC, 0xBF, 0x29, 0xFA, 0x05, 0x45, 0xB4, 0x0A, 0xD5, 0xE9, 0xAD, 0xA4, 0x0F, 0x64, 0x08, 0xA9, 0x91, 0x8D, 0x72, 0x01, 0x8B, 0xD6, 0x45, 0x20, 0x4A, 0x08, 0x75, 0x53, 0x0C, 0xBD, 0xED, 0x88, 0x2A, 0x16, 0x18, 0x8F, 0x90, 0xD9, 0x07, 0xDE, 0xDD, 0xFF, 0x34, 0x32, 0x66, 0x62, 0xDE, 0x04, 0x61, 0xF9, 0x42, 0xCE, 0xC1, 0x61, 0xC5, 0x4D, 0x31, 0x53, 0x40, 0x79, 0x4A, 0xC7, 0xF7, 0x17, 0x28, 0x7C, 0xD9, 0x10, 0x7E, 0xCC, 0x52, 0xDC, 0x52, 0xD1, 0x7E, 0x39, 0xE0, 0x01, 0x65, 0x7A, 0xB8, 0xEA, 0xA3, 0x4F}, IV: [16]byte{0x31, 0x75, 0x43, 0xA2, 0x25, 0x22, 0xFC, 0x95, 0xDC, 0xBF, 0x29, 0xFA, 0x20, 0xFD, 0x70, 0x86}},
{Ciphertext: []byte{0x46, 0x59, 0xD5, 0x11, 0x98, 0xE7, 0xC9, 0x0F, 0x00, 0xB9, 0x73, 0xD7, 0x62, 0xF0, 0x2E, 0xC6, 0x19, 0xF9, 0x45, 0xF7, 0x0B, 0x57, 0x35, 0x1F, 0xC9, 0xEB, 0x80, 0xBE, 0x19, 0xBE, 0x6B, 0xE3, 0x82, 0x39, 0x88, 0xF6, 0x95, 0x67, 0x47, 0x7D, 0xBC, 0xC9, 0xD3, 0x83, 0x1C, 0xAE, 0x47, 0xEF, 0xD6, 0x6D, 0x49, 0x01, 0xEA, 0x7F, 0x9A, 0x96, 0xEC, 0xA8, 0x22, 0x7A, 0x1D, 0x49, 0x2B, 0x34, 0x22, 0x2A, 0xFF, 0x3F, 0xF1, 0xEB, 0xDD, 0x5B, 0xB5, 0xFD, 0xB3, 0x6B, 0x4A, 0x44, 0x16, 0xCB, 0x9A, 0x70, 0x1F, 0xD9, 0x32, 0x0C, 0x4D, 0x96, 0x6D, 0x26, 0xCB, 0x93}, IV: [16]byte{0x46, 0x59, 0xD5, 0x11, 0x98, 0xE7, 0xC9, 0x0F, 0x00, 0xB9, 0x73, 0xD7, 0x67, 0x7C, 0x66, 0x1A}}, {Ciphertext: []byte{0x5B, 0xD6, 0x4E, 0xC9, 0x35, 0x81, 0x52, 0x5D, 0x3B, 0x1B, 0xCF, 0xBD, 0xB4, 0xF4, 0x36, 0x26, 0xFB, 0x60, 0x51, 0x9D, 0x71, 0xBB, 0x1F, 0x0E, 0x57, 0xE5, 0xED, 0x5A, 0xC7, 0x64, 0xFE, 0x3E, 0x9A, 0x1D, 0xAB, 0x61, 0x40, 0x44, 0x6F, 0xE1, 0xC2, 0xB9, 0xAB, 0xB9, 0xD8, 0x4A, 0xB4, 0xF7, 0x45, 0xC4, 0xEE, 0x73, 0x6B, 0x09, 0x17, 0x16, 0x21, 0x99, 0x14, 0xEE, 0x36, 0x96, 0x89, 0xB3, 0x3D, 0xD3, 0x5C, 0x4F, 0x86, 0xBA, 0x6F, 0xEB, 0x62, 0x40, 0x86, 0x8E, 0x5C, 0xF6, 0x07, 0x43, 0x3C, 0x02, 0x77, 0xCB, 0xD9, 0x5B, 0xB8, 0x34, 0x1C, 0x21, 0x60, 0xA7}, IV: [16]byte{0x5B, 0xD6, 0x4E, 0xC9, 0x35, 0x81, 0x52, 0x5D, 0x3B, 0x1B, 0xCF, 0xBD, 0x01, 0x03, 0xDB, 0xB8}},
{Ciphertext: []byte{0xB5, 0x89, 0x78, 0x8E, 0x5F, 0x5D, 0xBB, 0xF4, 0xF2, 0x5E, 0x18, 0x2A, 0xA8, 0x1A, 0x69, 0x70, 0xF9, 0xB9, 0x8A, 0xDF, 0x4D, 0x25, 0x6A, 0x78, 0xD8, 0xD4, 0x16, 0xD8, 0xDF, 0x39, 0x2B, 0x78, 0x51, 0x8C, 0xBA, 0x8D, 0x76, 0xBF, 0x53, 0xCB, 0xDB, 0x59, 0xEF, 0xDF, 0x9C, 0x1C, 0xDA, 0xC3, 0x3A, 0x89, 0xD8, 0x31, 0x7E, 0xD3, 0x79, 0x08, 0x66, 0xF5, 0x7F, 0x58, 0x2B, 0x7D, 0xA9, 0x83, 0xE3, 0xBC, 0x64, 0xC7, 0xD9, 0xCC, 0x19, 0xAD, 0xF2, 0x93, 0x3C, 0xB1, 0x61, 0xFC, 0x7B, 0x03, 0x30, 0x51, 0x41, 0x48, 0x51, 0x04, 0x45, 0x14, 0xD1, 0x14, 0x72, 0x0B}, IV: [16]byte{0xB5, 0x89, 0x78, 0x8E, 0x5F, 0x5D, 0xBB, 0xF4, 0xF2, 0x5E, 0x18, 0x2A, 0x68, 0x6E, 0x1A, 0x33}}, {Ciphertext: []byte{0xA9, 0x7E, 0xDF, 0x65, 0xF7, 0xCD, 0xB4, 0xD1, 0x54, 0xDC, 0x11, 0xCF, 0xF8, 0xD1, 0x8D, 0x89, 0xB5, 0xA2, 0x8C, 0xB0, 0xCD, 0x8A, 0x80, 0x75, 0x65, 0xF3, 0x7D, 0x9B, 0x68, 0x79, 0x07, 0x3E, 0x47, 0xA2, 0x89, 0x8C, 0x57, 0x2E, 0xFB, 0xBC, 0x7B, 0x49, 0x81, 0x33, 0x2A, 0xBB, 0xB3, 0x69, 0x7B, 0xEB, 0x15, 0xDE, 0xC6, 0x65, 0x57, 0x6D, 0xD5, 0x35, 0x57, 0x9F, 0x4C, 0x77, 0x1A, 0x83, 0xE8, 0x04, 0x3A, 0x65, 0x53, 0x61, 0x51, 0xE4, 0x2E, 0x48, 0x0F, 0xD0, 0xD1, 0x7F, 0x18, 0x7A, 0x69, 0xC1, 0x14, 0x9F, 0x79, 0x0A, 0x8B, 0x6D, 0xAF, 0x0E, 0x40, 0xE7}, IV: [16]byte{0xA9, 0x7E, 0xDF, 0x65, 0xF7, 0xCD, 0xB4, 0xD1, 0x54, 0xDC, 0x11, 0xCF, 0x6A, 0x6A, 0xA6, 0x35}},
{Ciphertext: []byte{0x8B, 0x4E, 0xB4, 0x83, 0x28, 0x49, 0x0F, 0x3B, 0x26, 0xB3, 0x86, 0x31, 0x7F, 0x88, 0x6C, 0x57, 0x53, 0x5B, 0x22, 0xB7, 0x9D, 0xBB, 0x9B, 0x16, 0x9C, 0xAC, 0xAE, 0xC2, 0xAA, 0x7E, 0x59, 0xC5, 0x6C, 0x57, 0xB2, 0xA3, 0x0B, 0xDE, 0x15, 0x42, 0x3A, 0x8C, 0x04, 0x31, 0x4F, 0x44, 0x7F, 0x5E, 0x9B, 0x41, 0x8A, 0x00, 0x05, 0x44, 0x0A, 0x7C, 0x87, 0xD7, 0xF3, 0x56, 0x03, 0xFF, 0x71, 0x58, 0xC2, 0x7E, 0xB0, 0xC9, 0x57, 0x00, 0x78, 0x4A, 0xF2, 0x3C, 0xAB, 0xB0, 0x30, 0x65, 0x1C, 0xB7, 0xD5, 0xC6, 0xC3, 0x16, 0x01, 0x86, 0xC9, 0xD2, 0x8D, 0x04, 0xF0, 0xB9}, IV: [16]byte{0x8B, 0x4E, 0xB4, 0x83, 0x28, 0x49, 0x0F, 0x3B, 0x26, 0xB3, 0x86, 0x31, 0x83, 0xD0, 0x78, 0x5B}}, {Ciphertext: []byte{0x2B, 0x52, 0x89, 0x10, 0x1F, 0x72, 0xCC, 0xDF, 0xD3, 0x8E, 0x1B, 0xC0, 0x16, 0x36, 0x97, 0x2B, 0x00, 0x17, 0x7F, 0x1D, 0x3E, 0x4C, 0x20, 0x5F, 0x48, 0x08, 0x41, 0xBC, 0x32, 0xE3, 0xFA, 0x10, 0x03, 0x0B, 0x6E, 0x3E, 0x67, 0x36, 0x90, 0x31, 0xFE, 0x55, 0xFD, 0x5E, 0x7A, 0xDD, 0xF8, 0x3B, 0xA8, 0x0B, 0x98, 0xDB, 0x22, 0x7D, 0xE5, 0xF9, 0xE8, 0xEF, 0x17, 0x68, 0x2A, 0x17, 0xA8, 0x2B, 0x93, 0x62, 0x28, 0x76, 0xC7, 0x48, 0xC2, 0xBD, 0xEF, 0xE5, 0x58, 0x0C, 0x13, 0x4B, 0x68, 0x93, 0x7F, 0x51, 0xD3, 0x49, 0xE4, 0xBA, 0xE8, 0xDB, 0xCA, 0x61, 0x04, 0xA2}, IV: [16]byte{0x2B, 0x52, 0x89, 0x10, 0x1F, 0x72, 0xCC, 0xDF, 0xD3, 0x8E, 0x1B, 0xC0, 0x22, 0x3D, 0x46, 0x43}},
{Ciphertext: []byte{0x25, 0xB7, 0xFA, 0x94, 0x6A, 0x73, 0x1F, 0x9E, 0xE2, 0x13, 0x6E, 0x18, 0x07, 0x94, 0x74, 0x6F, 0xE6, 0xB9, 0x48, 0xCD, 0xFA, 0x6B, 0x7D, 0xB4, 0x84, 0x1B, 0xDC, 0x3C, 0x30, 0x4D, 0x99, 0xA4, 0xA7, 0x9A, 0x52, 0x43, 0x41, 0x7B, 0x9F, 0x86, 0x7A, 0x7C, 0x25, 0x55, 0x75, 0x38, 0x4B, 0x37, 0x92, 0x97, 0x96, 0xE5, 0x35, 0xDD, 0x44, 0xCF, 0x45, 0xF1, 0x9F, 0x92, 0x9B, 0xEB, 0x30, 0x9F, 0x7E, 0x64, 0x98, 0x5D, 0x78, 0x31, 0xFA, 0x73, 0x57, 0x1D, 0xF0, 0xAC, 0xBB, 0xA1, 0xC9, 0x57, 0x4B, 0x8D, 0x62, 0x80, 0xBE, 0x1C, 0xA9, 0xE1, 0x34, 0x56, 0xB3, 0xAA}, IV: [16]byte{0x25, 0xB7, 0xFA, 0x94, 0x6A, 0x73, 0x1F, 0x9E, 0xE2, 0x13, 0x6E, 0x18, 0x75, 0xB7, 0x15, 0x4C}}, {Ciphertext: []byte{0xE1, 0xAB, 0xA0, 0x53, 0xEB, 0x0E, 0xB0, 0x77, 0x9D, 0xFA, 0xB0, 0x6A, 0x97, 0xAF, 0x78, 0x2F, 0x40, 0x6A, 0x52, 0xC4, 0xBF, 0x89, 0xBF, 0x96, 0x7D, 0xE5, 0x5F, 0x73, 0xA7, 0x94, 0xA8, 0xA0, 0xAA, 0x47, 0xBD, 0xE4, 0xAF, 0xEE, 0x9B, 0x07, 0xAB, 0x31, 0xD6, 0x72, 0xE2, 0x75, 0x8C, 0x3C, 0x34, 0x4E, 0xC8, 0xA8, 0x05, 0x6F, 0xCB, 0x80, 0xD8, 0x2D, 0x48, 0xD2, 0xA0, 0xB5, 0x5C, 0x87, 0x4A, 0x5A, 0x72, 0x7D, 0xEB, 0x4A, 0x26, 0x68, 0x20, 0x72, 0x1C, 0x64, 0x9C, 0xDB, 0x28, 0xF0, 0x8C, 0x09, 0xF6, 0x74, 0x71, 0xC9, 0x72, 0xE3, 0x2E, 0x51, 0x49, 0xDC}, IV: [16]byte{0xE1, 0xAB, 0xA0, 0x53, 0xEB, 0x0E, 0xB0, 0x77, 0x9D, 0xFA, 0xB0, 0x6A, 0x59, 0x10, 0xB0, 0xD0}},
{Ciphertext: []byte{0x10, 0xD7, 0x54, 0xA5, 0x47, 0xDC, 0x58, 0xA2, 0xCD, 0x56, 0x39, 0x85, 0x5E, 0x43, 0x93, 0x14, 0x64, 0xF7, 0x22, 0x60, 0x4A, 0x38, 0x35, 0xF8, 0x6C, 0xA5, 0xE1, 0x3C, 0xD0, 0x42, 0xD8, 0x47, 0xBF, 0xE2, 0x81, 0x35, 0x4D, 0x56, 0xCC, 0x94, 0xA2, 0xF1, 0xD7, 0x5F, 0xD7, 0x48, 0xA5, 0x76, 0x12, 0x9D, 0x42, 0xAC, 0xA6, 0xDC, 0x3D, 0x16, 0xEC, 0x84, 0xC6, 0x1C, 0x00, 0x3C, 0xDA, 0xE1, 0x41, 0xD2, 0x22, 0x30, 0xE1, 0x01, 0x08, 0x71, 0x9A, 0xDF, 0x5B, 0x18, 0xC1, 0x70, 0xA9, 0x05, 0xAF, 0xAA, 0x02, 0x96, 0xC7, 0x73, 0x1F, 0xD3, 0x26, 0x9D, 0xCC, 0xA1}, IV: [16]byte{0x10, 0xD7, 0x54, 0xA5, 0x47, 0xDC, 0x58, 0xA2, 0xCD, 0x56, 0x39, 0x85, 0x53, 0x5F, 0xA9, 0x9E}}, {Ciphertext: []byte{0xB4, 0x98, 0x9A, 0x4D, 0x06, 0xF6, 0x80, 0x02, 0x50, 0xCF, 0x7B, 0x13, 0xE4, 0x82, 0x0A, 0xC7, 0x59, 0xD7, 0x3E, 0x96, 0xBB, 0x57, 0x55, 0x1E, 0xFD, 0xE7, 0x9E, 0x28, 0x2D, 0xEE, 0x40, 0x03, 0x42, 0x9E, 0x78, 0x06, 0x89, 0x48, 0x78, 0x98, 0xA2, 0x12, 0x3E, 0x16, 0x31, 0x0C, 0x2B, 0x09, 0x44, 0xA2, 0x69, 0x31, 0xBD, 0x8A, 0x70, 0x7A, 0x1F, 0x9D, 0x92, 0xE7, 0x3B, 0xE7, 0xDC, 0xCF, 0x95, 0x9B, 0x58, 0xB3, 0xEF, 0xD9, 0xB5, 0x0F, 0x3E, 0xA1, 0xDF, 0x05, 0x9C, 0x3F, 0x91, 0x24, 0x1F, 0x24, 0x7D, 0x54, 0x50, 0x69, 0xAC, 0x0A, 0x10, 0x01, 0x3D, 0xBF}, IV: [16]byte{0xB4, 0x98, 0x9A, 0x4D, 0x06, 0xF6, 0x80, 0x02, 0x50, 0xCF, 0x7B, 0x13, 0xEE, 0x94, 0x07, 0xC6}},
{Ciphertext: []byte{0x41, 0xE3, 0xEF, 0x63, 0x8F, 0xE4, 0xD6, 0x20, 0xE1, 0x94, 0x93, 0x56, 0x6D, 0xA1, 0x9F, 0x44, 0xC2, 0x6E, 0x64, 0xAE, 0xB6, 0x9C, 0x95, 0x8E, 0x0F, 0x08, 0xF6, 0xAF, 0xDF, 0x68, 0xFE, 0x20, 0xC3, 0x6D, 0xF5, 0x03, 0x07, 0xCD, 0xA2, 0x6B, 0xD1, 0x5D, 0xBA, 0x63, 0xAB, 0x29, 0x7C, 0x79, 0xD1, 0xC8, 0xEA, 0x29, 0xFA, 0x70, 0xC6, 0x67, 0xCC, 0x9E, 0x2A, 0xB8, 0x33, 0xE0, 0x80, 0x29, 0x5D, 0x0C, 0xBB, 0x08, 0x26, 0x46, 0x27, 0xD2, 0x9A, 0xE2, 0x9C, 0x50, 0xBE, 0x40, 0x08, 0xF6, 0x30, 0xCD, 0x1B, 0xD4, 0x13, 0x43, 0x3B, 0xB9, 0x59, 0x7F, 0xFE, 0x16}, IV: [16]byte{0x41, 0xE3, 0xEF, 0x63, 0x8F, 0xE4, 0xD6, 0x20, 0xE1, 0x94, 0x93, 0x56, 0x50, 0x1F, 0xDB, 0xD5}}, {Ciphertext: []byte{0xCF, 0xE1, 0xD2, 0x93, 0x18, 0xD2, 0x0F, 0x36, 0x27, 0x87, 0x27, 0x57, 0x4D, 0x82, 0x33, 0xDE, 0xCC, 0xE1, 0x88, 0x09, 0xE0, 0x4F, 0x6F, 0xA3, 0xC0, 0x2E, 0x82, 0x84, 0xCE, 0x33, 0xF1, 0x64, 0xBA, 0x46, 0xA1, 0xA2, 0x99, 0x25, 0x9B, 0x33, 0xFF, 0x80, 0x6E, 0x42, 0x36, 0x18, 0x34, 0xCA, 0x09, 0x96, 0xC4, 0xFC, 0x86, 0x52, 0x0D, 0xC2, 0x8D, 0xFF, 0x74, 0x11, 0x15, 0xEC, 0xED, 0xD3, 0x71, 0x66, 0x50, 0x82, 0xD9, 0xF7, 0x96, 0x80, 0x07, 0x06, 0xDD, 0x57, 0x9C, 0xEB, 0x56, 0x8D, 0x4C, 0xAA, 0x8A, 0xF2, 0x06, 0x24, 0x8C, 0x3A, 0x43, 0xBD, 0xC6, 0x49}, IV: [16]byte{0xCF, 0xE1, 0xD2, 0x93, 0x18, 0xD2, 0x0F, 0x36, 0x27, 0x87, 0x27, 0x57, 0x60, 0x1A, 0xAA, 0x6C}},
{Ciphertext: []byte{0xD0, 0x95, 0xC4, 0xA9, 0xBA, 0x36, 0x14, 0x34, 0x8B, 0xC8, 0xA6, 0xF9, 0x9F, 0xB7, 0x37, 0x3C, 0xFE, 0x13, 0x0C, 0xA0, 0xDD, 0xAF, 0x6E, 0x0C, 0x11, 0x67, 0xCB, 0xC1, 0xE8, 0xC9, 0xA2, 0xB1, 0x75, 0x50, 0x43, 0x0C, 0x61, 0x03, 0xCA, 0x26, 0x0A, 0xB5, 0x24, 0x81, 0x59, 0x43, 0xED, 0x8B, 0x62, 0x3E, 0x7E, 0xB9, 0x0E, 0x8C, 0xE5, 0xDD, 0x3B, 0x29, 0xF2, 0xB2, 0x27, 0xAE, 0xA0, 0xBA, 0x51, 0xBD, 0x23, 0xD0, 0xCB, 0xDD, 0x8A, 0xC9, 0x95, 0xCE, 0x94, 0x02, 0xC9, 0xD3, 0xF5, 0x8E, 0xAD, 0xE4, 0xCB, 0xCB, 0xF0, 0x79, 0xF0, 0x7E, 0xDB, 0x1E, 0xA1, 0x18}, IV: [16]byte{0xD0, 0x95, 0xC4, 0xA9, 0xBA, 0x36, 0x14, 0x34, 0x8B, 0xC8, 0xA6, 0xF9, 0x2C, 0xF0, 0x54, 0x17}}, {Ciphertext: []byte{0x38, 0x69, 0x2E, 0xDD, 0x18, 0x24, 0x28, 0xE4, 0x88, 0x33, 0xA3, 0xFC, 0x39, 0x3D, 0x48, 0x07, 0xF7, 0x03, 0xBC, 0x68, 0x53, 0x2A, 0x57, 0x92, 0x01, 0x57, 0x04, 0x4D, 0xC8, 0xE6, 0xD4, 0x21, 0xA9, 0xDB, 0xA3, 0xFF, 0xCB, 0x56, 0x9A, 0x16, 0x58, 0x48, 0x2D, 0xF5, 0x25, 0x86, 0x21, 0x2E, 0x95, 0x85, 0x16, 0xA6, 0x24, 0x6D, 0x23, 0x98, 0xF3, 0xE0, 0x96, 0x1A, 0x27, 0x69, 0x50, 0xDD, 0xA8, 0x04, 0x37, 0x0B, 0xAE, 0xC7, 0xEB, 0x80, 0xA1, 0xBD, 0x0B, 0x55, 0x72, 0x3E, 0x62, 0x45, 0x1F, 0xF9, 0xBF, 0x1B, 0xBF, 0xE5, 0xA1, 0x4C, 0x5B, 0x7A, 0x23, 0x6E}, IV: [16]byte{0x38, 0x69, 0x2E, 0xDD, 0x18, 0x24, 0x28, 0xE4, 0x88, 0x33, 0xA3, 0xFC, 0x27, 0x5F, 0x02, 0x1C}},
{Ciphertext: []byte{0xD6, 0x45, 0x9B, 0xDD, 0xA1, 0xFF, 0xE1, 0x64, 0x58, 0x5B, 0x4D, 0x4B, 0x78, 0xAF, 0x8A, 0x00, 0xA2, 0xB2, 0x0C, 0x80, 0x68, 0x03, 0xDC, 0x8B, 0xFC, 0x3E, 0xBD, 0x24, 0x22, 0xCC, 0x6D, 0x50, 0x4A, 0xDD, 0x8A, 0xE4, 0x82, 0xD4, 0x4D, 0x15, 0xB7, 0x7D, 0x36, 0x7E, 0x7A, 0xA5, 0x80, 0x01, 0x82, 0xD0, 0x7B, 0x24, 0x5D, 0x22, 0xB8, 0x44, 0x8E, 0x12, 0x39, 0xB7, 0x6A, 0x3F, 0xC0, 0xA2, 0xA0, 0x7C, 0x54, 0x3F, 0xE5, 0x93, 0x91, 0x3D, 0xF7, 0xC3, 0x7F, 0xE7, 0x2E, 0x9D, 0x24, 0x15, 0x76, 0x4E, 0x77, 0x8D, 0xA8, 0x08, 0xAD, 0x3F, 0x6A, 0x14, 0xCA, 0xBC}, IV: [16]byte{0xD6, 0x45, 0x9B, 0xDD, 0xA1, 0xFF, 0xE1, 0x64, 0x58, 0x5B, 0x4D, 0x4B, 0xF9, 0xDC, 0x35, 0xB6}}, {Ciphertext: []byte{0xC4, 0x12, 0xF5, 0x8D, 0xC7, 0x0A, 0x06, 0x5E, 0xA7, 0xA3, 0x2B, 0xBF, 0xA4, 0x39, 0xA9, 0x9F, 0xC9, 0x58, 0xC8, 0x0D, 0x62, 0x8B, 0x0A, 0x0B, 0x33, 0x86, 0x7D, 0xB0, 0x01, 0x1B, 0x5B, 0x06, 0x40, 0x86, 0x97, 0x6D, 0x25, 0x39, 0xC7, 0x6A, 0xCB, 0x63, 0xD3, 0x83, 0x82, 0xFC, 0x24, 0x47, 0xE2, 0xDD, 0x8B, 0x5E, 0x19, 0x98, 0x2A, 0xC3, 0xA0, 0xD8, 0xA5, 0x74, 0xAA, 0x47, 0x94, 0x61, 0x2B, 0xD8, 0x49, 0x89, 0x38, 0x74, 0x65, 0x7F, 0x54, 0xD5, 0xDF, 0xD6, 0x94, 0xB4, 0x58, 0xAE, 0xCE, 0xBD, 0x45, 0xF7, 0x4C, 0x14, 0xF3, 0xF8, 0xDB, 0xBF, 0x7F, 0x35}, IV: [16]byte{0xC4, 0x12, 0xF5, 0x8D, 0xC7, 0x0A, 0x06, 0x5E, 0xA7, 0xA3, 0x2B, 0xBF, 0x40, 0x65, 0x3E, 0x8B}},
{Ciphertext: []byte{0xA1, 0x89, 0xDB, 0x84, 0xE2, 0x8B, 0x10, 0xC2, 0xB2, 0xB5, 0x0A, 0x3C, 0xE4, 0x05, 0x6A, 0x6F, 0xA9, 0x8A, 0xDC, 0xE4, 0xB8, 0x23, 0x32, 0xBA, 0x80, 0x96, 0x99, 0x93, 0x0C, 0xF6, 0x71, 0x93, 0x55, 0x84, 0xE0, 0x48, 0xEC, 0xEE, 0xEF, 0xD6, 0x6A, 0xB1, 0x84, 0x15, 0x0F, 0x16, 0x8A, 0x37, 0x16, 0x22, 0x7B, 0x77, 0x92, 0x2B, 0xB4, 0xB1, 0x69, 0xCE, 0x13, 0x23, 0x32, 0x2F, 0x2B, 0xC3, 0x85, 0x60, 0x2E, 0xA2, 0x31, 0x00, 0x96, 0x75, 0xFC, 0x29, 0x74, 0xBF, 0xC3, 0xE4, 0x2E, 0x47, 0x73, 0xE7, 0x91, 0x9E, 0x94, 0x78, 0x3C, 0xC4, 0xA0, 0x9C, 0x1D, 0xE8}, IV: [16]byte{0xA1, 0x89, 0xDB, 0x84, 0xE2, 0x8B, 0x10, 0xC2, 0xB2, 0xB5, 0x0A, 0x3C, 0xDC, 0x55, 0xDE, 0xAB}}, {Ciphertext: []byte{0x1A, 0xD9, 0xDD, 0x57, 0xF2, 0x7B, 0xD1, 0x59, 0xEB, 0xEC, 0x91, 0xDF, 0x96, 0xEF, 0xC5, 0x48, 0x02, 0xE6, 0x77, 0xD8, 0x5D, 0xF2, 0xDE, 0xD9, 0x0E, 0x4A, 0xD4, 0x7C, 0xF1, 0x5C, 0x68, 0xBC, 0xDD, 0x8D, 0x9C, 0xEC, 0x4F, 0x2C, 0x45, 0x70, 0x51, 0xAA, 0xEB, 0xA8, 0x3F, 0x35, 0x3C, 0x66, 0x4E, 0x14, 0x43, 0x63, 0x88, 0x04, 0x73, 0xC2, 0x69, 0x76, 0x41, 0x4F, 0x3C, 0x50, 0x1F, 0x3A, 0x5A, 0x8B, 0xFE, 0xE0, 0x85, 0x63, 0xA0, 0x45, 0x64, 0x28, 0xB2, 0x4D, 0x8E, 0x65, 0x90, 0xEF, 0x03, 0xAE, 0xA3, 0xB1, 0x52, 0xA5, 0xD5, 0xC0, 0xBC, 0xE3, 0x63, 0xCB}, IV: [16]byte{0x1A, 0xD9, 0xDD, 0x57, 0xF2, 0x7B, 0xD1, 0x59, 0xEB, 0xEC, 0x91, 0xDF, 0xFC, 0x18, 0x6B, 0x2A}},
{Ciphertext: []byte{0xF2, 0x0F, 0x1E, 0x76, 0x95, 0xED, 0x1A, 0x03, 0x18, 0x5C, 0x51, 0x73, 0xE1, 0x8E, 0xE7, 0xEE, 0x34, 0x74, 0x6B, 0xCB, 0x6A, 0x11, 0x40, 0x30, 0xE7, 0x3A, 0x0C, 0xCA, 0xAE, 0x9C, 0xF0, 0x9E, 0x78, 0xD0, 0xE7, 0xDC, 0x3D, 0x27, 0x6A, 0x7A, 0x78, 0x77, 0xD4, 0xAA, 0x4F, 0xC9, 0xAC, 0x27, 0x68, 0x8C, 0x48, 0x1C, 0x52, 0xD1, 0x22, 0xC6, 0x9A, 0x66, 0x01, 0x3F, 0x86, 0xC7, 0xF5, 0xC9, 0x13, 0xDD, 0x70, 0xB3, 0xF9, 0x62, 0xF6, 0x7E, 0x3D, 0xB5, 0x60, 0x91, 0x35, 0x60, 0x4E, 0x99, 0x3B, 0xAB, 0x5B, 0x4F, 0xBD, 0x54, 0x05, 0xA7, 0x9C, 0xF8, 0x69, 0xDD}, IV: [16]byte{0xF2, 0x0F, 0x1E, 0x76, 0x95, 0xED, 0x1A, 0x03, 0x18, 0x5C, 0x51, 0x73, 0xBE, 0x4C, 0x12, 0x5F}}, {Ciphertext: []byte{0x8B, 0x4C, 0xC7, 0x09, 0x0A, 0xE1, 0xC8, 0x47, 0x4B, 0xD0, 0xFA, 0x71, 0xCE, 0xEB, 0x19, 0x70, 0xC7, 0xAA, 0xFA, 0xAE, 0xD1, 0x8B, 0x76, 0xC5, 0x54, 0x00, 0xCE, 0x2A, 0xD5, 0x2E, 0x97, 0x94, 0x47, 0x8F, 0xB1, 0x1E, 0x87, 0x59, 0x5A, 0xD3, 0xA8, 0xE0, 0xD9, 0xBC, 0xB1, 0xD9, 0x12, 0x34, 0x87, 0xBA, 0x10, 0x1A, 0xB8, 0x37, 0xA7, 0x0E, 0xCB, 0x28, 0x5C, 0xF6, 0xBC, 0xF1, 0x85, 0xC2, 0xC8, 0x89, 0x8D, 0x85, 0xF8, 0x58, 0x92, 0x81, 0x52, 0xE6, 0xC3, 0x40, 0xA1, 0xD3, 0xAF, 0x89, 0xB7, 0x90, 0xF6, 0xB7, 0x58, 0x25, 0x3B, 0x7A, 0xE9, 0x6E, 0x45, 0x16}, IV: [16]byte{0x8B, 0x4C, 0xC7, 0x09, 0x0A, 0xE1, 0xC8, 0x47, 0x4B, 0xD0, 0xFA, 0x71, 0x3C, 0xEE, 0xA4, 0xC6}},
{Ciphertext: []byte{0xCB, 0x41, 0x34, 0x92, 0xAF, 0xF4, 0xF1, 0xD0, 0x80, 0x48, 0x53, 0x79, 0x7C, 0xE0, 0x28, 0xD9, 0x71, 0xB1, 0xB4, 0xA4, 0xB1, 0x97, 0x5B, 0xE2, 0x29, 0x73, 0xDF, 0x0B, 0x3D, 0x79, 0x82, 0xA3, 0x53, 0xC2, 0x73, 0x4B, 0x09, 0x3F, 0x4B, 0xA1, 0x9B, 0xB2, 0xB9, 0xA9, 0x59, 0xEF, 0xF8, 0x2D, 0xCB, 0x71, 0xE9, 0x94, 0x6A, 0x0B, 0xF8, 0xE5, 0x5D, 0x7A, 0x55, 0xE4, 0x7E, 0x55, 0x4B, 0x04, 0x97, 0x3D, 0xBF, 0x24, 0x99, 0xE7, 0x58, 0x2D, 0xFC, 0x38, 0x57, 0xBB, 0x34, 0x2B, 0x68, 0xA5, 0x88, 0x7C, 0x59, 0xD8, 0x0A, 0x1C, 0x41, 0x3E, 0xBB, 0x1E, 0x07, 0x12}, IV: [16]byte{0xCB, 0x41, 0x34, 0x92, 0xAF, 0xF4, 0xF1, 0xD0, 0x80, 0x48, 0x53, 0x79, 0x59, 0x6B, 0xCD, 0x66}}, {Ciphertext: []byte{0x45, 0x1C, 0xF2, 0x62, 0x51, 0x45, 0x07, 0x74, 0x1F, 0xCF, 0xC6, 0xB1, 0x05, 0xDF, 0x88, 0xCD, 0x5C, 0x3F, 0x14, 0x9D, 0x90, 0x62, 0x80, 0xDD, 0x08, 0xC9, 0xB1, 0x20, 0x21, 0xAD, 0x4D, 0x9D, 0xA6, 0x8F, 0xCC, 0xE9, 0x83, 0xD6, 0x17, 0x82, 0xE5, 0x28, 0x0B, 0x73, 0x9F, 0x68, 0xD6, 0xAE, 0x9F, 0x32, 0x62, 0x80, 0x91, 0xE6, 0x09, 0xE5, 0x14, 0x0E, 0x87, 0x98, 0x4B, 0x9B, 0x67, 0x4F, 0x6B, 0x0D, 0x67, 0xED, 0x4A, 0x6A, 0xFD, 0x09, 0x12, 0xA3, 0xC7, 0x07, 0xC7, 0xFE, 0x8C, 0x07, 0xAF, 0x77, 0x42, 0x14, 0xB0, 0x44, 0xEC, 0xB0, 0xB5, 0x0C, 0x6D, 0x09}, IV: [16]byte{0x45, 0x1C, 0xF2, 0x62, 0x51, 0x45, 0x07, 0x74, 0x1F, 0xCF, 0xC6, 0xB1, 0xD2, 0xD9, 0x3B, 0xA0}},
{Ciphertext: []byte{0x3E, 0x17, 0x48, 0x61, 0x49, 0x4E, 0xBA, 0xF6, 0x00, 0xB9, 0x7D, 0x78, 0x55, 0xC7, 0xA1, 0x0D, 0xAD, 0xB4, 0x10, 0x16, 0x25, 0x24, 0xC3, 0xE5, 0x95, 0xF8, 0x42, 0xF5, 0xC4, 0xF9, 0x01, 0x4E, 0x9E, 0x1A, 0x05, 0x26, 0x2B, 0xF9, 0x7B, 0x83, 0x6B, 0xBC, 0xEB, 0xFB, 0x7B, 0x2C, 0xDD, 0x59, 0x9D, 0x94, 0x07, 0xA3, 0x8B, 0x44, 0x2B, 0x55, 0x55, 0x46, 0xA2, 0x14, 0xA8, 0x9A, 0xE7, 0x60, 0x7F, 0xA9, 0xE8, 0xD4, 0xB5, 0xB1, 0x7A, 0x4A, 0x8F, 0xCF, 0xB0, 0xB2, 0x99, 0xC6, 0x57, 0x1E, 0xF2, 0x3A, 0x00, 0x09, 0xD3, 0xD4, 0x69, 0xD7, 0x5D, 0x3D, 0x69, 0x87}, IV: [16]byte{0x3E, 0x17, 0x48, 0x61, 0x49, 0x4E, 0xBA, 0xF6, 0x00, 0xB9, 0x7D, 0x78, 0xB6, 0x9D, 0x3E, 0x6C}}, {Ciphertext: []byte{0x9E, 0xD7, 0x66, 0xF7, 0xEF, 0xFE, 0xDE, 0x19, 0x5D, 0x19, 0x16, 0x02, 0x37, 0xF6, 0xD1, 0x47, 0xB9, 0xF6, 0x9F, 0x4B, 0xC6, 0xFD, 0x45, 0xD3, 0xE4, 0x6E, 0xD4, 0xC7, 0x16, 0x76, 0x4D, 0x5E, 0xEA, 0x57, 0x85, 0x36, 0xF1, 0x95, 0x10, 0x5A, 0x03, 0xC4, 0x8E, 0x30, 0xF6, 0x4B, 0xAA, 0x0A, 0xA0, 0x38, 0x29, 0x89, 0x39, 0xDA, 0x8A, 0x9D, 0x1A, 0x15, 0x28, 0x93, 0x08, 0xE4, 0x89, 0x3C, 0x3B, 0xC4, 0xB6, 0xB8, 0x2F, 0x53, 0xDC, 0x80, 0x2B, 0xC8, 0x33, 0x9C, 0x9B, 0xDE, 0x4E, 0xA6, 0xE4, 0x6C, 0x59, 0x65, 0xAE, 0xA2, 0x59, 0x74, 0x9D, 0x76, 0xE3, 0xB3}, IV: [16]byte{0x9E, 0xD7, 0x66, 0xF7, 0xEF, 0xFE, 0xDE, 0x19, 0x5D, 0x19, 0x16, 0x02, 0xF7, 0xE2, 0x09, 0xE9}},
{Ciphertext: []byte{0x8E, 0xCC, 0x97, 0x83, 0x7F, 0xDC, 0x5C, 0x7E, 0x8C, 0xEB, 0x7A, 0x9D, 0xC9, 0x2F, 0x76, 0xE5, 0x04, 0x06, 0xD3, 0xEE, 0xB1, 0xCB, 0x65, 0xC2, 0x8D, 0x90, 0x28, 0xE9, 0x6A, 0x9F, 0xD2, 0xEB, 0x47, 0x04, 0xA2, 0xE4, 0x99, 0x19, 0x2F, 0xAC, 0xF3, 0x8A, 0x3F, 0xFA, 0x89, 0x99, 0xFF, 0xE4, 0xE1, 0xC4, 0xFE, 0xB8, 0x0C, 0x25, 0xC3, 0xEA, 0x64, 0x05, 0x81, 0x7F, 0x72, 0x8E, 0x33, 0x74, 0xCF, 0xA6, 0x7B, 0x70, 0x48, 0x59, 0x92, 0x3B, 0x3C, 0x5D, 0xC8, 0x62, 0x29, 0x60, 0x2C, 0x18, 0x05, 0x80, 0x87, 0xD1, 0xF7, 0xB5, 0x98, 0x99, 0xC1, 0x4A, 0xF1, 0xDF}, IV: [16]byte{0x8E, 0xCC, 0x97, 0x83, 0x7F, 0xDC, 0x5C, 0x7E, 0x8C, 0xEB, 0x7A, 0x9D, 0xA0, 0xD3, 0x7E, 0xE3}}, {Ciphertext: []byte{0x48, 0x7C, 0x9A, 0x69, 0x04, 0x5C, 0xAF, 0x53, 0xA6, 0xF3, 0xCD, 0x20, 0xBA, 0xA1, 0xFE, 0x95, 0x32, 0x2C, 0x62, 0x1A, 0x90, 0xCC, 0xAA, 0xA4, 0x8B, 0x5E, 0xF3, 0x93, 0x93, 0x21, 0x3E, 0x88, 0xD6, 0x2B, 0xD3, 0x9F, 0xCC, 0x9C, 0x8B, 0xEC, 0xF8, 0x87, 0xDB, 0x21, 0xDE, 0x80, 0xD4, 0xD1, 0x31, 0x91, 0xF9, 0x14, 0xC6, 0x84, 0x44, 0xCC, 0x3C, 0x86, 0x18, 0xBD, 0x94, 0x99, 0xDF, 0x95, 0x35, 0xEB, 0x9C, 0x7B, 0x03, 0x25, 0x18, 0x5C, 0xA7, 0x29, 0x37, 0xEE, 0x33, 0x7F, 0x52, 0x41, 0x65, 0xB1, 0xD9, 0x79, 0x28, 0xA7, 0x71, 0x74, 0x96, 0x08, 0x88, 0x36}, IV: [16]byte{0x48, 0x7C, 0x9A, 0x69, 0x04, 0x5C, 0xAF, 0x53, 0xA6, 0xF3, 0xCD, 0x20, 0x24, 0x12, 0xB8, 0xC1}},
{Ciphertext: []byte{0x56, 0x60, 0xCA, 0xCB, 0xB4, 0xA4, 0x62, 0xE0, 0x38, 0x67, 0xD8, 0xE3, 0xC7, 0x8F, 0x2B, 0x8E, 0x8F, 0xF9, 0x2F, 0x00, 0xD5, 0xDC, 0x0A, 0xAA, 0x1F, 0xBC, 0x1C, 0x62, 0x90, 0x3B, 0x38, 0xD7, 0x82, 0xB6, 0xDF, 0x7B, 0xD3, 0xEF, 0x4D, 0x39, 0x84, 0xE6, 0x2F, 0x57, 0x4B, 0x21, 0xFC, 0x1F, 0x46, 0xBF, 0x4A, 0xAF, 0x0C, 0x34, 0x01, 0x0C, 0xFB, 0xC3, 0x49, 0xC8, 0xEA, 0x8B, 0x62, 0xF2, 0x0C, 0x47, 0x6F, 0x19, 0x0F, 0x9E, 0x49, 0x97, 0x93, 0xE6, 0x35, 0xC0, 0xD6, 0x3C, 0xA4, 0x7D, 0x9C, 0x01, 0xB4, 0x03, 0xC8, 0x21, 0x2B, 0xE2, 0x1A, 0x4C, 0xD1, 0x24}, IV: [16]byte{0x56, 0x60, 0xCA, 0xCB, 0xB4, 0xA4, 0x62, 0xE0, 0x38, 0x67, 0xD8, 0xE3, 0x5F, 0xD3, 0xA1, 0x49}}, {Ciphertext: []byte{0x65, 0x5E, 0xCB, 0xC5, 0x9D, 0xED, 0xD6, 0x7B, 0x8D, 0x30, 0x95, 0xAC, 0x61, 0x09, 0xD4, 0xC2, 0x35, 0x49, 0xA9, 0x31, 0x6F, 0x32, 0x84, 0x72, 0x15, 0x76, 0x59, 0xA6, 0xB3, 0x90, 0xB2, 0xA1, 0x08, 0x7D, 0x72, 0x6A, 0xB4, 0xE5, 0x23, 0xFC, 0x76, 0x5B, 0xBB, 0x31, 0x7D, 0x51, 0x76, 0xCE, 0xCA, 0x0D, 0x24, 0x74, 0x96, 0xA2, 0xF6, 0xAF, 0x30, 0x96, 0x28, 0x47, 0x52, 0xB2, 0xFF, 0x2C, 0x66, 0x74, 0xC0, 0x82, 0x23, 0x2C, 0xCC, 0x14, 0xBD, 0x85, 0x4A, 0xF9, 0x61, 0x8F, 0xE5, 0xF4, 0x2A, 0xAA, 0x7C, 0x75, 0xEA, 0xC6, 0x35, 0x6F, 0x10, 0x36, 0x36, 0x30}, IV: [16]byte{0x65, 0x5E, 0xCB, 0xC5, 0x9D, 0xED, 0xD6, 0x7B, 0x8D, 0x30, 0x95, 0xAC, 0x86, 0xAC, 0x5D, 0x77}},
{Ciphertext: []byte{0x49, 0xDC, 0x73, 0x9A, 0x26, 0x63, 0xD2, 0xBB, 0xC3, 0x6E, 0x6D, 0xCB, 0xEE, 0x48, 0xA6, 0x54, 0xB4, 0xF2, 0x82, 0x99, 0x79, 0x1E, 0xDA, 0x9E, 0x83, 0x19, 0xFA, 0x8D, 0x3B, 0x95, 0xC3, 0xDA, 0x4B, 0xA0, 0x71, 0x30, 0xC8, 0xA7, 0x00, 0x56, 0x71, 0xF0, 0x32, 0x32, 0x6E, 0x41, 0x01, 0xF6, 0xF8, 0xF0, 0xB3, 0xF4, 0x00, 0x62, 0x87, 0xAD, 0xCD, 0x75, 0x64, 0x04, 0x9A, 0xB7, 0x3F, 0x02, 0x2E, 0x4C, 0x14, 0x24, 0x53, 0x59, 0x8B, 0xBA, 0xA7, 0x4D, 0x44, 0xFE, 0xB4, 0x34, 0x99, 0x19, 0x13, 0x5D, 0xD0, 0xD7, 0x0B, 0xA9, 0xF7, 0xD0, 0x65, 0xD5, 0xC6, 0x99}, IV: [16]byte{0x49, 0xDC, 0x73, 0x9A, 0x26, 0x63, 0xD2, 0xBB, 0xC3, 0x6E, 0x6D, 0xCB, 0x99, 0x39, 0x48, 0x8D}}, {Ciphertext: []byte{0x7D, 0xF2, 0x37, 0xA2, 0xAC, 0x61, 0x56, 0xAF, 0xD3, 0x42, 0xB0, 0xFA, 0x54, 0x45, 0x88, 0x17, 0x19, 0x9D, 0x5A, 0x04, 0xA9, 0x97, 0xCF, 0x93, 0x64, 0x1F, 0x68, 0x18, 0xE2, 0xAB, 0x20, 0xEA, 0x7A, 0xE2, 0x29, 0x44, 0x97, 0x10, 0x70, 0x99, 0xA7, 0x91, 0x4C, 0x84, 0x9C, 0x4E, 0x42, 0xD4, 0xB1, 0x0E, 0x26, 0x6F, 0x33, 0xA8, 0xE8, 0x0D, 0x8E, 0xE0, 0x01, 0xBA, 0x38, 0x0D, 0x2B, 0x82, 0x29, 0x73, 0x70, 0x6D, 0xCD, 0xED, 0x7A, 0x8B, 0x47, 0x2F, 0x13, 0x7F, 0x09, 0xFD, 0x99, 0xB9, 0x1D, 0x90, 0x67, 0x80, 0xC2, 0x14, 0x58, 0xFD, 0x24, 0xB2, 0x16, 0xF0}, IV: [16]byte{0x7D, 0xF2, 0x37, 0xA2, 0xAC, 0x61, 0x56, 0xAF, 0xD3, 0x42, 0xB0, 0xFA, 0x54, 0x09, 0xD3, 0x75}},
{Ciphertext: []byte{0xFA, 0x46, 0xAF, 0x91, 0xDD, 0xF7, 0xCD, 0x4D, 0x25, 0x4A, 0xDA, 0x4C, 0xE2, 0x88, 0x5C, 0x04, 0xD2, 0xDC, 0x65, 0xE0, 0x7A, 0x19, 0x8A, 0x04, 0x7E, 0x42, 0xAC, 0xA6, 0x1E, 0x86, 0xE6, 0xA4, 0x51, 0xE2, 0x2A, 0x81, 0x0D, 0x36, 0xFA, 0x67, 0x74, 0x59, 0xFD, 0x29, 0xC3, 0x4A, 0x63, 0xF2, 0x5D, 0x2F, 0x48, 0xE6, 0x3A, 0x42, 0x92, 0xFE, 0x2A, 0xCD, 0xE1, 0x22, 0x2E, 0x80, 0x7A, 0x9B, 0x82, 0x83, 0x1A, 0x33, 0x19, 0x78, 0x13, 0x0E, 0xC2, 0x0A, 0x1B, 0x53, 0xF8, 0xCA, 0x64, 0x24, 0x37, 0xD5, 0x00, 0x16, 0x03, 0x69, 0x90, 0xFA, 0x92, 0x7B, 0x92, 0x55}, IV: [16]byte{0xFA, 0x46, 0xAF, 0x91, 0xDD, 0xF7, 0xCD, 0x4D, 0x25, 0x4A, 0xDA, 0x4C, 0x2A, 0x28, 0x86, 0xD4}}, {Ciphertext: []byte{0xB5, 0x67, 0x8D, 0x32, 0x9B, 0xCE, 0x74, 0xEB, 0xC3, 0xFF, 0xE3, 0xA8, 0x34, 0xE0, 0xBE, 0x5B, 0xB8, 0x72, 0x86, 0x58, 0xA5, 0x93, 0x15, 0x0E, 0x75, 0x0E, 0x78, 0x8A, 0x1E, 0x6A, 0xAB, 0x02, 0x25, 0xA6, 0x16, 0xF1, 0xFE, 0x84, 0x7F, 0x0B, 0xF7, 0xE1, 0xE9, 0xAB, 0xDD, 0x44, 0x1B, 0x39, 0x15, 0x4C, 0x98, 0x0F, 0xF5, 0x5D, 0x54, 0x50, 0x23, 0xC3, 0x2D, 0x0F, 0x39, 0x80, 0x48, 0xD1, 0x5C, 0x7B, 0xE5, 0x6D, 0x16, 0x5D, 0xA6, 0x24, 0x0D, 0x33, 0x5A, 0xFE, 0x75, 0x1A, 0x5F, 0x49, 0x06, 0x7C, 0x0E, 0xB2, 0xD5, 0x06, 0x44, 0xE0, 0x60, 0x0A, 0x3F, 0x77}, IV: [16]byte{0xB5, 0x67, 0x8D, 0x32, 0x9B, 0xCE, 0x74, 0xEB, 0xC3, 0xFF, 0xE3, 0xA8, 0x26, 0x0A, 0xB4, 0xF5}},
} }
var _encPool = strenc.NewPool(_masterSeed, _encEntries) var _encPool = strenc.NewPool(_masterSeed, _encEntries)
//go:noinline //go:noinline
@@ -57,24 +77,22 @@ var licenseKey = _decStr(4)
func main() { func main() {
fmt.Println(_decStr(5)) fmt.Println(_decStr(5))
if func() bool { _bciLLbB := int64(1); for i := 0; i < 10; i++ { _bciLLbB = _bciLLbB*7%49999999 }; return _bciLLbB == 1 }() { _ = struct{}{} }
fmt.Printf(_decStr(6), getVersion()) fmt.Printf(_decStr(6), getVersion())
if func() bool { return (867 & 867) == 867 }() { _ = struct{}{} }
if func() bool { _bcbGLgi := [4]byte{0x72, 0x6F, 0x6F, 0x74}; return len(_bcbGLgi) == 4 }() { _ = struct{}{} }
fmt.Printf(_decStr(7), getBuildID()) fmt.Printf(_decStr(7), getBuildID())
if func() bool { return func() bool { return (11134^11134) > 0 && (11134^11134) < 0 }() }() { println("unreachable") }
processRequest(_decStr(8)) processRequest(_decStr(8))
} }
func getVersion_obf2511() string { func getVersion_obf1861() string {
return _decStr(9) return _decStr(9)
} }
func getBuildID_obf7656() string { func getBuildID_obf7802() string {
return fmt.Sprintf(_decStr(10), time.Now().Unix()) return fmt.Sprintf(_decStr(10), time.Now().Unix())
} }
func processRequest_obf1301(userID string) { func processRequest_obf4807(userID string) {
fmt.Printf(_decStr(11), userID) fmt.Printf(_decStr(11), userID)
if userID == "" { if userID == "" {
@@ -94,13 +112,14 @@ func processRequest_obf1301(userID string) {
_ = jwtSecret _ = jwtSecret
} }
func generateToken_obf5646(userID string) string { func generateToken_obf1103(userID string) string {
h := sha256.Sum256([]byte(fmt.Sprintf(_decStr(15), userID, time.Now().UnixNano()))) h := sha256.Sum256([]byte(fmt.Sprintf(_decStr(15), userID, time.Now().UnixNano())))
{ _bcIcrhv := func() int { n := 0; for i := 1; i <= 100; i++ { n += i }; return n }(); _ = _bcIcrhv }
return fmt.Sprintf(_decStr(16), h[:8]) return fmt.Sprintf(_decStr(16), h[:8])
} }
//go:noinline //go:noinline
func validateLicense_obf9184(key string) bool { func validateLicense_obf1490(key string) bool {
_co := map[int]func([]int64) int64{ _co := map[int]func([]int64) int64{
0: func(_ []int64) int64 { return int64(len(key)) }, 0: func(_ []int64) int64 { return int64(len(key)) },
} }
@@ -109,7 +128,7 @@ func validateLicense_obf9184(key string) bool {
return _vm.Run() != 0 return _vm.Run() != 0
} }
func maskString_obf9182(s string) string { func maskString_obf3138(s string) string {
if len(s) <= 8 { if len(s) <= 8 {
return _decStr(17) return _decStr(17)
} }
BIN
View File
Binary file not shown.
+6 -2
View File
@@ -23,6 +23,8 @@ func main() {
seed := flag.Int64("seed", 0, "Build seed for polymorphic output (0 = use current timestamp)") seed := flag.Int64("seed", 0, "Build seed for polymorphic output (0 = use current timestamp)")
injectBuildID := flag.Bool("buildid", true, "Inject unique build ID constant") injectBuildID := flag.Bool("buildid", true, "Inject unique build ID constant")
virtualizeVM := flag.Bool("vm", true, "Virtualize simple functions into VM bytecode") virtualizeVM := flag.Bool("vm", true, "Virtualize simple functions into VM bytecode")
antiDisasm := flag.Bool("anti-disasm", true, "Inject anti-disassembly patterns")
junkStrings := flag.Bool("junk-strings", true, "Inject junk string constants")
flag.Parse() flag.Parse()
if *srcDir == "" || *dstDir == "" { if *srcDir == "" || *dstDir == "" {
@@ -58,16 +60,18 @@ func main() {
BuildSeed: *seed, BuildSeed: *seed,
InjectBuildID: *injectBuildID, InjectBuildID: *injectBuildID,
VirtualizeFunctions: *virtualizeVM, VirtualizeFunctions: *virtualizeVM,
AntiDisassembly: *antiDisasm,
JunkStrings: *junkStrings,
} }
t := transform.New(config) t := transform.New(config)
fmt.Printf("[transformer] src=%s dst=%s\n", absSrc, absDst) fmt.Printf("[transformer] src=%s dst=%s\n", absSrc, absDst)
fmt.Printf("[transformer] seed=%d buildid=%v\n", config.BuildSeed, config.InjectBuildID) fmt.Printf("[transformer] seed=%d buildid=%v\n", config.BuildSeed, config.InjectBuildID)
fmt.Printf("[transformer] strings=%v opaque=%v deadcode=%v bogus=%v flatten=%v vm=%v\n", fmt.Printf("[transformer] strings=%v opaque=%v deadcode=%v bogus=%v flatten=%v vm=%v antidisasm=%v junkstr=%v\n",
config.EncryptStrings, config.InjectOpaquePreds, config.EncryptStrings, config.InjectOpaquePreds,
config.InjectDeadCode, config.BogusControlFlow, config.FlattenControl, config.InjectDeadCode, config.BogusControlFlow, config.FlattenControl,
config.VirtualizeFunctions) config.VirtualizeFunctions, config.AntiDisassembly, config.JunkStrings)
start := time.Now() start := time.Now()
+102 -4
View File
@@ -34,6 +34,8 @@ type Config struct {
BuildSeed int64 BuildSeed int64
InjectBuildID bool InjectBuildID bool
VirtualizeFunctions bool VirtualizeFunctions bool
AntiDisassembly bool
JunkStrings bool
} }
func DefaultConfig() Config { func DefaultConfig() Config {
@@ -120,6 +122,14 @@ func (t *Transformer) TransformFile(srcPath, dstPath string) error {
result = t.virtualizeFunctions(result) result = t.virtualizeFunctions(result)
} }
if t.config.AntiDisassembly {
result = t.injectAntiDisassembly(result)
}
if t.config.JunkStrings {
result = t.injectJunkStrings(result)
}
if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
return fmt.Errorf("mkdir %s: %w", filepath.Dir(dstPath), err) return fmt.Errorf("mkdir %s: %w", filepath.Dir(dstPath), err)
} }
@@ -921,6 +931,7 @@ func (t *Transformer) indirectDispatch(src string) string {
lines := strings.Split(src, "\n") lines := strings.Split(src, "\n")
var result []string var result []string
var wrappers []string var wrappers []string
dispatchIdx := 0
for _, line := range lines { for _, line := range lines {
trimmed := strings.TrimSpace(line) trimmed := strings.TrimSpace(line)
@@ -981,13 +992,20 @@ func (t *Transformer) indirectDispatch(src string) string {
argNames := extractArgNames(argStr) argNames := extractArgNames(argStr)
callArgs := strings.Join(argNames, ", ") callArgs := strings.Join(argNames, ", ")
ptrVar := fmt.Sprintf("_fptr%d", dispatchIdx)
dispatchIdx++
if hasReturn { if hasReturn {
wrapperFunc := fmt.Sprintf("func %s%s %s { return %s(%s) }", ptrDecl := fmt.Sprintf("var %s = %s", ptrVar, funcName+obfSuffix)
funcName, params, returnType, funcName+obfSuffix, callArgs) wrappers = append(wrappers, ptrDecl)
wrapperFunc := fmt.Sprintf("//go:noinline\nfunc %s%s %s { return %s(%s) }",
funcName, params, returnType, ptrVar, callArgs)
wrappers = append(wrappers, wrapperFunc) wrappers = append(wrappers, wrapperFunc)
} else { } else {
wrapperFunc := fmt.Sprintf("func %s%s { %s(%s) }", ptrDecl := fmt.Sprintf("var %s = %s", ptrVar, funcName+obfSuffix)
funcName, params, funcName+obfSuffix, callArgs) wrappers = append(wrappers, ptrDecl)
wrapperFunc := fmt.Sprintf("//go:noinline\nfunc %s%s { %s(%s) }",
funcName, params, ptrVar, callArgs)
wrappers = append(wrappers, wrapperFunc) wrappers = append(wrappers, wrapperFunc)
} }
} }
@@ -1487,6 +1505,86 @@ func %s(%s int64) int64 {
}`, funcName, param, param, strings.Join(byteLits, ", ")) }`, funcName, param, param, strings.Join(byteLits, ", "))
} }
func (t *Transformer) injectAntiDisassembly(src string) string {
lines := strings.Split(src, "\n")
var result []string
inFuncBody := false
for _, line := range lines {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "func ") && strings.HasSuffix(trimmed, "{") {
inFuncBody = true
result = append(result, line)
continue
}
if inFuncBody && trimmed == "}" {
inFuncBody = false
result = append(result, line)
continue
}
if inFuncBody && strings.HasPrefix(line, "\t") && !strings.HasPrefix(line, "\t\t") && trimmed != "" {
if t.rng.Float64() < 0.15 {
junkVar := stringcrypt.RandomIdent("_ad", 4)
junkSize := t.rng.Intn(32) + 8
result = append(result, fmt.Sprintf("\tvar %s [%d]byte; _ = %s", junkVar, junkSize, junkVar))
}
}
result = append(result, line)
}
return strings.Join(result, "\n")
}
func (t *Transformer) injectJunkStrings(src string) string {
junkStrings := []string{
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789abcdef0123456789abcdef",
"/usr/lib/libSystem.B.dylib",
"/proc/self/maps",
"\\x00\\x00\\x00\\x00",
"HKEY_LOCAL_MACHINE\\SOFTWARE",
"C:\\Windows\\System32\\ntdll.dll",
"SELECT * FROM users WHERE id=?",
"Content-Type: application/json",
"Mozilla/5.0 (Windows NT 10.0)",
"-----BEGIN RSA PRIVATE KEY-----",
"192.168.1.1:8080",
"admin@localhost",
"Bearer eyJhbGciOiJIUzI1NiJ9",
"application/x-www-form-urlencoded",
}
numJunk := t.rng.Intn(6) + 4
var junkBlock strings.Builder
junkBlock.WriteString("\nvar _junkData = [...]string{\n")
for i := 0; i < numJunk; i++ {
idx := t.rng.Intn(len(junkStrings))
junkBlock.WriteString(fmt.Sprintf("\t%q,\n", junkStrings[idx]))
}
junkBlock.WriteString("}\n")
junkBlock.WriteString("var _ = _junkData\n")
insertAt := findImportBlockEnd(src)
if insertAt == -1 {
pkgIdx := strings.Index(src, "package ")
if pkgIdx != -1 {
lineEnd := strings.Index(src[pkgIdx:], "\n")
if lineEnd != -1 {
insertAt = pkgIdx + lineEnd + 1
}
}
}
if insertAt != -1 && insertAt < len(src) {
src = src[:insertAt] + junkBlock.String() + src[insertAt:]
}
return src
}
func (t *Transformer) ensureImport(src string, importPath string) string { func (t *Transformer) ensureImport(src string, importPath string) string {
importBlock := `import ("` + importPath + `")` importBlock := `import ("` + importPath + `")`
+6 -150
View File
@@ -1,20 +1,12 @@
package antidebug package antidebug
import (
"fmt"
"os"
"runtime"
"time"
)
func Check() error { func Check() error {
if runtime.GOOS == "linux" { if err := checkPtrace(); err != nil {
if err := checkPtrace(); err != nil { return err
return err }
}
if err := disableCoreDump(); err != nil { if err := disableCoreDump(); err != nil {
return err return err
}
} }
if err := checkTiming(); err != nil { if err := checkTiming(); err != nil {
@@ -35,139 +27,3 @@ func Check() error {
return nil return nil
} }
func checkPtrace() error {
self, err := os.ReadFile("/proc/self/status")
if err != nil {
return nil
}
data := string(self)
for i := 0; i < len(data)-11; i++ {
if data[i:i+11] == "TracerPid:\t" {
j := i + 11
for j < len(data) && data[j] >= '0' && data[j] <= '9' {
j++
}
pid := data[i+11 : j]
if pid != "0" {
return fmt.Errorf("antidebug: debugger detected (tracer pid=%s)", pid)
}
break
}
}
return nil
}
func disableCoreDump() error {
f, err := os.OpenFile("/proc/self/coredump_filter", os.O_WRONLY, 0)
if err != nil {
return nil
}
defer f.Close()
_, _ = f.WriteString("0")
return nil
}
func checkTiming() error {
start := time.Now()
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
elapsed := time.Since(start)
if elapsed > 200*time.Millisecond {
return fmt.Errorf("antidebug: timing anomaly detected (%v for 1M iterations)", elapsed)
}
_ = sum
return nil
}
func checkEnv() error {
suspiciousVars := []string{
"GODEBUG",
"DELVE_LISTENER",
"DEBUGINFOD_URL",
"RR_LOG_FILE",
"_JAVA_OPTIONS",
"LD_PRELOAD",
"DYLD_INSERT_LIBRARIES",
}
for _, v := range suspiciousVars {
if os.Getenv(v) != "" {
return fmt.Errorf("antidebug: suspicious env var %s=%s", v, os.Getenv(v))
}
}
return nil
}
func checkParentProcess() error {
if runtime.GOOS != "linux" {
return nil
}
ppid := os.Getppid()
if ppid <= 1 {
return nil
}
commPath := fmt.Sprintf("/proc/%d/comm", ppid)
comm, err := os.ReadFile(commPath)
if err != nil {
return nil
}
parent := string(comm)
debuggers := []string{
"gdb", "lldb", "strace", "ltrace", "ida", "ida64",
"radare2", "r2", "ghidra", "x64dbg", "ollydbg",
"delve", "debugserver",
}
for _, d := range debuggers {
if len(parent) >= len(d) && parent[:len(d)] == d {
return fmt.Errorf("antidebug: parent process is debugger: %s", parent)
}
}
return nil
}
func AntiAttach() {
if runtime.GOOS != "linux" {
return
}
go func() {
for {
time.Sleep(500 * time.Millisecond)
if err := checkPtrace(); err != nil {
os.Exit(66)
}
}
}()
}
func AntiDump() {
if runtime.GOOS != "linux" {
return
}
go func() {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for range ticker.C {
_ = disableCoreDump()
}
}()
}
func CheckHooks() error {
if err := checkFunctionPrologues(); err != nil {
return err
}
if err := scanForBreakpoints(); err != nil {
return err
}
return nil
}
+147
View File
@@ -0,0 +1,147 @@
//go:build darwin
package antidebug
import (
"fmt"
"os"
"syscall"
"time"
"unsafe"
)
const (
ctlKern = 1
kernProc = 14
kernProcPID = 1
pTraced = 0x00000800
ptDenyAttach = 31
)
func checkPtrace() error {
pid := os.Getpid()
var mib [4]int32
mib[0] = ctlKern
mib[1] = kernProc
mib[2] = kernProcPID
mib[3] = int32(pid)
bufSize := uintptr(64)
buf := make([]byte, bufSize)
_, _, errno := syscall.Syscall6(
uintptr(0x2000000+202),
uintptr(unsafe.Pointer(&mib[0])),
4,
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&bufSize)),
0,
0,
)
if errno != 0 {
return nil
}
if bufSize < 36 {
return nil
}
pFlag := uint32(buf[32]) | uint32(buf[33])<<8 | uint32(buf[34])<<16 | uint32(buf[35])<<24
if pFlag&pTraced != 0 {
return fmt.Errorf("antidebug: debugger detected via sysctl P_TRACED (pid=%d)", pid)
}
return nil
}
func denyPtraceAttach() {
pid := os.Getpid()
syscall.RawSyscall(
uintptr(syscall.SYS_PTRACE),
uintptr(ptDenyAttach),
uintptr(pid),
0,
)
}
func disableCoreDump() error {
return nil
}
func checkTiming() error {
start := time.Now()
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
elapsed := time.Since(start)
if elapsed > 200*time.Millisecond {
return fmt.Errorf("antidebug: timing anomaly detected (%v for 1M iterations)", elapsed)
}
_ = sum
return nil
}
func checkEnv() error {
suspiciousVars := []string{
"DYLD_INSERT_LIBRARIES",
"DYLD_FRAMEWORK_PATH",
"DYLD_LIBRARY_PATH",
"DYLD_FALLBACK_FRAMEWORK_PATH",
"DYLD_FALLBACK_LIBRARY_PATH",
"DYLD_ROOT_PATH",
"GODEBUG",
"DELVE_LISTENER",
"DEBUGINFOD_URL",
"RR_LOG_FILE",
"_JAVA_OPTIONS",
}
for _, v := range suspiciousVars {
if os.Getenv(v) != "" {
return fmt.Errorf("antidebug: suspicious env var %s=%s", v, os.Getenv(v))
}
}
return nil
}
func checkParentProcess() error {
return nil
}
func AntiAttach() {
go func() {
denyPtraceAttach()
for {
time.Sleep(500 * time.Millisecond)
if err := checkPtrace(); err != nil {
os.Exit(66)
}
}
}()
}
func AntiDump() {
go func() {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for range ticker.C {
_ = disableCoreDump()
}
}()
}
func CheckHooks() error {
if err := checkFunctionPrologues(); err != nil {
return err
}
if err := scanForBreakpoints(); err != nil {
return err
}
return nil
}
+106
View File
@@ -2,10 +2,116 @@
package antidebug package antidebug
import (
"fmt"
"os"
"reflect"
"runtime"
"unsafe"
)
func checkFunctionPrologues() error { func checkFunctionPrologues() error {
type target struct {
name string
addr uintptr
}
targets := []target{
{"os.Exit", reflect.ValueOf(os.Exit).Pointer()},
{"runtime.Goexit", reflect.ValueOf(runtime.Goexit).Pointer()},
}
for _, t := range targets {
if t.addr == 0 {
continue
}
prologue := readAddr(t.addr, 8)
if len(prologue) < 2 {
continue
}
if prologue[0] == 0xE9 {
return fmt.Errorf("antidebug: JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xEB {
return fmt.Errorf("antidebug: short JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xFF && prologue[1] == 0x25 {
return fmt.Errorf("antidebug: indirect JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xCC && prologue[1] == 0xCC {
return fmt.Errorf("antidebug: INT3 breakpoint at %s (0x%x)", t.name, t.addr)
}
if runtime.GOARCH == "arm64" {
instr := uint32(prologue[0]) | uint32(prologue[1])<<8 | uint32(prologue[2])<<16 | uint32(prologue[3])<<24
if instr&0xFC000000 == 0x14000000 {
return fmt.Errorf("antidebug: ARM64 B hook detected at %s (0x%x)", t.name, t.addr)
}
if instr&0xFFE0001F == 0xD61F0000 {
return fmt.Errorf("antidebug: ARM64 BR hook detected at %s (0x%x)", t.name, t.addr)
}
}
}
return nil return nil
} }
func scanForBreakpoints() error { func scanForBreakpoints() error {
type target struct {
name string
addr uintptr
}
targets := []target{
{"os.Exit", reflect.ValueOf(os.Exit).Pointer()},
{"runtime.Goexit", reflect.ValueOf(runtime.Goexit).Pointer()},
{"fmt.Printf", reflect.ValueOf(fmt.Printf).Pointer()},
{"os.ReadFile", reflect.ValueOf(os.ReadFile).Pointer()},
}
for _, t := range targets {
if t.addr == 0 {
continue
}
region := readAddr(t.addr, 64)
if len(region) < 8 {
continue
}
maxConsecutive := 0
consecutive := 0
for _, b := range region {
if b == 0xCC {
consecutive++
if consecutive > maxConsecutive {
maxConsecutive = consecutive
}
} else {
consecutive = 0
}
}
if maxConsecutive >= 4 {
return fmt.Errorf("antidebug: breakpoint cluster (%d consecutive INT3) near %s at 0x%x", maxConsecutive, t.name, t.addr)
}
}
return nil return nil
} }
func readAddr(addr uintptr, size int) []byte {
if size <= 0 || size > 4096 {
return nil
}
buf := make([]byte, size)
var src []byte
sh := (*reflect.SliceHeader)(unsafe.Pointer(&src))
sh.Data = addr
sh.Len = size
sh.Cap = size
copy(buf, src)
return buf
}
+116
View File
@@ -0,0 +1,116 @@
//go:build windows
package antidebug
import (
"fmt"
"os"
"reflect"
"runtime"
"syscall"
"unsafe"
)
var procReadProcessMemory = kernel32.NewProc("ReadProcessMemory")
func checkFunctionPrologues() error {
type target struct {
name string
addr uintptr
}
targets := []target{
{"os.Exit", reflect.ValueOf(os.Exit).Pointer()},
{"runtime.Goexit", reflect.ValueOf(runtime.Goexit).Pointer()},
}
currentProc, _ := syscall.GetCurrentProcess()
for _, t := range targets {
if t.addr == 0 {
continue
}
prologue := make([]byte, 8)
var bytesRead uintptr
ret, _, _ := procReadProcessMemory.Call(
uintptr(currentProc),
t.addr,
uintptr(unsafe.Pointer(&prologue[0])),
uintptr(len(prologue)),
uintptr(unsafe.Pointer(&bytesRead)),
)
if ret == 0 || bytesRead < 2 {
continue
}
if prologue[0] == 0xE9 {
return fmt.Errorf("antidebug: JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xEB {
return fmt.Errorf("antidebug: short JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xFF && prologue[1] == 0x25 {
return fmt.Errorf("antidebug: indirect JMP hook detected at %s (0x%x)", t.name, t.addr)
}
if prologue[0] == 0xCC && prologue[1] == 0xCC {
return fmt.Errorf("antidebug: INT3 breakpoint at %s (0x%x)", t.name, t.addr)
}
}
return nil
}
func scanForBreakpoints() error {
type target struct {
name string
addr uintptr
}
targets := []target{
{"os.Exit", reflect.ValueOf(os.Exit).Pointer()},
{"runtime.Goexit", reflect.ValueOf(runtime.Goexit).Pointer()},
{"fmt.Printf", reflect.ValueOf(fmt.Printf).Pointer()},
{"os.ReadFile", reflect.ValueOf(os.ReadFile).Pointer()},
}
currentProc, _ := syscall.GetCurrentProcess()
for _, t := range targets {
if t.addr == 0 {
continue
}
region := make([]byte, 64)
var bytesRead uintptr
ret, _, _ := procReadProcessMemory.Call(
uintptr(currentProc),
t.addr,
uintptr(unsafe.Pointer(&region[0])),
uintptr(len(region)),
uintptr(unsafe.Pointer(&bytesRead)),
)
if ret == 0 || bytesRead < 8 {
continue
}
maxConsecutive := 0
consecutive := 0
for _, b := range region[:bytesRead] {
if b == 0xCC {
consecutive++
if consecutive > maxConsecutive {
maxConsecutive = consecutive
}
} else {
consecutive = 0
}
}
if maxConsecutive >= 4 {
return fmt.Errorf("antidebug: breakpoint cluster (%d consecutive INT3) near %s at 0x%x", maxConsecutive, t.name, t.addr)
}
}
return nil
}
+135
View File
@@ -0,0 +1,135 @@
//go:build linux
package antidebug
import (
"fmt"
"os"
"runtime"
"time"
)
func checkPtrace() error {
self, err := os.ReadFile("/proc/self/status")
if err != nil {
return nil
}
data := string(self)
for i := 0; i < len(data)-11; i++ {
if data[i:i+11] == "TracerPid:\t" {
j := i + 11
for j < len(data) && data[j] >= '0' && data[j] <= '9' {
j++
}
pid := data[i+11 : j]
if pid != "0" {
return fmt.Errorf("antidebug: debugger detected (tracer pid=%s)", pid)
}
break
}
}
return nil
}
func disableCoreDump() error {
f, err := os.OpenFile("/proc/self/coredump_filter", os.O_WRONLY, 0)
if err != nil {
return nil
}
defer f.Close()
_, _ = f.WriteString("0")
return nil
}
func checkTiming() error {
start := time.Now()
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
elapsed := time.Since(start)
if elapsed > 200*time.Millisecond {
return fmt.Errorf("antidebug: timing anomaly detected (%v for 1M iterations)", elapsed)
}
_ = sum
return nil
}
func checkEnv() error {
suspiciousVars := []string{
"GODEBUG",
"DELVE_LISTENER",
"DEBUGINFOD_URL",
"RR_LOG_FILE",
"_JAVA_OPTIONS",
"LD_PRELOAD",
}
for _, v := range suspiciousVars {
if os.Getenv(v) != "" {
return fmt.Errorf("antidebug: suspicious env var %s=%s", v, os.Getenv(v))
}
}
return nil
}
func checkParentProcess() error {
ppid := os.Getppid()
if ppid <= 1 {
return nil
}
commPath := fmt.Sprintf("/proc/%d/comm", ppid)
comm, err := os.ReadFile(commPath)
if err != nil {
return nil
}
parent := string(comm)
debuggers := []string{
"gdb", "lldb", "strace", "ltrace", "ida", "ida64",
"radare2", "r2", "ghidra", "x64dbg", "ollydbg",
"delve", "debugserver",
}
for _, d := range debuggers {
if len(parent) >= len(d) && parent[:len(d)] == d {
return fmt.Errorf("antidebug: parent process is debugger: %s", parent)
}
}
return nil
}
func AntiAttach() {
go func() {
for {
time.Sleep(500 * time.Millisecond)
if err := checkPtrace(); err != nil {
os.Exit(66)
}
}
}()
}
func AntiDump() {
go func() {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for range ticker.C {
_ = disableCoreDump()
}
}()
}
func CheckHooks() error {
if err := checkFunctionPrologues(); err != nil {
return err
}
if err := scanForBreakpoints(); err != nil {
return err
}
return nil
}
+266
View File
@@ -0,0 +1,266 @@
//go:build windows
package antidebug
import (
"fmt"
"os"
"syscall"
"time"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
ntdll = syscall.NewLazyDLL("ntdll.dll")
procIsDebuggerPresent = kernel32.NewProc("IsDebuggerPresent")
procCheckRemoteDebugger = kernel32.NewProc("CheckRemoteDebuggerPresent")
procNtQueryInformationProc = ntdll.NewProc("NtQueryInformationProcess")
procNtSetInformationThread = ntdll.NewProc("NtSetInformationThread")
procOutputDebugStringW = kernel32.NewProc("OutputDebugStringW")
procSetUnhandledException = kernel32.NewProc("SetUnhandledExceptionFilter")
)
const (
processDebugPort = 7
processDebugObjectHandle = 0x1E
processDebugFlags = 0x1F
threadHideFromDebugger = 0x11
)
func checkPtrace() error {
ret, _, _ := procIsDebuggerPresent.Call()
if ret != 0 {
return fmt.Errorf("antidebug: IsDebuggerPresent returned true")
}
var isRemoteDebugged int32
currentProc, _ := syscall.GetCurrentProcess()
ret, _, _ = procCheckRemoteDebugger.Call(
uintptr(currentProc),
uintptr(unsafe.Pointer(&isRemoteDebugged)),
)
if ret != 0 && isRemoteDebugged != 0 {
return fmt.Errorf("antidebug: CheckRemoteDebuggerPresent detected debugger")
}
var port uint32
var returnLength uint32
ret, _, _ = procNtQueryInformationProc.Call(
uintptr(currentProc),
processDebugPort,
uintptr(unsafe.Pointer(&port)),
unsafe.Sizeof(port),
uintptr(unsafe.Pointer(&returnLength)),
)
if ret == 0 && port != 0 {
return fmt.Errorf("antidebug: NtQueryInformationProcess(ProcessDebugPort) detected debugger (port=%d)", port)
}
var debugHandle uintptr
ret, _, _ = procNtQueryInformationProc.Call(
uintptr(currentProc),
processDebugObjectHandle,
uintptr(unsafe.Pointer(&debugHandle)),
unsafe.Sizeof(debugHandle),
uintptr(unsafe.Pointer(&returnLength)),
)
if ret == 0 {
return fmt.Errorf("antidebug: NtQueryInformationProcess(ProcessDebugObjectHandle) detected debugger")
}
var debugFlags uint32
ret, _, _ = procNtQueryInformationProc.Call(
uintptr(currentProc),
processDebugFlags,
uintptr(unsafe.Pointer(&debugFlags)),
unsafe.Sizeof(debugFlags),
uintptr(unsafe.Pointer(&returnLength)),
)
if ret == 0 && debugFlags == 0 {
return fmt.Errorf("antidebug: NtQueryInformationProcess(ProcessDebugFlags) detected debugger")
}
return nil
}
func checkPEB() error {
var pebBase uintptr
var returnLength uint32
currentProc, _ := syscall.GetCurrentProcess()
type processBasicInfo struct {
Reserved1 uintptr
PebBaseAddress uintptr
Reserved2 [2]uintptr
UniqueProcessID uintptr
Reserved3 uintptr
}
var info processBasicInfo
ret, _, _ := procNtQueryInformationProc.Call(
uintptr(currentProc),
0,
uintptr(unsafe.Pointer(&info)),
unsafe.Sizeof(info),
uintptr(unsafe.Pointer(&returnLength)),
)
if ret != 0 {
return nil
}
pebBase = info.PebBaseAddress
if pebBase == 0 {
return nil
}
beingDebugged := *(*byte)(unsafe.Pointer(pebBase + 2))
if beingDebugged != 0 {
return fmt.Errorf("antidebug: PEB.BeingDebugged is set")
}
ntGlobalFlag := *(*uint32)(unsafe.Pointer(pebBase + 0xBC))
const FLG_HEAP_ENABLE_TAIL_CHECK = 0x10
const FLG_HEAP_ENABLE_FREE_CHECK = 0x20
const FLG_HEAP_VALIDATE_PARAMETERS = 0x40
debugFlags := FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS
if ntGlobalFlag&uint32(debugFlags) != 0 {
return fmt.Errorf("antidebug: PEB.NtGlobalFlag has debug flags (0x%x)", ntGlobalFlag)
}
return nil
}
func checkHardwareBreakpoints() error {
type context struct {
ContextFlags uint32
Dr0 uintptr
Dr1 uintptr
Dr2 uintptr
Dr3 uintptr
Dr6 uintptr
Dr7 uintptr
FloatSave [112]byte
SegGs uint32
SegFs uint32
SegEs uint32
SegDs uint32
Edi uintptr
Esi uintptr
Ebx uintptr
Edx uintptr
Ecx uintptr
Eax uintptr
Ebp uintptr
Eip uintptr
SegCs uint32
EFlags uint32
Esp uintptr
SegSs uint32
ExtendedRegisters [512]byte
}
threadHandle, _ := syscall.GetCurrentThread()
var ctx context
ctx.ContextFlags = 0x00100010
procGetThreadContext := kernel32.NewProc("GetThreadContext")
ret, _, _ := procGetThreadContext.Call(
uintptr(threadHandle),
uintptr(unsafe.Pointer(&ctx)),
)
if ret == 0 {
return nil
}
if ctx.Dr0 != 0 || ctx.Dr1 != 0 || ctx.Dr2 != 0 || ctx.Dr3 != 0 {
return fmt.Errorf("antidebug: hardware breakpoints detected (dr0=0x%x dr1=0x%x dr2=0x%x dr3=0x%x)",
ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3)
}
return nil
}
func hideFromDebugger() {
threadHandle, _ := syscall.GetCurrentThread()
procNtSetInformationThread.Call(
uintptr(threadHandle),
threadHideFromDebugger,
0,
0,
)
}
func disableCoreDump() error {
return nil
}
func checkTiming() error {
start := time.Now()
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
elapsed := time.Since(start)
if elapsed > 200*time.Millisecond {
return fmt.Errorf("antidebug: timing anomaly detected (%v for 1M iterations)", elapsed)
}
_ = sum
return nil
}
func checkEnv() error {
suspiciousVars := []string{
"GODEBUG",
"DELVE_LISTENER",
"DEBUGINFOD_URL",
"RR_LOG_FILE",
"_JAVA_OPTIONS",
}
for _, v := range suspiciousVars {
if os.Getenv(v) != "" {
return fmt.Errorf("antidebug: suspicious env var %s=%s", v, os.Getenv(v))
}
}
return nil
}
func checkParentProcess() error {
return nil
}
func AntiAttach() {
go func() {
hideFromDebugger()
for {
time.Sleep(500 * time.Millisecond)
if err := checkPtrace(); err != nil {
os.Exit(66)
}
}
}()
}
func AntiDump() {
go func() {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for range ticker.C {
_ = disableCoreDump()
}
}()
}
func CheckHooks() error {
if err := checkFunctionPrologues(); err != nil {
return err
}
if err := scanForBreakpoints(); err != nil {
return err
}
return nil
}
+22
View File
@@ -5,6 +5,7 @@ import (
"crypto/sha256" "crypto/sha256"
"debug/elf" "debug/elf"
"debug/macho" "debug/macho"
"debug/pe"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"os" "os"
@@ -97,6 +98,8 @@ func hashTextSection(path string) ([32]byte, error) {
return hashTextELF(path) return hashTextELF(path)
case "darwin": case "darwin":
return hashTextMacho(path) return hashTextMacho(path)
case "windows":
return hashTextPE(path)
default: default:
return hashWholeFile(path) return hashWholeFile(path)
} }
@@ -139,6 +142,25 @@ func hashTextMacho(path string) ([32]byte, error) {
return hashWholeFile(path) return hashWholeFile(path)
} }
func hashTextPE(path string) ([32]byte, error) {
f, err := pe.Open(path)
if err != nil {
return [32]byte{}, err
}
defer f.Close()
for _, section := range f.Sections {
if section.Name == ".text" {
data, err := section.Data()
if err != nil {
return [32]byte{}, err
}
return sha256.Sum256(data), nil
}
}
return hashWholeFile(path)
}
func hashWholeFile(path string) ([32]byte, error) { func hashWholeFile(path string) ([32]byte, error) {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
+98 -16
View File
@@ -1,39 +1,121 @@
//go:build darwin
package syscallobf package syscallobf
import "syscall" import (
"crypto/rand"
"syscall"
"unsafe"
)
var (
obfPtraceTrap ObfuscatedCall
obfGetpidTrap ObfuscatedCall
obfKillTrap ObfuscatedCall
obfOpenTrap ObfuscatedCall
obfCloseTrap ObfuscatedCall
obfReadTrap ObfuscatedCall
obfLseekTrap ObfuscatedCall
obfMmapTrap ObfuscatedCall
obfMprotectTrap ObfuscatedCall
)
func init() {
var key [4]byte
if _, err := rand.Read(key[:]); err != nil {
panic("syscallobf: failed to generate random key: " + err.Error())
}
obfPtraceTrap = encode(0x200001A, key)
obfGetpidTrap = encode(0x2000027, key)
obfKillTrap = encode(0x2000025, key)
obfOpenTrap = encode(0x2000005, key)
obfCloseTrap = encode(0x2000006, key)
obfReadTrap = encode(0x2000003, key)
obfLseekTrap = encode(0x20000C7, key)
obfMmapTrap = encode(0x20000C5, key)
obfMprotectTrap = encode(0x200004A, key)
}
func ObfPtrace(request int, pid uintptr, addr uintptr, data uintptr) (uintptr, uintptr, syscall.Errno) { func ObfPtrace(request int, pid uintptr, addr uintptr, data uintptr) (uintptr, uintptr, syscall.Errno) {
return 0, 0, syscall.ENOSYS trap := obfPtraceTrap.Num()
r1, r2, errno := syscall.RawSyscall6(trap, uintptr(request), pid, addr, data, 0, 0)
return r1, r2, errno
} }
func ObfGetpid() int { func ObfGetpid() int {
return 0 trap := obfGetpidTrap.Num()
r1, _, _ := syscall.RawSyscall(trap, 0, 0, 0)
return int(r1)
} }
func ObfKill(pid int, sig int) error { func ObfKill(pid int, sig int) error {
return syscall.ENOSYS trap := obfKillTrap.Num()
_, _, errno := syscall.RawSyscall(trap, uintptr(pid), uintptr(sig), 0)
if errno != 0 {
return errno
}
return nil
} }
func ObfOpen(path string, flags int, mode int) (int, error) { func ObfOpen(path string, flags int, mode int) (int, error) {
return -1, syscall.ENOSYS trap := obfOpenTrap.Num()
pathBytes, err := syscall.BytePtrFromString(path)
if err != nil {
return -1, err
}
r1, _, errno := syscall.RawSyscall(trap, uintptr(unsafe.Pointer(pathBytes)), uintptr(flags), uintptr(mode))
if errno != 0 {
return int(r1), errno
}
return int(r1), nil
} }
func ObfClose(fd int) error { func ObfClose(fd int) error {
return syscall.ENOSYS trap := obfCloseTrap.Num()
_, _, errno := syscall.RawSyscall(trap, uintptr(fd), 0, 0)
if errno != 0 {
return errno
}
return nil
} }
func ObfRead(fd int, buf []byte) (int, error) { func ObfRead(fd int, buf []byte) (int, error) {
return 0, syscall.ENOSYS trap := obfReadTrap.Num()
} var p *byte
if len(buf) > 0 {
func ObfMmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset uintptr) (uintptr, error) { p = &buf[0]
return 0, syscall.ENOSYS }
} r1, _, errno := syscall.RawSyscall(trap, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(len(buf)))
if errno != 0 {
func ObfMprotect(addr uintptr, length uintptr, prot int) error { return int(r1), errno
return syscall.ENOSYS }
return int(r1), nil
} }
func ObfLseek(fd int, offset int64, whence int) (int64, error) { func ObfLseek(fd int, offset int64, whence int) (int64, error) {
return 0, syscall.ENOSYS trap := obfLseekTrap.Num()
r1, _, errno := syscall.RawSyscall(trap, uintptr(fd), uintptr(offset), uintptr(whence))
if errno != 0 {
return int64(r1), errno
}
return int64(r1), nil
}
func ObfMmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset uintptr) (uintptr, error) {
trap := obfMmapTrap.Num()
r1, _, errno := syscall.Syscall6(trap, addr, length, uintptr(prot), uintptr(flags), uintptr(fd), offset)
if errno != 0 {
return 0, errno
}
return r1, nil
}
func ObfMprotect(addr uintptr, length uintptr, prot int) error {
trap := obfMprotectTrap.Num()
_, _, errno := syscall.RawSyscall(trap, addr, length, uintptr(prot))
if errno != 0 {
return errno
}
return nil
} }
+195
View File
@@ -0,0 +1,195 @@
//go:build windows
package syscallobf
import (
"crypto/rand"
"sync"
"syscall"
"unsafe"
)
var (
modntdll = syscall.NewLazyDLL("ntdll.dll")
procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
procNtSetInformationThread = modntdll.NewProc("NtSetInformationThread")
procNtClose = modntdll.NewProc("NtClose")
procNtProtectVirtualMemory = modntdll.NewProc("NtProtectVirtualMemory")
procNtReadVirtualMemory = modntdll.NewProc("NtReadVirtualMemory")
procNtOpenProcess = modntdll.NewProc("NtOpenProcess")
obfPtraceTrap ObfuscatedCall
obfGetpidTrap ObfuscatedCall
obfKillTrap ObfuscatedCall
obfOpenTrap ObfuscatedCall
obfCloseTrap ObfuscatedCall
obfReadTrap ObfuscatedCall
obfLseekTrap ObfuscatedCall
obfMmapTrap ObfuscatedCall
obfMprotectTrap ObfuscatedCall
)
func init() {
var key [4]byte
if _, err := rand.Read(key[:]); err != nil {
panic("syscallobf: failed to generate random key: " + err.Error())
}
obfCloseTrap = encode(0, key)
obfReadTrap = encode(0, key)
obfOpenTrap = encode(0, key)
obfLseekTrap = encode(0, key)
obfMmapTrap = encode(0, key)
obfMprotectTrap = encode(0, key)
obfPtraceTrap = encode(0, key)
obfGetpidTrap = encode(0, key)
obfKillTrap = encode(0, key)
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetCurrentPID = kernel32.NewProc("GetCurrentProcessId")
procOpenProcess = kernel32.NewProc("OpenProcess")
procCloseHandle = kernel32.NewProc("CloseHandle")
procReadProcessMem = kernel32.NewProc("ReadProcessMemory")
)
func ObfGetpid() int {
r1, _, _ := procGetCurrentPID.Call()
return int(r1)
}
func ObfOpen(path string, flags int, mode int) (int, error) {
p, err := syscall.UTF16PtrFromString(path)
if err != nil {
return -1, err
}
access := uint32(syscall.GENERIC_READ)
if flags&syscall.O_WRONLY != 0 {
access = syscall.GENERIC_WRITE
}
if flags&syscall.O_RDWR != 0 {
access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
}
creation := uint32(syscall.OPEN_EXISTING)
if flags&syscall.O_CREAT != 0 {
creation = syscall.CREATE_ALWAYS
}
h, _, err := syscall.CreateFile(p, access, syscall.FILE_SHARE_READ, nil, creation, syscall.FILE_ATTRIBUTE_NORMAL, 0)
if err != nil && err.(syscall.Errno) != 0 {
return -1, err
}
return int(h), nil
}
func ObfClose(fd int) error {
r1, _, err := procCloseHandle.Call(uintptr(fd))
if r1 == 0 {
return err
}
return nil
}
func ObfRead(fd int, buf []byte) (int, error) {
var bytesRead uint32
var p *byte
if len(buf) > 0 {
p = &buf[0]
}
r1, _, err := syscall.ReadFile(
syscall.Handle(fd),
buf,
&bytesRead,
nil,
)
if r1 == 0 {
return int(bytesRead), err
}
return int(bytesRead), nil
}
func ObfLseek(fd int, offset int64, whence int) (int64, error) {
var newOff int64
high := int32(offset >> 32)
r1, _, err := syscall.Seek(syscall.Handle(fd), int32(offset), high)
if r1 == 0xffffffff && err != nil {
return 0, err
}
_ = newOff
return int64(r1), nil
}
func ObfMmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset uintptr) (uintptr, error) {
flProtect := uint32(syscall.PAGE_READWRITE)
if prot&syscall.PROT_EXEC != 0 {
flProtect = syscall.PAGE_EXECUTE_READWRITE
}
h, _, err := syscall.CreateFileMapping(
syscall.Handle(fd),
nil,
flProtect,
uint32(length>>32),
uint32(length),
nil,
)
if h == 0 {
return 0, err
}
return uintptr(h), nil
}
func ObfMprotect(addr uintptr, length uintptr, prot int) error {
var oldProtect uint32
flProtect := uint32(syscall.PAGE_READWRITE)
if prot&syscall.PROT_EXEC != 0 {
flProtect = syscall.PAGE_EXECUTE_READWRITE
}
r1, _, err := procNtProtectVirtualMemory.Call(
uintptr(0xffffffffffffffff),
uintptr(unsafe.Pointer(&addr)),
uintptr(unsafe.Pointer(&length)),
uintptr(flProtect),
uintptr(unsafe.Pointer(&oldProtect)),
)
if r1 != 0 {
return err
}
return nil
}
type windowsObfCall struct {
once sync.Once
procAddr uintptr
proc *syscall.LazyProc
}
func (w *windowsObfCall) Call(args ...uintptr) (uintptr, uintptr, error) {
w.once.Do(func() {
if w.proc != nil {
w.procAddr = w.proc.Addr()
}
})
return syscall.Syscall(w.procAddr, uintptr(len(args)), args[0], args[1], args[2])
}
func NtQueryInformationProcess(handle uintptr, infoclass uint32, info uintptr, infolen uint32, retlen *uint32) uintptr {
r1, _, _ := procNtQueryInformationProcess.Call(
handle,
uintptr(infoclass),
info,
uintptr(infolen),
uintptr(unsafe.Pointer(retlen)),
)
return r1
}
func NtSetInformationThread(handle uintptr, infoclass uint32, info uintptr, infolen uint32) uintptr {
r1, _, _ := procNtSetInformationThread.Call(
handle,
uintptr(infoclass),
info,
uintptr(infolen),
)
return r1
}
+32
View File
@@ -1,7 +1,9 @@
package vm package vm
import ( import (
"crypto/rand"
"fmt" "fmt"
"math/big"
) )
type Instruction struct { type Instruction struct {
@@ -15,7 +17,15 @@ type LabelledInstr struct {
Target string Target string
} }
type CompileOpts struct {
NoJunk bool
}
func Compile(program []LabelledInstr) []byte { func Compile(program []LabelledInstr) []byte {
return CompileWith(program, CompileOpts{})
}
func CompileWith(program []LabelledInstr, opts CompileOpts) []byte {
labelAddrs := make(map[string]int) labelAddrs := make(map[string]int)
type fixup struct { type fixup struct {
@@ -26,11 +36,18 @@ func Compile(program []LabelledInstr) []byte {
var fixups []fixup var fixups []fixup
var bytecode []byte var bytecode []byte
junkOpcodes := []Opcode{opJunkA, opJunkB, opJunkC, opJunkD}
for _, entry := range program { for _, entry := range program {
if entry.Label != "" { if entry.Label != "" {
labelAddrs[entry.Label] = len(bytecode) labelAddrs[entry.Label] = len(bytecode)
} }
if !opts.NoJunk && shouldInsertJunk() {
junkOp := junkOpcodes[randIntn(len(junkOpcodes))]
bytecode = append(bytecode, encodeOp(junkOp))
}
instr := entry.Instr instr := entry.Instr
isJump := instr.Op == OpJmp || instr.Op == OpJz || instr.Op == OpJnz isJump := instr.Op == OpJmp || instr.Op == OpJz || instr.Op == OpJnz
@@ -64,3 +81,18 @@ func Compile(program []LabelledInstr) []byte {
return bytecode return bytecode
} }
func shouldInsertJunk() bool {
return randIntn(3) == 0
}
func randIntn(n int) int {
if n <= 0 {
return 0
}
b, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
if err != nil {
return 0
}
return int(b.Int64())
}
+27 -5
View File
@@ -430,7 +430,7 @@ func TestStepwiseExecution(t *testing.T) {
{Instr: Instruction{Op: OpHalt}}, {Instr: Instruction{Op: OpHalt}},
} }
code := Compile(program) code := CompileWith(program, CompileOpts{NoJunk: true})
vm := NewVM(code, nil) vm := NewVM(code, nil)
steps := 0 steps := 0
@@ -461,8 +461,13 @@ func TestXorObfuscationDeterminism(t *testing.T) {
{Instr: Instruction{Op: OpHalt}}, {Instr: Instruction{Op: OpHalt}},
} }
code1 := Compile(program) opts := CompileOpts{NoJunk: true}
code2 := Compile(program) code1 := CompileWith(program, opts)
code2 := CompileWith(program, opts)
if len(code1) != len(code2) {
t.Fatalf("bytecode length differs: %d vs %d", len(code1), len(code2))
}
for i := range code1 { for i := range code1 {
if code1[i] != code2[i] { if code1[i] != code2[i] {
@@ -487,9 +492,8 @@ func TestBytecodeIsXORed(t *testing.T) {
{Instr: Instruction{Op: OpHalt}}, {Instr: Instruction{Op: OpHalt}},
} }
code := Compile(program) code := CompileWith(program, CompileOpts{NoJunk: true})
// First byte should be OpPush ^ dispatchKey, not OpPush itself
rawPush := byte(OpPush) ^ dispatchKey rawPush := byte(OpPush) ^ dispatchKey
if code[0] != rawPush { if code[0] != rawPush {
t.Errorf("expected bytecode[0]=0x%02X (XOR'd PUSH), got 0x%02X", rawPush, code[0]) t.Errorf("expected bytecode[0]=0x%02X (XOR'd PUSH), got 0x%02X", rawPush, code[0])
@@ -501,6 +505,24 @@ func TestBytecodeIsXORed(t *testing.T) {
} }
} }
func TestJunkOpcodesCorrectness(t *testing.T) {
program := []LabelledInstr{
{Instr: Instruction{Op: OpPush, Args: []int64{10}}},
{Instr: Instruction{Op: OpPush, Args: []int64{20}}},
{Instr: Instruction{Op: OpAdd}},
{Instr: Instruction{Op: OpHalt}},
}
for i := 0; i < 50; i++ {
code := Compile(program)
vm := NewVM(code, nil)
result := vm.Run()
if result != 30 {
t.Fatalf("iteration %d: expected 30, got %d (bytecode len %d)", i, result, len(code))
}
}
}
func TestOrOp(t *testing.T) { func TestOrOp(t *testing.T) {
// 0x0F OR 0xF0 = 0xFF // 0x0F OR 0xF0 = 0xFF
program := []LabelledInstr{ program := []LabelledInstr{