Commit 50417b03 authored by protolambda's avatar protolambda

mipsevm: syscall unicorn hook, state mem reader util func

parent b4614d9e
......@@ -2,13 +2,11 @@ package main
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/fatih/color"
uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)
......@@ -80,51 +78,7 @@ func GetHookedUnicorn(root string, ram map[uint32](uint32), callback func(int, u
log.Fatal("invalid interrupt ", intno, " at step ", steps)
}
syscall_no, _ := mu.RegRead(uc.MIPS_REG_V0)
v0 := uint64(0)
if syscall_no == 4020 {
oracle_hash, _ := mu.MemRead(0x30001000, 0x20)
hash := common.BytesToHash(oracle_hash)
key := fmt.Sprintf("%s/%s", root, hash)
value, err := ioutil.ReadFile(key)
check(err)
tmp := []byte{0, 0, 0, 0}
binary.BigEndian.PutUint32(tmp, uint32(len(value)))
mu.MemWrite(0x31000000, tmp)
mu.MemWrite(0x31000004, value)
WriteRam(ram, 0x31000000, uint32(len(value)))
value = append(value, 0, 0, 0)
for i := uint32(0); i < ram[0x31000000]; i += 4 {
WriteRam(ram, 0x31000004+i, binary.BigEndian.Uint32(value[i:i+4]))
}
} else if syscall_no == 4004 {
fd, _ := mu.RegRead(uc.MIPS_REG_A0)
buf, _ := mu.RegRead(uc.MIPS_REG_A1)
count, _ := mu.RegRead(uc.MIPS_REG_A2)
bytes, _ := mu.MemRead(buf, count)
WriteBytes(int(fd), bytes)
} else if syscall_no == 4090 {
a0, _ := mu.RegRead(uc.MIPS_REG_A0)
sz, _ := mu.RegRead(uc.MIPS_REG_A1)
if a0 == 0 {
v0 = 0x20000000 + heap_start
heap_start += sz
} else {
v0 = a0
}
} else if syscall_no == 4045 {
v0 = 0x40000000
} else if syscall_no == 4120 {
v0 = 1
} else if syscall_no == 4246 {
// exit group
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0000)
} else {
//fmt.Println("syscall", syscall_no)
}
mu.RegWrite(uc.MIPS_REG_V0, v0)
mu.RegWrite(uc.MIPS_REG_A3, 0)
}, 0, 0)
if callback != nil {
......
......@@ -3,6 +3,7 @@ package main
import (
"encoding/hex"
"fmt"
"io"
)
const (
......@@ -73,6 +74,43 @@ func (s *State) SetMemory(addr uint32, v uint32, size uint32) {
}
}
type memReader struct {
state *State
addr uint32
count uint32
}
func (r *memReader) Read(dest []byte) (n int, err error) {
if r.count == 0 {
return 0, io.EOF
}
// Keep iterating over memory until we have all our data.
// It may wrap around the address range, and may not be aligned
endAddr := r.addr + r.count
pageIndex := r.addr >> pageAddrSize
start := r.addr & pageAddrMask
end := uint32(pageSize)
if pageIndex == (endAddr >> pageAddrSize) {
end = endAddr & pageAddrMask
}
p, ok := r.state.Memory[pageIndex]
if ok {
n = copy(dest, p[start:end])
} else {
n = copy(dest, make([]byte, end-start)) // default to zeroes
}
r.addr += uint32(n)
r.count -= uint32(n)
return n, nil
}
func (s *State) ReadMemory(addr uint32, count uint32) io.Reader {
return &memReader{state: s, addr: addr, count: count}
}
// TODO merkleization
// TODO convert access-list to calldata and state-sets for EVM
......@@ -2,6 +2,7 @@ package main
import (
"fmt"
"io"
"log"
uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
......@@ -17,16 +18,44 @@ func LoadUnicorn(st *State, mu uc.Unicorn) error {
return nil
}
func HookUnicorn(st *State, mu uc.Unicorn) error {
func HookUnicorn(st *State, mu uc.Unicorn, stdOut, stdErr io.Writer) error {
_, err := mu.HookAdd(uc.HOOK_INTR, func(mu uc.Unicorn, intno uint32) {
if intno != 17 {
log.Fatal("invalid interrupt ", intno, " at step ", steps)
}
syscallNum, _ := mu.RegRead(uc.MIPS_REG_V0)
// TODO process syscalls
v0 := uint64(0)
switch syscallNum {
// TODO mmap
case 4004: // write
fd, _ := mu.RegRead(uc.MIPS_REG_A0)
addr, _ := mu.RegRead(uc.MIPS_REG_A1)
count, _ := mu.RegRead(uc.MIPS_REG_A2)
switch fd {
case 1:
_, _ = io.Copy(stdOut, st.ReadMemory(uint32(addr), uint32(count)))
case 2:
_, _ = io.Copy(stdErr, st.ReadMemory(uint32(addr), uint32(count)))
default:
// ignore other output data
}
case 4090: // mmap
a0, _ := mu.RegRead(uc.MIPS_REG_A0)
sz, _ := mu.RegRead(uc.MIPS_REG_A1)
if a0 == 0 {
v0 = 0x20000000 + heap_start
st.Heap += uint32(sz)
} else {
v0 = a0
}
// TODO mmap
case 4045: // brk
v0 = 0x40000000
case 4246: // exit_group
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0000)
}
mu.RegWrite(uc.MIPS_REG_V0, v0)
mu.RegWrite(uc.MIPS_REG_A3, 0)
}, 0, 0)
if err != nil {
return fmt.Errorf("failed to set up interrupt/syscall hook: %w", err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment