v0.1 - initial commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user