offensive-coding/fsop-dev/SKILL.md
Auth/lab dev: glibc FILE/FSOP exploitability research; libio structures, vtables, wide data, trigger paths, mitigation-aware modeling.
npx skillsauth add aeondave/malskill fsop-devInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Goal: turn FILE-structure corruption into the right libio dispatch path for that glibc era, trigger surface, and endgame — not into random _IO_FILE cargo cult.
Repository positioning: keep offensive-coding/heap-exploitation-dev as the allocator and overlap router, then switch here once success depends more on libio structure modeling, validated jump-table reuse, wide/codecvt/cookie-file dispatch, or trigger choice than on heap choreography itself.
stdin, stdout, stderr, another FILE *, or a fake FILE region.fopen/fdopen/custom FILE *, and the real question becomes how fputs/fwrite/cleanup will consume it._IO_list_all, vtable-misalignment, _wide_vtable, _codecvt, obstack, or leak-only FILE abuse.FILE, _IO_FILE_plus, _IO_wide_data, _IO_codecvt, pointer-guard-adjacent surfaces, or valid jump-table placement.If the problem is mostly allocator selection, heap shaping, tcache/largebin choreography, or House-family routing before the stream overlap exists, start with offensive-coding/heap-exploitation-dev and return here once FSOP is a real candidate.
stdout for output-driven paths like puts, printf, fflushstderr for low-noise or assert/abort-driven pathsstdin for leak or arbitrary-read/write redirectionFILE * / fopen object / socket-backed stream / heap fake FILE_wide_vtable, codecvt, and angr-mapped paths matter more than fake raw heap vtablessetcontext pivot / ORW / SUID-safe chainvtable-adjacent control_wide_data or _codecvt reachabilityputs, printf, fprintf, fwritefflush, fclose, setbuf, sync/finish pathsexit, return from main, abort/assert, __malloc_assertfgets, underflow/seekoff, orientation switches| Era | Bias toward | Avoid or de-prioritize |
|---|---|---|
| glibc <= 2.23 | classic fake vtable, _IO_list_all, _IO_OVERFLOW, raw FILE-chain abuse | post-hook-only thinking |
| glibc 2.24-2.33 | vtable-misalignment, validated jump-table reuse, _wide_vtable routes, leak-first stream abuse | fake heap vtable pointers outside libc vtable section |
| glibc 2.34+ | House of Apple 2/3, _wide_vtable, codecvt, stderr/stdout overlap, setcontext/ORW endings | __free_hook nostalgia |
| glibc 2.35+ and modern | angry-FSROP paths, _IO_wdoallocbuf, _IO_switch_to_wget_mode, codecvt, obstack, TLS/pointer-guard-adjacent pivots | assuming only one Apple chain exists |
| Family | Good fit | Typical result | Reality check |
|---|---|---|---|
| classic _IO_list_all FSOP | pre-vtable-check or controlled valid vtable path | exit-time _IO_overflow dispatch | foundational, but not the modern default |
| stdout/stderr overlap | arbitrary allocation/write over standard streams | trigger via normal output, fflush, or assert path | still one of the best practical setups |
| buffer redirection | control _IO_read_* / _IO_write_* ranges | arbitrary read/write or targeted leak | not all FSOP ends in RIP control |
| vtable misalignment | validated vtable section but wrong slot alignment | call a different libc libio function than intended | central post-2.24 concept |
| House of Apple 2 | _wide_data->_wide_vtable reachable | direct call, system, or setcontext | primary post-hook baseline |
| House of Apple 3 | _codecvt path easier than wide-data path | indirect call through codecvt helper | higher setup cost, but powerful |
| obstack paths | stream or neighboring stream state controllable | call via _obstack_newchunk | underused but real |
| leak-oriented FSOP | need TLS/libc/stack/tcb leak more than immediate RCE | stdout/stderr disclosure, pointer-guard recovery | often better than forcing shell-first |
| pointer-guard-adjacent FSOP | TLS/pointer-guard or encrypted callback surfaces in play | unlock later destructor/cookie-file hijack | usually a bridge, not the first stage |
| input-buffer redirection | can't forge in place (zeroing alloc) or redirect a RO stream pointer; an input stream is read each loop | corrupt only _IO_buf_base/read ptrs (keep vtable+_lock) → program's fgets/fread read()s a forged FILE into another stream → trigger on next print | the practical escape from the in-place wall; CET/IBT-safe (dispatch stays in libc) |
Load references/hints-and-recognition.md when triaging quickly. The shortest recognition cues are:
_exit (no exit/atexit) means _IO_list_all never flushes; unused stderr means no assert/error trigger. Don't forge for an unreachable trigger.stdout or stderr, ask which natural call path touches it next before chasing ROP.vtable must stay inside libc, ask which misaligned slot or alternate jump table gives the call you want._wide_data is reachable, ask can I force _IO_wdoallocbuf or _IO_WOVERFLOW?_codecvt is reachable, ask is this really Apple 3 / codecvt-in/out/length?system("/bin/sh") weak, bias toward setcontext, ORW, or a leak-first destructor chain.stderr or assert-time dispatch.memsets then printfs), do not forge in place. Use cross-stream buffer redirection (corrupt an input stream's _IO_buf_base/read ptrs, keep vtable+_lock, let its fgets/fread read() your forged FILE into another stream), pick a stream the corrupting op never touches, or use a non-zeroing/print-free/second-thread write.puts / printf / fprintf: excellent when stdout is the target and you can satisfy byte-oriented path checks.fflush / sync / finish: strong when you want a quieter dispatch point or an internal sync path.exit / return from main: best when _IO_list_all traversal or cleanup logic is your dispatch engine.__malloc_assert: strong when only failure-driven flushing is realistic; think Cat/Kiwi/Apple-style assert triggers._wide_vtable or codecvt.setcontext pivot, ORW, or structured ROP over system._lock valid and writable unless the chosen path proves it will not be touched._mode must stay negative, become positive, or remain zero for the intended path._IO_read_*, _IO_write_*, _wide_data, or adjacent bytes before dispatch.pwn-ctf RELRO/ASLR relocation guidance and prove object-specific RELRO, page permissions, and ASLR invariance first.system("/bin/sh") on SUID or seccomp targets by reflex._IO_write_ptr, _IO_buf_base, _mode, or _flags before the trigger fires._IO_list_all when the binary only _exits) — verify the trigger in the imports/PLT first.FILE, _IO_FILE_plus, _IO_wide_data, _IO_codecvt, vtable validation, and era map._IO_list_all, Apple 2/3, Pig, Cat, Kiwi, Emma, and where angry-FSROP paths fit.puts, printf, fflush, exit, assert/abort, underflow, seekoff, and why some paths are cleaner than others.Load references only after the target stream, glibc era, available corruption, and intended trigger are clear.
development
Auth/lab ref: Unicorn Engine CPU-only emulation for shellcode, decryptors, custom VM handlers, instruction tracing, memory hooks, and register-level experiments.
development
Auth/lab ref: Renode board and SoC simulation for MCU/RTOS firmware, UART/GPIO/peripheral modeling, GDB remote debugging, REPL platforms, and RESC scripts.
development
Auth/lab ref: Qiling OS-layer binary emulation for PE/ELF/Mach-O/UEFI/shellcode with rootfs, syscall/API hooks, filesystem mapping, and runtime patching.
databases
Auth/lab ref: QEMU user-mode and full-system emulation for cross-arch binaries, firmware, kernels, disks, serial consoles, networking, and GDB stubs.