Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##qvm.go
- package qvm
- import (
- "os"
- "encoding/binary"
- "fmt"
- )
- const (
- VM_MAGIC_VER1 = 0x12721444
- VM_MAGIC_VER2 = 0x12721445
- )
- //QVMHeader represents the header for a QVMFile. Note that even if VM_MAGIC_VER1
- //QVMHeader still contains a JumpTableLength field.
- type QVMHeader struct {
- Magic uint32
- InstructionCount uint32
- CodeOffset uint32
- CodeLength uint32
- DataOffset uint32
- DataLength uint32
- LitLength uint32
- BssLength uint32
- JumpTableLength uint32
- }
- //Pretty simple, QVMFile has a header and the three sections normally embedded
- //in a QVM file.
- type QVMFile struct {
- Header QVMHeader
- Code []byte
- Data []byte
- Lit []byte
- }
- //Also simple. Takes an os.File and creates a QVMFile from it.
- //Also performs a few sanity check to save the programmer from
- //extra work and potentially malicious files.
- func NewQVMFile(file *os.File) (*QVMFile, os.Error) {
- //Read the header...
- theFile := &QVMFile{QVMHeader{}, nil, nil, nil}
- if err := binary.Read(file, binary.LittleEndian, &theFile.Header); err != nil {
- return nil, err
- }
- //Run a couple sanity checks on the header...
- //First case: Unrecognized magic number
- if theFile.Header.Magic != VM_MAGIC_VER1 && theFile.Header.Magic != VM_MAGIC_VER2 {
- return nil, os.NewError(fmt.Sprintf("Unrecognized QVM version[Magic: 0x%08x]", theFile.Header.Magic))
- }
- //Second case: Magic is VM_MAGIC_VER1 but CodeOffset != 32
- if theFile.Header.Magic == VM_MAGIC_VER1 && theFile.Header.CodeOffset != 32 {
- return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver1)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
- }
- //Third case: Magic is VM_MAGIC_VER2 but CodeOffset != 36
- if theFile.Header.Magic == VM_MAGIC_VER2 && theFile.Header.CodeOffset != 36 {
- return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver2)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
- }
- //Fourth case: CodeOffset + CodeLength + (CodeLength % 4) != DataOffset
- if theFile.Header.CodeOffset + theFile.Header.CodeLength + (theFile.Header.CodeLength % 4) != theFile.Header.DataOffset {
- return nil, os.NewError(fmt.Sprintf("Invalid data offset[0x%x] or code length[0x%x]", theFile.Header.DataOffset, theFile.Header.CodeLength))
- }
- //Read the Code/Data/Lit sections...
- theFile.Code = make([]byte, theFile.Header.CodeLength)
- if _, err := file.ReadAt(theFile.Code, int64(theFile.Header.CodeOffset)); err != nil {
- return nil, err
- }
- theFile.Data = make([]byte, theFile.Header.DataLength)
- if _, err := file.ReadAt(theFile.Data, int64(theFile.Header.DataOffset)); err != nil {
- return nil, err
- }
- theFile.Lit = make([]byte, theFile.Header.LitLength)
- if _, err := file.ReadAt(theFile.Lit, int64(theFile.Header.LitLength)); err != nil {
- return nil, err
- }
- return theFile, nil
- }
- ##QVMDisas.go
- package main
- import (
- "fmt"
- "flag"
- "os"
- "./qvm"
- )
- var OpcodeTable = [...]string {
- "UNDEF",
- "IGNORE",
- "BREAK",
- "ENTER",
- "LEAVE",
- "CALL",
- "PUSH",
- "POP",
- "CONST",
- "LOCAL",
- "JUMP",
- "EQ",
- "NE",
- "LTI",
- "LEI",
- "GTI",
- "GEI",
- "LTU",
- "LEU",
- "GTU",
- "GEU",
- "EQF",
- "NEF",
- "LTF",
- "LEF",
- "GTF",
- "GEF",
- "LOAD1",
- "LOAD2",
- "LOAD4",
- "STORE1",
- "STORE2",
- "STORE4",
- "ARG",
- "BLOCK_COPY",
- "SEX8",
- "SEX16",
- "NEGI",
- "ADD",
- "SUB",
- "DIVI",
- "DIVU",
- "MODI",
- "MODU",
- "MULI",
- "MULU",
- "BAND",
- "BOR",
- "BXOR",
- "BCOM",
- "LSH",
- "RSHI",
- "RSHU",
- "NEGF",
- "ADDF",
- "SUBF",
- "DIVF",
- "MULF",
- "CVIF",
- "CVFI"}
- var ArgTable = []byte {
- 0,
- 0,
- 0,
- 4,
- 4,
- 0,
- 0,
- 0,
- 4,
- 4,
- 0,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 4,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 4,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0}
- func printHeader(qvmFile *qvm.QVMFile) {
- version := "unknown"
- switch qvmFile.Header.Magic {
- case qvm.VM_MAGIC_VER1:
- version = "Ver1"
- case qvm.VM_MAGIC_VER2:
- version = "Ver2"
- }
- fmt.Printf("Magic: 0x%x[%s]\n", qvmFile.Header.Magic, version)
- fmt.Printf("Instruction Count: 0x%x\n", qvmFile.Header.InstructionCount)
- fmt.Printf("Code Offset: 0x%x\n", qvmFile.Header.CodeOffset)
- fmt.Printf("Code Length: 0x%x\n", qvmFile.Header.CodeLength)
- fmt.Printf("Data Offset: 0x%x\n", qvmFile.Header.DataOffset)
- fmt.Printf("Data Length: 0x%x\n", qvmFile.Header.DataLength)
- fmt.Printf("Lit Length: 0x%x\n", qvmFile.Header.LitLength)
- fmt.Printf("Bss Length: 0x%x\n", qvmFile.Header.BssLength)
- if qvmFile.Header.Magic == qvm.VM_MAGIC_VER2 {
- fmt.Printf("Jump Table Length: 0x%x\n", qvmFile.Header.JumpTableLength)
- }
- }
- func parseInstructions(qvmFile *qvm.QVMFile) {
- return
- }
- func parseProcedures(qvmFile *qvm.QVMFile) {
- return
- }
- func parseCodeXRefs(qvmFile *qvm.QVMFile) {
- return
- }
- func parseStrings(qvmFile *qvm.QVMFile) {
- return
- }
- func main() {
- var syscallsFile string
- var commentsFile string
- flag.StringVar(&syscallsFile, "s", "", "Specify a file defining the system calls for this QVM.")
- flag.StringVar(&commentsFile, "c", "", "Specify a file containing comments from a previous disassembly.")
- flag.Parse()
- if flag.NArg() != 1 {
- fmt.Println("Must specify one QVM!")
- }
- file, err := os.Open(flag.Arg(0), os.O_RDONLY, 0444)
- if err != nil {
- fmt.Println(err.String())
- os.Exit(-1)
- }
- qvmFile, err := qvm.NewQVMFile(file)
- printHeader(qvmFile)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement