mirror of
https://github.com/lukaszraczylo/go-obfuscation.git
synced 2026-10-15 05:58:22 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Opcode byte
|
||||
|
||||
const (
|
||||
OpNop Opcode = 0x00
|
||||
OpPush Opcode = 0x01
|
||||
OpPop Opcode = 0x02
|
||||
OpDup Opcode = 0x03
|
||||
OpAdd Opcode = 0x04
|
||||
OpSub Opcode = 0x05
|
||||
OpMul Opcode = 0x06
|
||||
OpDiv Opcode = 0x07
|
||||
OpMod Opcode = 0x08
|
||||
OpXor Opcode = 0x09
|
||||
OpAnd Opcode = 0x0A
|
||||
OpOr Opcode = 0x0B
|
||||
OpNot Opcode = 0x0C
|
||||
OpShl Opcode = 0x0D
|
||||
OpShr Opcode = 0x0E
|
||||
OpCmpEq Opcode = 0x0F
|
||||
OpCmpLt Opcode = 0x10
|
||||
OpCmpGt Opcode = 0x11
|
||||
OpJmp Opcode = 0x12
|
||||
OpJz Opcode = 0x13
|
||||
OpJnz Opcode = 0x14
|
||||
OpLoad Opcode = 0x15
|
||||
OpStore Opcode = 0x16
|
||||
OpCall Opcode = 0x17
|
||||
OpRet Opcode = 0x18
|
||||
OpHalt Opcode = 0x19
|
||||
OpSwap Opcode = 0x1A
|
||||
OpRot Opcode = 0x1B
|
||||
opJunkA Opcode = 0x1C
|
||||
opJunkB Opcode = 0x1D
|
||||
opJunkC Opcode = 0x1E
|
||||
opJunkD Opcode = 0x1F
|
||||
)
|
||||
|
||||
const dispatchKey byte = 0xA5
|
||||
|
||||
var opcodeNames = map[Opcode]string{
|
||||
OpNop: "NOP", OpPush: "PUSH", OpPop: "POP", OpDup: "DUP",
|
||||
OpAdd: "ADD", OpSub: "SUB", OpMul: "MUL", OpDiv: "DIV",
|
||||
OpMod: "MOD", OpXor: "XOR", OpAnd: "AND", OpOr: "OR",
|
||||
OpNot: "NOT", OpShl: "SHL", OpShr: "SHR", OpCmpEq: "CMP_EQ",
|
||||
OpCmpLt: "CMP_LT", OpCmpGt: "CMP_GT", OpJmp: "JMP", OpJz: "JZ",
|
||||
OpJnz: "JNZ", OpLoad: "LOAD", OpStore: "STORE", OpCall: "CALL",
|
||||
OpRet: "RET", OpHalt: "HALT", OpSwap: "SWAP", OpRot: "ROT",
|
||||
}
|
||||
|
||||
func (o Opcode) String() string {
|
||||
if name, ok := opcodeNames[o]; ok {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf("UNK(0x%02X)", byte(o))
|
||||
}
|
||||
|
||||
func encodeOp(op Opcode) byte {
|
||||
return byte(op) ^ dispatchKey
|
||||
}
|
||||
|
||||
func decodeOp(b byte) Opcode {
|
||||
return Opcode(b ^ dispatchKey)
|
||||
}
|
||||
|
||||
type argEncoding int
|
||||
|
||||
const (
|
||||
argNone argEncoding = iota
|
||||
argI8
|
||||
argI16
|
||||
argI32
|
||||
argI64
|
||||
)
|
||||
|
||||
func opArgEnc(op Opcode) argEncoding {
|
||||
switch op {
|
||||
case OpPush:
|
||||
return argI64
|
||||
case OpShl, OpShr, OpSwap:
|
||||
return argI8
|
||||
case OpJmp, OpJz, OpJnz:
|
||||
return argI32
|
||||
case OpLoad, OpStore, OpCall:
|
||||
return argI16
|
||||
default:
|
||||
return argNone
|
||||
}
|
||||
}
|
||||
|
||||
func InstrSize(op Opcode) int {
|
||||
switch opArgEnc(op) {
|
||||
case argI64:
|
||||
return 9
|
||||
case argI32:
|
||||
return 5
|
||||
case argI16:
|
||||
return 3
|
||||
case argI8:
|
||||
return 2
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func EncodeInstr(op Opcode, arg int64) []byte {
|
||||
size := InstrSize(op)
|
||||
buf := make([]byte, size)
|
||||
buf[0] = encodeOp(op)
|
||||
|
||||
switch opArgEnc(op) {
|
||||
case argI64:
|
||||
binary.LittleEndian.PutUint64(buf[1:], uint64(arg))
|
||||
case argI32:
|
||||
binary.LittleEndian.PutUint32(buf[1:], uint32(arg))
|
||||
case argI16:
|
||||
binary.LittleEndian.PutUint16(buf[1:], uint16(arg))
|
||||
case argI8:
|
||||
buf[1] = byte(arg)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func DecodeInstr(code []byte, pc int) (Opcode, int64, int) {
|
||||
op := decodeOp(code[pc])
|
||||
size := InstrSize(op)
|
||||
|
||||
var arg int64
|
||||
switch opArgEnc(op) {
|
||||
case argI64:
|
||||
arg = int64(binary.LittleEndian.Uint64(code[pc+1 : pc+9]))
|
||||
case argI32:
|
||||
arg = int64(binary.LittleEndian.Uint32(code[pc+1 : pc+5]))
|
||||
case argI16:
|
||||
arg = int64(binary.LittleEndian.Uint16(code[pc+1 : pc+3]))
|
||||
case argI8:
|
||||
arg = int64(code[pc+1])
|
||||
}
|
||||
return op, arg, size
|
||||
}
|
||||
Reference in New Issue
Block a user