Skip to content

Instantly share code, notes, and snippets.

@pboyd
Last active February 11, 2026 05:57
Show Gist options
  • Select an option

  • Save pboyd/1e1018de131e0f27a3bef1f377952c2e to your computer and use it in GitHub Desktop.

Select an option

Save pboyd/1e1018de131e0f27a3bef1f377952c2e to your computer and use it in GitHub Desktop.
Redefine a Go function
package main
import (
"encoding/binary"
"fmt"
"reflect"
"syscall"
"time"
"unsafe"
)
func myTimeNow() time.Time {
return time.Date(2026, 1, 30, 17, 0, 0, 0, time.FixedZone("Somewhere", -5))
}
func main() {
addr := reflect.ValueOf(time.Now).Pointer()
buf := unsafe.Slice((*byte)(unsafe.Pointer(addr)), 5)
mprotect(addr, len(buf), syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC)
buf[0] = 0xe9 // JMP
src := addr + 5 // Where to jump from
dest := reflect.ValueOf(myTimeNow).Pointer() // Where to jump to
binary.LittleEndian.PutUint32(buf[1:], uint32(int32(dest-src)))
mprotect(addr, len(buf), syscall.PROT_READ|syscall.PROT_EXEC)
fmt.Println(time.Now().Format(time.Kitchen))
}
func mprotect(addr uintptr, length int, flags int) error {
pageSize := syscall.Getpagesize()
// Round address down to page boundary.
pageStart := addr &^ (uintptr(syscall.Getpagesize()) - 1)
// Round up to cover complete pages.
regionSize := (int(addr-pageStart) + length + pageSize - 1) &^ (pageSize - 1)
region := unsafe.Slice((*byte)(unsafe.Pointer(pageStart)), regionSize)
return syscall.Mprotect(region, flags)
}
package main
import (
"encoding/binary"
"fmt"
"reflect"
"syscall"
"time"
"unsafe"
)
import "C"
func myTimeNow() time.Time {
return time.Date(2026, 1, 30, 17, 0, 0, 0, time.FixedZone("Somewhere", -5))
}
func main() {
addr := reflect.ValueOf(time.Now).Pointer()
buf := unsafe.Slice((*byte)(unsafe.Pointer(addr)), 4)
mprotect(addr, len(buf), syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC)
dest := reflect.ValueOf(myTimeNow).Pointer() // Where to jump to
offset := int32(dest - addr)
// Encode the instruction:
// -----------------------------------
// | 000101 | ... 26 bit address ... |
// -----------------------------------
inst := (5 << 26) | (uint32(offset>>2) & (1<<26 - 1))
binary.LittleEndian.PutUint32(buf, inst)
mprotect(addr, len(buf), syscall.PROT_READ|syscall.PROT_EXEC)
cacheflush(buf)
fmt.Println(time.Now().Format(time.Kitchen))
}
func mprotect(addr uintptr, length int, flags int) error {
pageSize := syscall.Getpagesize()
// Round address down to page boundary.
pageStart := addr &^ (uintptr(syscall.Getpagesize()) - 1)
// Round up to cover complete pages.
regionSize := (int(addr-pageStart) + length + pageSize - 1) &^ (pageSize - 1)
region := unsafe.Slice((*byte)(unsafe.Pointer(pageStart)), regionSize)
return syscall.Mprotect(region, flags)
}
func cacheflush(buf []byte) {
start := unsafe.Pointer(unsafe.SliceData(buf))
end := unsafe.Pointer(uintptr(len(buf)) + uintptr(start))
C.__builtin___clear_cache(start, end)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment