mirror of
https://github.com/lukaszraczylo/go-obfuscation.git
synced 2026-10-11 05:27:42 +00:00
v0.0.2
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
build/
|
||||
*.exe
|
||||
@@ -54,9 +54,9 @@ make transformer
|
||||
|
||||
```
|
||||
Normal Obfuscated
|
||||
Size: 2707026 3063458
|
||||
Size: 2707026 3081170
|
||||
Symbols: 2864 58
|
||||
Strings: 15335 4302
|
||||
Strings: 15335 4264
|
||||
Secret leaks: 1 (LIC-*) 0
|
||||
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 |
|
||||
| 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
|
||||
|
||||
### 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`
|
||||
- **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.
|
||||
|
||||
@@ -268,12 +306,17 @@ The anti-debugging package uses these for stealthy `/proc/self/mem` and `/proc/s
|
||||
| Check | Platform | Description |
|
||||
|-------|----------|-------------|
|
||||
| `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` |
|
||||
| `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` |
|
||||
| `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) |
|
||||
| `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:**
|
||||
- `AntiAttach()` — polls `checkPtrace()` every 500ms, exits with code 66 on detection
|
||||
@@ -335,6 +378,8 @@ Flags:
|
||||
-flatten Control-flow flattening (default true)
|
||||
-vm Virtualize simple functions into VM bytecode (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)
|
||||
```
|
||||
|
||||
@@ -383,7 +428,7 @@ The `make compare` target verifies all of these are hidden in the obfuscated bin
|
||||
# Run all package tests
|
||||
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
|
||||
|
||||
# Syscall obfuscation tests
|
||||
@@ -402,6 +447,6 @@ go vet ./...
|
||||
## 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).
|
||||
- **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.
|
||||
- **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.
@@ -8,38 +8,58 @@ import (
|
||||
"os"
|
||||
"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
|
||||
|
||||
func getVersion() string { return getVersion_obf2511() }
|
||||
func getBuildID() string { return getBuildID_obf7656() }
|
||||
func processRequest(userID string) { processRequest_obf1301(userID) }
|
||||
func generateToken(userID string) string { return generateToken_obf5646(userID) }
|
||||
func validateLicense(key string) bool { return validateLicense_obf9184(key) }
|
||||
func maskString(s string) string { return maskString_obf9182(s) }
|
||||
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 _fptr0 = getVersion_obf1861
|
||||
//go:noinline
|
||||
func getVersion() string { return _fptr0() }
|
||||
var _fptr1 = getBuildID_obf7802
|
||||
//go:noinline
|
||||
func getBuildID() string { return _fptr1() }
|
||||
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{
|
||||
{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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{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)
|
||||
//go:noinline
|
||||
@@ -57,24 +77,22 @@ var licenseKey = _decStr(4)
|
||||
|
||||
func main() {
|
||||
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())
|
||||
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())
|
||||
|
||||
if func() bool { return func() bool { return (11134^11134) > 0 && (11134^11134) < 0 }() }() { println("unreachable") }
|
||||
processRequest(_decStr(8))
|
||||
}
|
||||
|
||||
func getVersion_obf2511() string {
|
||||
func getVersion_obf1861() string {
|
||||
return _decStr(9)
|
||||
}
|
||||
|
||||
func getBuildID_obf7656() string {
|
||||
func getBuildID_obf7802() string {
|
||||
return fmt.Sprintf(_decStr(10), time.Now().Unix())
|
||||
}
|
||||
|
||||
func processRequest_obf1301(userID string) {
|
||||
func processRequest_obf4807(userID string) {
|
||||
fmt.Printf(_decStr(11), userID)
|
||||
|
||||
if userID == "" {
|
||||
@@ -94,13 +112,14 @@ func processRequest_obf1301(userID string) {
|
||||
_ = 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())))
|
||||
{ _bcIcrhv := func() int { n := 0; for i := 1; i <= 100; i++ { n += i }; return n }(); _ = _bcIcrhv }
|
||||
return fmt.Sprintf(_decStr(16), h[:8])
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func validateLicense_obf9184(key string) bool {
|
||||
func validateLicense_obf1490(key string) bool {
|
||||
_co := map[int]func([]int64) int64{
|
||||
0: func(_ []int64) int64 { return int64(len(key)) },
|
||||
}
|
||||
@@ -109,7 +128,7 @@ func validateLicense_obf9184(key string) bool {
|
||||
return _vm.Run() != 0
|
||||
}
|
||||
|
||||
func maskString_obf9182(s string) string {
|
||||
func maskString_obf3138(s string) string {
|
||||
if len(s) <= 8 {
|
||||
return _decStr(17)
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -23,6 +23,8 @@ func main() {
|
||||
seed := flag.Int64("seed", 0, "Build seed for polymorphic output (0 = use current timestamp)")
|
||||
injectBuildID := flag.Bool("buildid", true, "Inject unique build ID constant")
|
||||
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()
|
||||
|
||||
if *srcDir == "" || *dstDir == "" {
|
||||
@@ -58,16 +60,18 @@ func main() {
|
||||
BuildSeed: *seed,
|
||||
InjectBuildID: *injectBuildID,
|
||||
VirtualizeFunctions: *virtualizeVM,
|
||||
AntiDisassembly: *antiDisasm,
|
||||
JunkStrings: *junkStrings,
|
||||
}
|
||||
|
||||
t := transform.New(config)
|
||||
|
||||
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] 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.InjectDeadCode, config.BogusControlFlow, config.FlattenControl,
|
||||
config.VirtualizeFunctions)
|
||||
config.VirtualizeFunctions, config.AntiDisassembly, config.JunkStrings)
|
||||
|
||||
start := time.Now()
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ type Config struct {
|
||||
BuildSeed int64
|
||||
InjectBuildID bool
|
||||
VirtualizeFunctions bool
|
||||
AntiDisassembly bool
|
||||
JunkStrings bool
|
||||
}
|
||||
|
||||
func DefaultConfig() Config {
|
||||
@@ -120,6 +122,14 @@ func (t *Transformer) TransformFile(srcPath, dstPath string) error {
|
||||
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 {
|
||||
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")
|
||||
var result []string
|
||||
var wrappers []string
|
||||
dispatchIdx := 0
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
@@ -981,13 +992,20 @@ func (t *Transformer) indirectDispatch(src string) string {
|
||||
argNames := extractArgNames(argStr)
|
||||
callArgs := strings.Join(argNames, ", ")
|
||||
|
||||
ptrVar := fmt.Sprintf("_fptr%d", dispatchIdx)
|
||||
dispatchIdx++
|
||||
|
||||
if hasReturn {
|
||||
wrapperFunc := fmt.Sprintf("func %s%s %s { return %s(%s) }",
|
||||
funcName, params, returnType, funcName+obfSuffix, callArgs)
|
||||
ptrDecl := fmt.Sprintf("var %s = %s", ptrVar, funcName+obfSuffix)
|
||||
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)
|
||||
} else {
|
||||
wrapperFunc := fmt.Sprintf("func %s%s { %s(%s) }",
|
||||
funcName, params, funcName+obfSuffix, callArgs)
|
||||
ptrDecl := fmt.Sprintf("var %s = %s", ptrVar, funcName+obfSuffix)
|
||||
wrappers = append(wrappers, ptrDecl)
|
||||
wrapperFunc := fmt.Sprintf("//go:noinline\nfunc %s%s { %s(%s) }",
|
||||
funcName, params, ptrVar, callArgs)
|
||||
wrappers = append(wrappers, wrapperFunc)
|
||||
}
|
||||
}
|
||||
@@ -1487,6 +1505,86 @@ func %s(%s int64) int64 {
|
||||
}`, 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 {
|
||||
importBlock := `import ("` + importPath + `")`
|
||||
|
||||
|
||||
+1
-145
@@ -1,21 +1,13 @@
|
||||
package antidebug
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Check() error {
|
||||
if runtime.GOOS == "linux" {
|
||||
if err := checkPtrace(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := disableCoreDump(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := checkTiming(); err != nil {
|
||||
return err
|
||||
@@ -35,139 +27,3 @@ func Check() error {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -2,10 +2,116 @@
|
||||
|
||||
package antidebug
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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(®ion[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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"debug/pe"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -97,6 +98,8 @@ func hashTextSection(path string) ([32]byte, error) {
|
||||
return hashTextELF(path)
|
||||
case "darwin":
|
||||
return hashTextMacho(path)
|
||||
case "windows":
|
||||
return hashTextPE(path)
|
||||
default:
|
||||
return hashWholeFile(path)
|
||||
}
|
||||
@@ -139,6 +142,25 @@ func hashTextMacho(path string) ([32]byte, error) {
|
||||
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) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,39 +1,121 @@
|
||||
//go:build darwin
|
||||
|
||||
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) {
|
||||
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 {
|
||||
return 0
|
||||
trap := obfGetpidTrap.Num()
|
||||
r1, _, _ := syscall.RawSyscall(trap, 0, 0, 0)
|
||||
return int(r1)
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
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) {
|
||||
return 0, syscall.ENOSYS
|
||||
trap := obfReadTrap.Num()
|
||||
var p *byte
|
||||
if len(buf) > 0 {
|
||||
p = &buf[0]
|
||||
}
|
||||
|
||||
func ObfMmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset uintptr) (uintptr, error) {
|
||||
return 0, syscall.ENOSYS
|
||||
r1, _, errno := syscall.RawSyscall(trap, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(len(buf)))
|
||||
if errno != 0 {
|
||||
return int(r1), errno
|
||||
}
|
||||
|
||||
func ObfMprotect(addr uintptr, length uintptr, prot int) error {
|
||||
return syscall.ENOSYS
|
||||
return int(r1), nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type Instruction struct {
|
||||
@@ -15,7 +17,15 @@ type LabelledInstr struct {
|
||||
Target string
|
||||
}
|
||||
|
||||
type CompileOpts struct {
|
||||
NoJunk bool
|
||||
}
|
||||
|
||||
func Compile(program []LabelledInstr) []byte {
|
||||
return CompileWith(program, CompileOpts{})
|
||||
}
|
||||
|
||||
func CompileWith(program []LabelledInstr, opts CompileOpts) []byte {
|
||||
labelAddrs := make(map[string]int)
|
||||
|
||||
type fixup struct {
|
||||
@@ -26,11 +36,18 @@ func Compile(program []LabelledInstr) []byte {
|
||||
var fixups []fixup
|
||||
var bytecode []byte
|
||||
|
||||
junkOpcodes := []Opcode{opJunkA, opJunkB, opJunkC, opJunkD}
|
||||
|
||||
for _, entry := range program {
|
||||
if entry.Label != "" {
|
||||
labelAddrs[entry.Label] = len(bytecode)
|
||||
}
|
||||
|
||||
if !opts.NoJunk && shouldInsertJunk() {
|
||||
junkOp := junkOpcodes[randIntn(len(junkOpcodes))]
|
||||
bytecode = append(bytecode, encodeOp(junkOp))
|
||||
}
|
||||
|
||||
instr := entry.Instr
|
||||
isJump := instr.Op == OpJmp || instr.Op == OpJz || instr.Op == OpJnz
|
||||
|
||||
@@ -64,3 +81,18 @@ func Compile(program []LabelledInstr) []byte {
|
||||
|
||||
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
@@ -430,7 +430,7 @@ func TestStepwiseExecution(t *testing.T) {
|
||||
{Instr: Instruction{Op: OpHalt}},
|
||||
}
|
||||
|
||||
code := Compile(program)
|
||||
code := CompileWith(program, CompileOpts{NoJunk: true})
|
||||
vm := NewVM(code, nil)
|
||||
|
||||
steps := 0
|
||||
@@ -461,8 +461,13 @@ func TestXorObfuscationDeterminism(t *testing.T) {
|
||||
{Instr: Instruction{Op: OpHalt}},
|
||||
}
|
||||
|
||||
code1 := Compile(program)
|
||||
code2 := Compile(program)
|
||||
opts := CompileOpts{NoJunk: true}
|
||||
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 {
|
||||
if code1[i] != code2[i] {
|
||||
@@ -487,9 +492,8 @@ func TestBytecodeIsXORed(t *testing.T) {
|
||||
{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
|
||||
if code[0] != rawPush {
|
||||
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) {
|
||||
// 0x0F OR 0xF0 = 0xFF
|
||||
program := []LabelledInstr{
|
||||
|
||||
Reference in New Issue
Block a user