// pe_multitool tours the static-analysis side of winpwn: checksec, section
// entropy, IAT/EAT navigation with forwarder resolution, and the native ROP
// gadget scanner. Run from: workspace/demos/pe_multitool -> go run .
package main

import (
	"fmt"
	"log"
	"winpwn"
)
const target = "../../../../Users/lee/Desktop/win_sems/Seminar/2019_Winter_WinPwn/200108/Lab2/simple_rop.exe"
//const target = "../../../../Windows/System32/kernel32.dll"

func main() {
	pe, err := winpwn.OpenPE(target)
	if err != nil {
		log.Fatalf("OpenPE: %v", err)
	}
	defer pe.Close()

	is64, _ := pe.Is64Bit()
	base, _ := pe.ImageBase()
	entry, _ := pe.EntryPoint()
	fmt.Printf("=== %s ===\n", target)
	fmt.Printf("64-bit: %v  ImageBase: 0x%X  EntryPoint: 0x%X\n\n", is64, base, entry)

	// --- checksec ---
	cs, err := pe.Checksec()
	if err != nil {
		log.Fatalf("Checksec: %v", err)
	}
	fmt.Println("--- checksec ---")
	fmt.Printf("ASLR (DYNAMIC_BASE):  %v\n", cs.ASLR)
	fmt.Printf("High-Entropy VA:      %v\n", cs.HighEntropyVA)
	fmt.Printf("DEP (NX_COMPAT):      %v\n", cs.DEP)
	fmt.Printf("CFG:                  %v\n", cs.CFG)
	if cs.SEHApplicable {
		fmt.Printf("SafeSEH:              %v\n", cs.SafeSEH)
	} else {
		fmt.Println("SafeSEH:              n/a (x64 uses table-based SEH)")
	}
	fmt.Printf("GS cookie (heuristic): %v\n", cs.GSHeuristic)
	fmt.Printf("Authenticode present:  %v\n", cs.AuthenticodeSigned)
	fmt.Println()

	// --- section entropy / packing ---
	fmt.Println("--- sections ---")
	for _, sec := range pe.Sections() {
		entropy, _ := sec.Entropy()
		fmt.Printf("%-10s R=%v W=%v X=%v entropy=%.2f\n",
			sec.Name, sec.IsReadable(), sec.IsWritable(), sec.IsExecutable(), entropy)
	}
	fmt.Println()

	// --- IAT: what does this binary already pull in? ---
	fmt.Println("--- interesting imports ---")
	for _, name := range []string{"VirtualProtect", "VirtualAlloc", "LoadLibraryA", "GetProcAddress", "CreateFileA"} {
		imp, err := pe.FindImport(name)
		if err != nil {
			fmt.Printf("%-16s not imported\n", name)
			continue
		}
		fmt.Printf("%-16s %s!%s  IAT RVA=0x%X\n", name, imp.DLL, imp.Name, imp.IATRVA)
	}
	fmt.Println()

	// --- EAT: does this binary export anything (e.g. a win() for ROP)? ---
	exports, err := pe.ListExports()
	if err == nil {
		fmt.Printf("--- exports (%d) ---\n", len(exports))
		for _, e := range exports {
			if e.ForwardTarget != "" {
				dll, fn := winpwn.ParseForwardTarget(e.ForwardTarget)
				fmt.Printf("%s -> forwards to %s!%s\n", e.Name, dll, fn)
			} else {
				fmt.Printf("%s RVA=0x%X\n", e.Name, e.RVA)
			}
		}
		fmt.Println()
	}

	// --- native ROP gadget scan, no rp++/Ropper required ---
	rop, err := winpwn.NewROP(target)
	if err != nil {
		log.Fatalf("NewROP: %v", err)
	}
	defer rop.Close()

	fmt.Println("--- gadgets ---")
	if g, err := rop.Search("pop ecx ; ret"); err == nil {
		fmt.Printf("pop ecx ; ret: 0x%X (%d candidates)\n", g[0].Address, len(g))
		if lines, err := rop.Disassemble(g[0].Address, 2); err == nil {
			fmt.Printf("  verified: %v\n", lines)
		}
	}

	if g, err := rop.Search("pop eax ; ret"); err == nil {
		fmt.Printf("pop eax ; ret: 0x%X (%d candidates)\n", g[0].Address, len(g))
		if lines, err := rop.Disassemble(g[0].Address, 2); err == nil {
			fmt.Printf("  verified: %v\n", lines)
		}
	}

	if g, err := rop.Search("mov dword ptr [ecx], eax ; mov eax, esi ; pop esi ; pop ebp ; ret"); err == nil {
		fmt.Printf("mov dword ptr [ecx], eax ; mov eax, esi ; pop esi ; pop ebp ; ret: 0x%X (%d candidates)\n", g[0].Address, len(g))
		if lines, err := rop.Disassemble(g[0].Address, 2); err == nil {
			fmt.Printf("  verified: %v\n", lines)
		}
	}
	
	if g, err := rop.SearchRegex(`^pop r\w+ ; pop r\w+ ; ret$`); err == nil {
		fmt.Printf("pop r.. ; pop r.. ; ret: %d candidates, first at 0x%X\n", len(g), g[0].Address)
	}

}
