Skip to content

Instantly share code, notes, and snippets.

@stevenjohnstone
Last active January 28, 2020 13:33
Show Gist options
  • Save stevenjohnstone/cbf145560e94b56c0d09ae1aeb24ceb2 to your computer and use it in GitHub Desktop.
Save stevenjohnstone/cbf145560e94b56c0d09ae1aeb24ceb2 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
// a branch of keystone golang bindings which builds on linux
"github.com/stevenjohnstone/keystone/bindings/go/keystone"
uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)
// This program explores a few inputs to
// problem 0x03 of xchg rax,rax:
// https://www.xorpd.net/pages/xchg_rax/snip_03.html
//
// This is a good excuse to give keystone and unicorn
// a spin in golang
func main() {
// first, convert the assembly language into numerical opcodes
// (machine language)
assembly := "sub rdx,rax; sbb rcx,rcx; and rcx,rdx; add rax,rcx"
ks, err := keystone.New(keystone.ARCH_X86, keystone.MODE_64)
if err != nil {
panic(err)
}
defer ks.Close()
err = ks.Option(keystone.OPT_SYNTAX, keystone.OPT_SYNTAX_INTEL)
if err != nil {
panic(err)
}
insn, _, ok := ks.Assemble(assembly, 0)
if !ok {
panic("failed to assemble")
}
// choose some initial values for rax and rdx
// to get a feel for what the algorithm does
regPairs := []struct {
rax, rdx uint64
}{
{0x0, 0x1},
{0x1, 0x1},
{0xf, 0xe},
{0xe, 0xf},
{0xffffffff, 0x00},
}
// try each pair of initial register values with the emulator
for i, regPair := range regPairs {
mu, _ := uc.NewUnicorn(uc.ARCH_X86, uc.MODE_64)
mu.MemMap(0x1000, 0x1000)
mu.MemWrite(0x1000, insn)
mu.RegWrite(uc.X86_REG_RAX, regPair.rax)
mu.RegWrite(uc.X86_REG_RDX, regPair.rdx)
if err := mu.Start(0x1000, 0x1000+uint64(len(insn))); err != nil {
panic(err)
}
endRax, _ := mu.RegRead(uc.X86_REG_RAX)
fmt.Printf("%d (rax: %016x rdx %016x) -> rax: %016x\n", i, regPair.rax, regPair.rdx, endRax)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment