commit 1a12678441858defa08a34ba6bd5331be0f8c445 Author: serr Date: Sun Apr 13 22:59:50 2025 +0300 new diff --git a/main.go b/main.go new file mode 100644 index 0000000..4c33f87 --- /dev/null +++ b/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "syscall" + "unsafe" +) + +func main() { + s := "hello" + fmt.Println("Original:", s) + + // Строки в Go - структуры с двумя полями: указатель на данные и длина + // тут строка интерпретируется как структура + strHeader := (*struct { + data unsafe.Pointer + len int + })(unsafe.Pointer(&s)) + + // Вычисляем начало страницы памяти + pageSize := syscall.Getpagesize() + pageStart := uintptr(strHeader.data) - (uintptr(strHeader.data) % uintptr(pageSize)) + fmt.Printf( + "\nАдрес строки = %d\nразмер страницы памяти = %d\nадрес строки относительно начала страницы = %d\nадрес страницы = %d\n\n", + uintptr(strHeader.data), + uintptr(pageSize), + (uintptr(strHeader.data) % uintptr(pageSize)), + pageStart) + + // Имея адрес страницы и ее размер даю права на запись на данной странице памяти + ret, _, err := syscall.Syscall( + syscall.SYS_MPROTECT, + pageStart, + uintptr(pageSize), + uintptr(syscall.PROT_READ|syscall.PROT_WRITE), + ) + if ret != 0 { + panic("mprotect failed: " + err.Error()) + } + + // Теперь можно менять строку + // поменяю, например, пятый байт + fifthBytePtr := (*byte)(unsafe.Pointer(uintptr(strHeader.data) + 4)) + *fifthBytePtr = 0 + + // Восстанавливаю дефолтные права + ret, _, err = syscall.Syscall( + syscall.SYS_MPROTECT, + pageStart, + uintptr(pageSize), + uintptr(syscall.PROT_READ), + ) + if ret != 0 { + panic("mprotect restore failed: " + err.Error()) + } + + fmt.Println("Modified:", s) // Должно быть "Xello" +}