Reader

Blog

Welcome to the Blog.

Security Findings as Design Feedback

Reading vulnerabilities as architecture signals

Security reports are often treated as defect inventories: patch issue, close ticket, move on. That workflow is necessary, but it is incomplete. Many findings are not isolated mistakes; they are design feedback about how a system creates, hides, or amplifies risk. Teams that only chase individual fixes improve slowly. Teams that read findings as architecture signals improve compoundingly.

A useful reframing is to ask, for each vulnerability: what design decision made this class of bug easy to introduce and hard to detect? The answer is frequently broader than the code diff. Weak trust boundaries, inconsistent authorization checks, ambiguous ownership of validation, and hidden data flows are structural causes. Fixing one endpoint without changing those structures guarantees recurrence.

Take broken access control patterns. A typical report may show one API endpoint missing a tenant check. The immediate patch adds the check. The design feedback, however, is that authorization is optional at call sites. The durable response is to move authorization into mandatory middleware or typed service contracts so bypassing it becomes difficult by construction. Good security design reduces optionality.

Input-validation findings show similar dynamics. If every handler parses raw request bodies independently, validation drift is inevitable. One team sanitizes aggressively, another copies old logic, a third misses edge cases under deadline pressure. The root issue is distributed policy. Consolidated schemas, shared parsers, and fail-closed defaults turn ad-hoc validation into predictable infrastructure.

Injection flaws often reveal boundary confusion rather than purely “bad escaping.” When query construction crosses multiple abstraction layers with mixed assumptions, responsibility blurs and dangerous concatenation appears. The design-level fix is not a lint rule alone. It is to constrain query creation to safe primitives and enforce typed interfaces that make unsafe composition visibly abnormal. ... continue

ROP Under Pressure

Payloads that survive leaks, mitigations, and messy binaries

Return-oriented programming feels elegant in writeups and messy in real targets. In controlled examples, gadgets line up, stack state is stable, and side effects are manageable. In live binaries, you are usually balancing fragile constraints: limited write primitives, partial leaks, constrained input channels, and mitigation combinations that punish assumptions.

Working “under pressure” means building payloads that survive imperfect conditions, not just proving theoretical code execution.

My practical approach starts by classifying constraints before touching gadgets:

Without this map, gadget hunting becomes random motion.

A reliable chain should minimize dependencies. Fancy multi-stage chains look impressive but fail more often when target timing or memory layout shifts. Prefer short chains with explicit stack hygiene and clear post-condition checks. ... continue

Recon Pipeline with Unix Tools

Composable stages instead of one monolithic scanner

Recon tooling has exploded, but many workflows are still stronger when built from composable Unix primitives instead of a single monolithic scanner. The reason is control: you can tune each step, inspect intermediate data, and adapt quickly when targets or scope constraints change.

A practical recon pipeline is not about running every tool. It is about building trustworthy data flow:

If one stage is noisy, downstream conclusions become fiction.

My default stack stays intentionally boring:

Boring tools are good because they are scriptable and predictable. ... continue

Recapping a Vintage Mainboard

A controlled restoration process, not just a parts swap

Recapping is one of those maintenance tasks that seems simple from a distance and unforgiving in practice. “Replace old capacitors” sounds straightforward until you are diagnosing intermittent instability on a thirty-year-old board with unknown service history, lifted pads, and undocumented revisions.

Done well, recapping is not a parts swap. It is a controlled restoration process with verification steps before, during, and after soldering.

Start with baseline behavior. Do not desolder anything yet. Record:

Without baseline data, you cannot measure improvement or detect regressions introduced during rework.

Next, create a capacitor map from the actual board, not just internet photos. Vintage boards often have revision differences. Mark value, voltage rating, polarity orientation, and physical clearance constraints. Photograph every zone before removal. Good photos save bad assumptions later. ... continue

Prototyping with Failure Budgets

Planning time for bad assumptions and rework

Most prototype plans assume success too early. Schedules are built around happy-path bring-up, and risk is represented as a vague buffer at the end. In practice, hardware projects move faster when failure is budgeted explicitly from the beginning.

A failure budget is not pessimism. It is resource planning for uncertainty:

Without these budgets, teams call normal engineering iteration “delay.”

The first step is failure classification. Not all failures are equal:

Each class needs different mitigation strategy, so one generic “debug week” is rarely effective. ... continue

Overlay Lab: Build and Debug OVR

Hands-on overlay packaging, runtime setup, and deployment in Turbo Pascal

This tutorial is intentionally practical. You will build a small Turbo Pascal program with one resident path and one overlayed path, then test deployment and failure behavior.

If your install names/options differ, keep the process and adapt the exact menu or command names.

Goal and expected outcomes

Goal: move a cold code path out of always-resident memory and verify it loads on demand from .OVR.

Expected outcomes before you start:

Minimal project layout

1
2
3
4
OVRDEMO/
  MAIN.PAS
  REPORTS.PAS
  BUILD.BAT

Step 1: write resident core and cold module

REPORTS.PAS (cold path candidate):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{$O+}  { TP5 requirement: unit may be overlaid }
{$F+}  { TP5 requirement for safe calls in overlaid programs }
unit Reports;

interface
procedure RunMonthlyReport;

implementation

procedure RunMonthlyReport;
var
  I: Integer;
  S: LongInt;
begin
  S := 0;
  for I := 1 to 25000 do
    S := S + I;
end;

end.

... continue

Mode X (TP) IV: Tilemaps

Scrolling worlds, chunk loading, and scene-scale memory budgets

A renderer becomes a game when it can show world-scale structure, not just local effects. That means tilemaps, camera movement, and disciplined data loading. In Mode X-era development, these systems were not optional polish. They were the only way to present rich scenes inside strict memory budgets.

This final Mode X article focuses on operational structure: how to build scenes that scroll smoothly, load predictably, and remain debuggable.

Start with memory budget, not features

Before defining map format, set your memory envelope:

Then derive map chunk dimensions from those limits. Teams that reverse the order usually rewrite their map loader halfway through the project.

Tilemap schema that survives growth

A practical map record often includes: ... continue

Mode X (TP) III: Sprites

Masked blits, transparency, draw order, and palette animation

Sprites are where a renderer starts to feel like a game engine. In Mode X, the challenge is not just drawing images quickly. The challenge is managing transparency, overlap order, and visual dynamism while staying within the strict memory and bandwidth constraints of VGA-era hardware.

If your primitives and clipping are not stable yet, go back to Part 2 . Sprite bugs are hard enough without foundational uncertainty.

Sprite data strategy: keep it explicit

A reliable sprite pipeline separates three concerns:

Trying to “infer” transparency from arbitrary colors in ad-hoc code works until assets evolve. Use explicit conventions and document them in your asset converter notes.

Masked blit pattern

A classic masked blit uses one pass to preserve destination where mask says transparent, then overlays sprite pixels where opaque. In Turbo Pascal, even simple byte-level logic remains effective if your loops are predictable. ... continue

Mode X (TP) II: Primitives

Plane-aware pixels, centralized clipping, and page-target drawing

After the planar memory model clicks, the next trap is pretending linear drawing code can be “ported” to Mode X by changing one helper. That works for demos and fails for games. Robust Mode X rendering starts with primitives that are aware of planes, clipping, and page targets from day one.

If you missed the foundation, begin with Part 1: Planar Memory and Pages . This article assumes you already have working pixel output and page flipping.

Primitive design goals

For old DOS rendering pipelines, primitives should optimize for correctness first:

Performance matters, but undefined writes kill performance faster than any missing micro-optimization.

Clipping is policy, not an afterthought

A common beginner pattern is “draw first, check later.” On VGA memory that quickly becomes silent corruption. Instead, apply clipping at primitive boundaries before entering the hot loops. ... continue

Mode X (TP) I: Planar Memory

VGA planes, off-screen pages, and why games left Mode 13h

Mode 13h is the famous VGA “easy mode”: one byte per pixel, 320x200, 256 colors, linear memory. It is perfect for first experiments and still great for teaching rendering basics. But old DOS games that felt smoother than your own early experiments usually did not stop there. They switched to Mode X style layouts where planar memory, off-screen pages, and explicit register control gave better composition options and cleaner timing.

This first article in the series is about that mental model. Before writing sprite engines, tile systems, or palette tricks, you need to understand what the VGA memory controller is really doing. If the model is wrong, every optimization turns into folklore.

If you have not read Mode 13h Graphics in Turbo Pascal , do that first. It gives the baseline we are now deliberately leaving behind.

Why Mode X felt “faster” in real games

The practical advantage was not raw arithmetic speed. The advantage was control over layout and buffering:

What looked like magic in magazines was mostly disciplined memory mapping plus stable frame pacing.

The key shift: from linear bytes to planes

... continue