mirror of
https://github.com/lukaszraczylo/go-obfuscation.git
synced 2026-10-12 05:32:33 +00:00
Bug fixes: - pclntab/rtcorrupt_linux.go: remove duplicate mprotectRW/mprotectRO that broke GOOS=linux builds (they're defined in rtcorrupt_unsafe.go for darwin+linux). - pclntab/pclntab.go: readUint now guards against negative offset (previously panicked via slice out-of-range). - integrity/integrity.go: SetExpectedHashHex now validates length 64 up-front and reports byte index on parse error; added ClearExpectedHash for runtime toggling and test isolation. - transform/mba.go: mbaApplyBinOp used strings.Index on first match instead of the current match; replaced with FindAllStringSubmatchIndex + two-pass replacement. - transform/transform.go: removed duplicate unconditional SplitLongStrings call. New transform passes (CLI flags + Config fields + pipeline wiring): - splice, constblind, mba, fakesigs, funcsplit, bbreorder — all default true. Cleanup: - strenc/keyderive.go: removed unused DeriveFromBinary + buildSeed. - transform/transform.go: removed unused trimFirstParen. - antidebug_hook_darwin.go: modernized readAddr to unsafe.Slice with noescape pattern (vet-safe). Tests (10 packages, 116 tests, all green): - internal/transform: 28 tests covering every pipeline stage. - pkg/strenc: 7 tests for key derivation + XOR stream. - pkg/stringcrypt: 7 tests for CFB round-trip + tamper detection. - pkg/pageman: 14 tests for alignment + mprotect guards. - pkg/integrity: 14 tests including ClearExpectedHash teardown. - pkg/pclntab: 12 tests including readUint negative-offset guard. - pkg/antisandbox: 6 tests for hostname/MAC lists + Check delegation. - pkg/antiemul: 6 tests (1 skipped on non-Linux) for no-panic + timing. Tooling: - Makefile: added test, verify, lint, fmt, vet targets. vet uses -unsafeptr=false (only legitimate uintptr→pointer is the darwin antidebug hook). fmt skips build/ (generated). - README.md: test coverage table + Makefile target reference.
133 lines
3.9 KiB
Go
133 lines
3.9 KiB
Go
package pclntab
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
func TestBytesEqual(t *testing.T) {
|
|
cases := []struct {
|
|
a, b []byte
|
|
want bool
|
|
}{
|
|
{nil, nil, true},
|
|
{[]byte{}, []byte{}, true},
|
|
{[]byte{1, 2, 3}, []byte{1, 2, 3}, true},
|
|
{[]byte{1, 2}, []byte{1, 2, 3}, false},
|
|
{[]byte{1, 2, 3}, []byte{1, 2}, false},
|
|
{[]byte{1, 2, 3}, []byte{1, 2, 4}, false},
|
|
}
|
|
for i, c := range cases {
|
|
if got := bytesEqual(c.a, c.b); got != c.want {
|
|
t.Errorf("case %d: bytesEqual(%v, %v) = %v, want %v", i, c.a, c.b, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReadUintBoundaries(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
data []byte
|
|
offset int
|
|
size int
|
|
want uint64
|
|
}{
|
|
{"32bit", []byte{0x78, 0x56, 0x34, 0x12}, 0, 4, 0x12345678},
|
|
{"64bit", []byte{0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12}, 0, 8, 0x1234567890abcdef},
|
|
{"out of range 4", []byte{0x01, 0x02}, 0, 4, 0},
|
|
{"out of range 8", []byte{0x01, 0x02}, 0, 8, 0},
|
|
{"unsupported size", []byte{0x01, 0x02, 0x03}, 0, 3, 0},
|
|
{"negative offset returns 0", []byte{0x01, 0x02, 0x03, 0x04}, -1, 4, 0},
|
|
{"offset past end", []byte{0x01, 0x02}, 100, 4, 0},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
if got := readUint(c.data, c.offset, c.size); got != c.want {
|
|
t.Errorf("readUint(%v, %d, %d) = %d, want %d", c.data, c.offset, c.size, got, c.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPclntabParserRejectsUnknownMagic(t *testing.T) {
|
|
tab := &pclntabParser{data: []byte{0x00, 0x00, 0x00, 0x00, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0}}
|
|
if err := tab.parse(); err == nil {
|
|
t.Error("expected error for unknown magic")
|
|
}
|
|
}
|
|
|
|
func TestPclntabParserRejectsShortData(t *testing.T) {
|
|
tab := &pclntabParser{data: []byte{0x01, 0x02, 0x03}}
|
|
if err := tab.parse(); err == nil {
|
|
t.Error("expected error for too-short data")
|
|
}
|
|
}
|
|
|
|
func TestPclntabParserValidGo118Magic(t *testing.T) {
|
|
tab := &pclntabParser{data: append([]byte{0xF1, 0xFF, 0xFF, 0xF1, 0x00, 0x00, 0x08, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, bytes.Repeat([]byte{0}, 16)...)}
|
|
if err := tab.parse(); err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if !tab.valid {
|
|
t.Error("parser should mark valid")
|
|
}
|
|
if tab.ptrSize != 8 {
|
|
t.Errorf("ptrSize = %d, want 8", tab.ptrSize)
|
|
}
|
|
if tab.quantum != 1 {
|
|
t.Errorf("quantum = %d, want 1", tab.quantum)
|
|
}
|
|
}
|
|
|
|
func TestPclntabParserNormalizesZeroPtrSize(t *testing.T) {
|
|
tab := &pclntabParser{data: append([]byte{0xF1, 0xFF, 0xFF, 0xF1, 0x00, 0x00, 0x00, 0x01}, bytes.Repeat([]byte{0}, 16)...)}
|
|
if err := tab.parse(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if tab.ptrSize != 8 {
|
|
t.Errorf("ptrSize should default to 8, got %d", tab.ptrSize)
|
|
}
|
|
}
|
|
|
|
func TestPclntabParserNormalizesInvalidPtrSize(t *testing.T) {
|
|
tab := &pclntabParser{data: append([]byte{0xF1, 0xFF, 0xFF, 0xF1, 0x00, 0x00, 0x06, 0x01}, bytes.Repeat([]byte{0}, 16)...)}
|
|
if err := tab.parse(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if tab.ptrSize != 8 {
|
|
t.Errorf("ptrSize should default to 8, got %d", tab.ptrSize)
|
|
}
|
|
}
|
|
|
|
func TestScrambleMagicChangesHeader(t *testing.T) {
|
|
original := []byte{0xF1, 0xFF, 0xFF, 0xF1, 0x00, 0x00, 0x08, 0x01}
|
|
data := append([]byte{}, original...)
|
|
scrambleMagic(data)
|
|
if bytes.Equal(data[:4], original[:4]) {
|
|
t.Error("scrambleMagic did not change the first 4 bytes")
|
|
}
|
|
// Tail must be preserved
|
|
if !bytes.Equal(data[4:], original[4:]) {
|
|
t.Error("scrambleMagic modified bytes past the magic header")
|
|
}
|
|
}
|
|
|
|
func TestScrambleMagicNoOpOnShortData(t *testing.T) {
|
|
// No panic on short input.
|
|
scrambleMagic([]byte{0x01, 0x02})
|
|
scrambleMagic(nil)
|
|
}
|
|
|
|
func TestCorruptPclntabRejectsMissingSection(t *testing.T) {
|
|
if _, err := CorruptPclntab("/nonexistent", CorruptOptions{}); err == nil {
|
|
t.Error("expected error for nonexistent binary")
|
|
}
|
|
}
|
|
|
|
func TestEncryptNamesRequiresValidTab(t *testing.T) {
|
|
tab := &pclntabParser{data: []byte{0x00, 0x01, 0x02, 0x03}}
|
|
if err := encryptNames(tab, 0x42); err == nil {
|
|
t.Error("expected error for invalid pclntab")
|
|
}
|
|
}
|