v0.1 - initial commit

This commit is contained in:
2026-07-18 21:37:15 +03:00
commit 9b89f4cb8e
153 changed files with 22887 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
# winpwn
Pwntools-style exploitation toolkit for Windows pwn/CTF tasks, written in Go.
pwntools targets Linux. winpwn targets the Windows equivalents: SEH instead of
signals, PE instead of ELF, msvcrt/ntdll instead of glibc, the Windows Debug
API instead of ptrace/GDB. Go is used for direct WinAPI access
(`golang.org/x/sys/windows`) and goroutine-based concurrent I/O.
## Install / import
Library (used from a solve script):
```go
import "winpwn"
func main() {
t, err := winpwn.Spawn("./target.exe")
if err != nil {
log.Fatal(err)
}
if err := t.SendLineAfter([]byte("Input: "), payload); err != nil {
log.Fatal(err)
}
t.Interactive()
}
```
The module is used locally via a `replace` directive; it is not published.
CLI (quick-answer wrapper):
```
go install ./cmd/winpwn
go install ./cmd/pwninit
```
## Components
**Core** ([context.go](context.go), [log.go](log.go), [cyclic.go](cyclic.go),
[fiddling.go](fiddling.go), [packing.go](packing.go))
- `Context`: global `Arch`, `LogLevel`, `Timeout`, `Newline` (pwntools' `context`).
- `Info`/`Success`/`Warn`/`Error`: leveled logger to stderr, gated by `Context.LogLevel`.
- `Cyclic`/`CyclicN`/`CyclicFind`/`CyclicFindN`: de Bruijn pattern generation and
offset lookup. Matches pwntools' `cyclic`/`cyclic_find` output.
- `Hexdump`/`Enhex`/`Unhex`/`Xor`.
- `P16`/`P32`/`P64`, `U16`/`U32`/`U64`: little-endian pack/unpack.
**Tubes** ([tube.go](tube.go), [process.go](process.go), [remote.go](remote.go))
- `Spawn` (local process) and `Remote` (TCP) return a `*Tube`.
- `Send`/`SendLine`/`SendAfter`/`SendLineAfter`/`Recv`/`RecvUntil`/`RecvLine`/
`RecvRegex`/`RecvPred`/`Interactive`/`Close`.
- Every method returns `error`; the library never calls `os.Exit`/`log.Fatal`.
- `SetTimeout` overrides `Context.Timeout` per tube (0 = block forever).
**Named pipes** ([pipe_windows.go](pipe_windows.go))
- `ServePipe(name)` / `DialPipe(name)` over `CreateNamedPipe`
(`PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED`) / `CreateFile`, both returning a
`*Tube`.
**PE analysis** ([pe.go](pe.go), [sections.go](sections.go))
- `OpenPE`, `ImageBase`, `EntryPoint`, `Is64Bit` (PE32 and PE32+).
- Per-section `IsReadable`/`Writable`/`Executable`/`IsRWX`, `VirtualAddress`
(RVA), `Offset` (`PointerToRawData`, file offset), `Entropy`,
`LikelyPackedSections`.
- `SearchBytes`: byte-pattern search across sections (analogue of `elf.search()`).
**Checksec** ([checksec.go](checksec.go), [authenticode_windows.go](authenticode_windows.go))
- `(*PEFile).Checksec()`: ASLR, HighEntropyVA, DEP, CFG (cross-checked against
Load Config `GuardFlags`), SafeSEH (x86 only, gated by `SEHApplicable`),
GS-cookie heuristic, Authenticode presence, .NET/CLR.
- `VerifyAuthenticodeSignature`: signature verification via `WinVerifyTrust`
(Windows-only, no network calls).
**Imports / exports** ([exports.go](exports.go), [imports.go](imports.go),
[imported_libs_windows.go](imported_libs_windows.go))
- `ListExports`/`GetExport` with forwarder resolution.
- `ListImports`/`FindImport` walking the IAT thunk arrays.
- `ImportedLibs`: distinct imported DLLs, each `LoadLibrary`'d to report its live
image base (system DLL bases are randomized per boot, not per process, so the
address is valid machine-wide until reboot).
**Live-process PE** ([procmem_windows.go](procmem_windows.go), [symbols_windows.go](symbols_windows.go))
- `OpenPEFromProcess(pid, base)`: every PE accessor works against process memory
(`ReadProcessMemory`), not just a disk file.
- `ResolveModuleBase(pid, name)`: walks `PEB->Ldr->InMemoryOrderModuleList`.
- `SpawnSuspended`/`ResumeMainThread`: launch with `CREATE_SUSPENDED`.
`ResolveModuleBase` returns null until the loader runs post-resume.
- `ProcessSymbols` (`NewProcessSymbols`): `Base`, `Symbol`, `Modules`,
`AllSymbols`. `SymbolVA`/`ListLoadedModules` for one-off lookups.
**ROP gadgets** ([gadgets.go](gadgets.go), [rop.go](rop.go))
- `NewROP(path)`: shells out to `rp-win.exe` (a Windows build of rp++), resolved
from `RP_WIN_EXE` or `C:\tools\rp-win\rp-win.exe`. Run with `--allow-branches`,
so results include JOP transit gadgets (indirect `jmp reg`/`call reg`) as well
as ret-terminated ones.
- `NewROPExternal(path, toolPath)`: explicit tool path.
- `Find(pattern)`: ranked matches, index 0 is the cleanest usable gadget.
`Search`/`SearchRegex`: `(results, error)` form.
- `Disassemble(addr, count)`: native decode via `golang.org/x/arch/x86/x86asm`
for verifying a chain in-script.
**Patching** ([patch.go](patch.go))
- `OpenPEForWrite`, `SetSectionCharacteristics`/`MakeSectionExecutable`/
`MakeSectionWritable`, `DisableTLSCallbacks`, `PatchBytes`/
`PatchBytesAtOffset`, `RecalculateChecksum`.
**Minidump** ([minidump.go](minidump.go))
- `OpenMinidump(path)`: parses `MINIDUMP_HEADER`/`MINIDUMP_DIRECTORY` directly
(no `dbghelp.dll`). `Modules()` (loaded modules + base addresses),
`Exception()` (faulting thread/code/address/parameters), `RawStream(type)` for
any other stream. Works without `GOOS=windows`.
**Debugger** ([debugger_windows.go](debugger_windows.go))
- `Attach(pid)`: wraps the Windows Debug API
(`DebugActiveProcess`/`WaitForDebugEvent`/`ContinueDebugEvent`/
`Get/SetThreadContext`), resolved via `LazyDLL`.
- `Events()`: typed event channel (`EventBreakpoint`/`EventException`/
`EventCreateProcess`/`EventLoadDll`/`EventExitProcess`/...).
- `SetBreakpoint`/`RemoveBreakpoint`: software INT3; `Continue` handles the
restore/single-step/re-arm sequence internally.
- `GetContext`/`SetContext` (registers), `ReadMemory`/`WriteMemory`.
- No GUI-debugger (x64dbg/WinDbg) integration; `Attach` uses the same Win32 API.
**Heap struct parsing** ([heap.go](heap.go), [heap_lfh.go](heap_lfh.go),
[heap_segment.go](heap_segment.go), [heap_windows.go](heap_windows.go))
- Works against any `io.ReaderAt` (`*ProcessMemory`, `*Debugger`, or a test
buffer). Only `ListProcessHeaps` requires a live process (walks the PEB).
- NT Heap: `ReadHeap`, `DecodeHeapEntry` (XOR-decoding), `WalkAllHeapEntries`,
`SummariseEntries`, `AdjacentBusyPairs`, `EntriesInRange`, `EntriesWithUserData`.
- NT Heap LFH: `ReadLFHBuckets`, `FindLFHBucket`, `ActiveSubsegment`,
`ReadLFHSubsegment`, `CalibrateLFHFirstBlockOffset`, `BlockAddress`, `SlotOf`.
- Segment Heap: `ReadSegmentHeap` (VS/LFH context summaries).
- `AdjacentAddressPairs`/`FindAdjacentPair`: adjacency detection from leaked
addresses, no chunk-header decode required.
- Offsets confirmed on build 10.0.26100; verify on other builds. VS chunk headers
and LFH `EncodedOffsets` are XOR-encoded and not decoded — calibrate against a
known address instead.
**Spray** ([spray.go](spray.go))
- `SprayAndFind`: spray up to N times, check each attempt against all prior
samples (plus an optional seed) via a caller-supplied relation, return the
first match. Covers both equality (UAF reuse) and distance (adjacency) checks.
**Shellcraft** ([shellcraft.go](shellcraft.go), [shellcode_exec_windows.go](shellcode_exec_windows.go))
- `ShellcodeWinExec(cmd)`: position-independent x64 shellcode resolving kernel32
via the PEB (source: [shellcode/asm/winexec_x64.asm](shellcode/asm/winexec_x64.asm)).
- `ExecuteShellcode`: runs a template locally for validation.
**CLI** ([cmd/winpwn](cmd/winpwn/main.go), [cmd/pwninit](cmd/pwninit/main.go))
- `winpwn`: `checksec`, `cyclic`, `hex`/`unhex`, `hexdump`, `rop`, `bytes`,
`disasm`, `exports`, `imports`, `heap`.
- `pwninit`: prints recon (arch, checksec, sections, imported libs) and scaffolds
a `go.mod` + minimal `main.go` for a new task.
## Documentation
- [USAGE.md](USAGE.md) — worked examples and a function-by-function reference.
- [USAGE_RU.md](USAGE_RU.md) — condensed reference (Russian).
- [ROADMAP.md](ROADMAP.md) — implementation status and planned work.