~/components/README.md

Component gallery: every post block on one page

Every body component a post can use, each shown once with how it looks and works; all data is illustrative (documentation addresses, example.com hosts, made-up hashes).

Contents
  1. 0x00Network
  2. 0x01Bytes and layouts
  3. 0x02Debugging and reversing
  4. 0x03Code
  5. 0x04Data
  6. 0x05Security artefacts
  7. 0x06Narrative

This page uses every post component once, to show how each looks and works in a post, and so styles, scripts and performance can be checked in one place. All data is illustrative: addresses come from the documentation ranges, hosts are example.com names, and hashes, serials and timings are made up unless the text says otherwise.

Network

A raw request and its response, instead of a screenshot of a proxy's request pane:

login · Set-Cookie
Request
POST /login HTTP/1.1
Host: app.example.com
Content-Type: application/x-www-form-urlencoded

user=alice&password=REDACTED
Response
HTTP/1.1 303 See Other
Location: /
Set-Cookie: session=REDACTED; Path=/; Secure; HttpOnly; SameSite=Lax

A packet list with its field tree and bytes, instead of a protocol analyzer screenshot:

DNS lookuppcap
No.TimeSourceDestinationProtocolLengthInfo
10.000000192.0.2.10192.0.2.53DNS71Standard query 0x4a7c A example.com
20.012204192.0.2.53192.0.2.10DNS87Standard query response 0x4a7c A example.com A 192.0.2.80
#1 · DNS · Standard query 0x4a7c A example.com
  • Ethernet II, Src: 00:00:5e:00:53:0a, Dst: 00:00:5e:00:53:35
    • Destination: 00:00:5e:00:53:35
    • Source: 00:00:5e:00:53:0a
    • Type: IPv4 (0x0800)
  • Internet Protocol Version 4, Src: 192.0.2.10, Dst: 192.0.2.53
    • 0100 .... = Version: 4
    • .... 0101 = Header Length: 20 bytes (5)
    • Time to Live: 64
    • Protocol: UDP (17)
    • Header Checksum: 0xda2e not verified
    • Source Address: 192.0.2.10
    • Destination Address: 192.0.2.53
  • User Datagram Protocol, Src Port: 53001, Dst Port: 53
    • Source Port: 53001
    • Destination Port: 53
    • Length: 37
    • Checksum: 0x923b
  • Domain Name System (query)
    • Transaction ID: 0x4a7c
    • Flags: 0x0100 Standard query
      • 0... .... .... .... = Response: Message is a query
      • .... ...1 .... .... = Recursion desired: Do query recursively
    • Questions: 1
    • Queries
      • example.com: type A, class IN
        • Name: example.com
        • Type: A (1)
        • Class: IN (0x0001)
0000 00 00 5E 00 53 35 00 00 5E 00 53 0A 08 00 45 00
0010 00 39 1C 46 00 00 40 11 DA 2E C0 00 02 0A C0 00
0020 02 35 CF 09 00 35 00 25 92 3B 4A 7C 01 00 00 01
0030 00 00 00 00 00 00 07 65 78 61 6D 70 6C 65 03 63
0040 6F 6D 00 00 01 00 01
2 packets

Bytes and layouts

Named fields over a hex dump, instead of a hex editor screenshot:

hello · ELF64 header (first 32 bytes)
000000007F454C46020101000000000000000000
0000001003003E00010000006010000000000000
  1. EI_MAG0x00–0x03magic 0x7F followed by ASCII E, L, F
  2. EI_CLASS0x042 = ELFCLASS64
  3. EI_DATA0x051 = little-endian
  4. e_type0x10–0x113 = ET_DYN, also used by PIE
  5. e_machine0x12–0x130x3E = x86-64
  6. e_entry0x18–0x1Fentry point 0x1060

A C structure as bytes and a field table, instead of a struct diagram or pahole output:

struct malloc_chunk (glibc, x86-64)x86-64 · LE
OffsetNameTypeSizeValue
0x00mchunk_prev_sizesize of the previous chunk while it is freesize_t8
0x08mchunk_sizechunk size; low 3 bits are flagssize_t80x31
0x10fdstruct malloc_chunk *80x55555555a2c0
0x18bkoverwrittenstruct malloc_chunk *80x4141414141414141
0x20fd_nextsizestruct malloc_chunk *8
0x28bk_nextsizestruct malloc_chunk *8
sizeof(struct malloc_chunk) = 0x30 (48 bytes)

The bits of a register, instead of a figure from a processor manual (flip a bit to see the fields decode):

x86-64 page-table entry (4 KiB page)64-bit
XDPK0x0Address0x0000012345
AddressGPATDAPCDPWTU/SR/WP
value0x80000000_12345067= 9223372037160194151
BitsFieldValue
63XDExecute disable1
62–59PKProtection key0x0
51–12AddressPhysical address of the page frame0x0000012345
8GGlobal0
7PAT0
6DDirty1
5AAccessed1
4PCD0
3PWT0
2U/S
  • 0 supervisor
  • 1 user
1
1R/W
  • 0 read-only
  • 1 read/write
1
0PPresent1

A process tree, instead of a screenshot of a process explorer:

Process tree
  • explorer.exepid 4012user alice
    • WINWORD.EXEpid 6120opened invoice.docm
      • cmd.exepid 6644
        • powershell.exepid 7020cmd powershell -nop -w hidden -enc …encoded command line
          • conhost.exepid 7028
    • OneDrive.exepid 4388
      • FileCoAuth.exepid 4502
7 processes

Debugging and reversing

Disassembly with addresses and bytes, instead of a disassembler screenshot:

.text:_start · x86-64 · Intel syntax
0x1060f3 0f 1e faendbr64
0x106431 edxorebp, ebp; clear the frame pointer: outermost frame
0x106649 89 d1movr9, rdx; rtld_fini → sixth argument
0x106d48 83 e4 f0andrsp, 0xfffffffffffffff0; align the stack to 16 bytes
0x107848 8d 3d ca 00 00 00leardi, [rip+0xca]; main @ 0x1149
0x107fff 15 53 2f 00 00callqword ptr [rip+0x2f53]; __libc_start_main@GOT

Debugger snapshots to step through, instead of debugger screenshots or a stepping GIF:

leave; ret: tearing down a stack framex86-64
  1. Step 1/3before leave

    rbp points at the saved frame pointer; the return address sits above it.

    Code
    0x401136<add+16>8b 45 fcmoveax, dword ptr [rbp-0x4]
    current instruction: 0x401139<add+19>c9leave
    0x40113a<add+20>c3ret
    Registers
    rax
    0x2a
    rbp
    0x7ffe3a8c1e40
    rsp
    0x7ffe3a8c1e30
    rip
    0x401139 <add+19>
    Flags
    • ZF1
    • PF1
    Stack
    Registers pointing hereAddressValueNote
    rsp0x7ffe3a8c1e300x0000000000000000
    0x7ffe3a8c1e380x0000002a00000000locals
    rbp0x7ffe3a8c1e400x00007ffe3a8c1e60saved rbp
    0x7ffe3a8c1e480x0000000000401160return address
    Memory
    AddressBytes
    0x7ffe3a8c1e4060 1e 8c 3a fe 7f 00 00 60 11 40 00 00 00 00 00
  2. Step 2/3after leave

    leave is mov rsp, rbp then pop rbp.

    Code
    0x401136<add+16>8b 45 fcmoveax, dword ptr [rbp-0x4]
    0x401139<add+19>c9leave
    current instruction: 0x40113a<add+20>c3ret
    Registers
    rax
    0x2a
    rbp
    0x7ffe3a8c1e60 (changed, was 0x7ffe3a8c1e40)
    rsp
    0x7ffe3a8c1e48 (changed, was 0x7ffe3a8c1e30)
    rip
    0x40113a <add+20> (changed, was 0x401139)
    Flags
    • ZF1
    • PF1
    Stack
    Registers pointing hereAddressValueNote
    0x7ffe3a8c1e300x0000000000000000
    0x7ffe3a8c1e380x0000002a00000000locals
    0x7ffe3a8c1e400x00007ffe3a8c1e60saved rbp
    rsp0x7ffe3a8c1e480x0000000000401160return address
    Memory
    AddressBytes
    0x7ffe3a8c1e4060 1e 8c 3a fe 7f 00 00 60 11 40 00 00 00 00 00
  3. Step 3/3after ret

    ret pops the return address into rip.

    Code
    0x401136<add+16>8b 45 fcmoveax, dword ptr [rbp-0x4]
    0x401139<add+19>c9leave
    0x40113a<add+20>c3ret
    Registers
    rax
    0x2a
    rbp
    0x7ffe3a8c1e60
    rsp
    0x7ffe3a8c1e50 (changed, was 0x7ffe3a8c1e48)
    rip
    0x401160 <main+26> (changed, was 0x40113a)
    Flags
    • ZF1
    • PF1
    Stack
    AddressValueNote
    0x7ffe3a8c1e300x0000000000000000
    0x7ffe3a8c1e380x0000002a00000000locals
    0x7ffe3a8c1e400x00007ffe3a8c1e60saved rbp
    0x7ffe3a8c1e480x0000000000401160return address
    Memory
    AddressBytes
    0x7ffe3a8c1e4060 1e 8c 3a fe 7f 00 00 60 11 40 00 00 00 00 00

A backtrace with the key frame marked and library frames folded, instead of a crash dialog screenshot:

SIGSEGV in png_read_row (toy viewer)x86-64
  1. #0 (system frame)0x7f3a2b9a1f2flibc.so.6!__memmove_avx_unaligned_erms+0x2f
  2. #1 (system frame)0x7f3a2b9a2a5dlibc.so.6!__memcpy_chk+0x1d
  3. #2 (key frame)0x7f3a2c01d9e4libpng16.so.16!png_read_row+0x1c4pngread.c:512

    row_buf holds 0x40 bytes, but the row is 0x200 bytes long.

  4. #30x7f3a2c01e1a0libpng16.so.16!png_read_image+0x5cpngread.c:720
  5. #40x55d0c0a01234viewer!load_image+0x9asrc/image.c:88
  6. #50x55d0c0a00f8aviewer!main+0x2asrc/main.c:31
  7. #6 (system frame)0x7f3a2b829d90libc.so.6!__libc_start_call_main+0x80
  8. #7 (system frame)0x7f3a2b829e40libc.so.6!__libc_start_main+0x89
  9. #80x55d0c0a00b55viewer!_start+0x25
9 frames · innermost first · 4 system

A control-flow graph, instead of a screenshot of a disassembler's graph view:

check_keyx86-64
entryentry
0x401126  cmp esi, 0x10
0x401129  jne bad
0x40112b  xor ecx, ecx

Next: bad (true), loop (false).

loopecx = i
0x40112d  movzx eax, byte ptr [rdi+rcx]
0x401131  xor   al, 0x5a
0x401133  cmp   al, byte ptr [rdx+rcx]
0x401136  jne   bad

Next: bad (true), next (false).

bad
0x401145  xor eax, eax
0x401147  ret

No successors.

next
0x401138  inc ecx
0x40113a  cmp ecx, 0x10
0x40113d  jl  loop

Next: loop (true), ok (false).

ok
0x40113f  mov eax, 1
0x401144  ret

No successors.

5 blocks · 6 edgestruefalsehighlighted path

An executable's headers, sections and imports, instead of a PE viewer screenshot:

hello.exePE32+
Arch
x86-64
Type
EXE (console)
Entry point
0x140001400
Image base
0x140000000
Security
  • ASLR: on
  • DEP: on
  • CFG: off
  • SafeSEHn/a
Header fields
Machine
0x8664
AMD64
NumberOfSections
4
TimeDateStamp
0x66F2A1C0
DllCharacteristics
0x8160
HIGH_ENTROPY_VA | DYNAMIC_BASE | NX_COMPAT
Sections4
NameRVAMem sizeOffsetFile sizeFlagsEntropyNote
.textEP0x000010000x1A2C0x000004000x1C00r-x6.21
.rdata0x000030000xF100x000020000x1000r--4.87
.data0x000040000x6400x000030000x200rw-1.02
.rsrc0x000050000x1E00x000032000x200r--7.61compressed icon

Entropy (bits/byte)< 1 sparse< 6.8 typical6.8–7.2 high≥ 7.2 packed or encrypted

Imports2 libraries · 6 symbols
KERNEL32.dll4
  • GetStdHandle
  • WriteConsoleW
  • ExitProcess
  • VirtualProtectchanges page protection at run time
VCRUNTIME140.dll2
  • memset
  • __C_specific_handler

A process memory map, instead of a screenshot of vmmap or /proc/<pid>/maps in a terminal:

demo (pid 4242): /proc/4242/maps64-bit

8 regions · 2.02 MiB mapped · 4 gaps · 1 W+X

  • image5
  • heap1
  • private1
  • stack1
  • writable + executable
  • marked
  • unmapped (compressed)
StartEndSizePermTypeModule / note
000055555555400000005555555550004 KiBr--pimage/usr/local/bin/demo
000055555555500000005555555560004 KiBr-xpimage/usr/local/bin/demo
000055555555600000005555555580008 KiBrw-pimage/usr/local/bin/demo
000055555555800000005555555590004 KiBunmapped
0000555555559000000055555557a000132 KiBrw-pheap[heap]
000055555557a00000007ffff7d8300042.7 TiBunmapped
00007ffff7d8300000007ffff7dab000160 KiBr--pimage/usr/lib/x86_64-linux-gnu/libc.so.6
00007ffff7dab00000007ffff7f400001.58 MiBr-xpimage/usr/lib/x86_64-linux-gnu/libc.so.6
00007ffff7f4000000007ffff7fbb000492 KiBunmapped
00007ffff7fbb00000007ffff7fbc0004 KiBrwxpW+XprivateRWX page from mmap(PROT_WRITE | PROT_EXEC)
00007ffff7fbc00000007ffffffde000128 MiBunmapped
00007ffffffde00000007ffffffff000132 KiBrw-pstack[stack]

Code

A shell session where readers copy only the commands, instead of a terminal screenshot:

lab · file
$ file ./hello
./hello: ELF 64-bit LSB pie executable, x86-64
$ id -u
1000

Numbered notes on lines of code, instead of a screenshot with arrows drawn on it:

read_header.cc
ssize_t n = read(fd, hdr, sizeof *hdr);
if (n != sizeof *hdr) return -1;
if (hdr->len > MAX_BODY) return -1;
body = malloc(hdr->len);
  1. read may return fewer bytes than asked for, even on a regular file.
  2. A short read is an error here; n may also be -1 with errno set.
  3. The length comes from the input: check it before it sizes an allocation.

A patch with word-level marks and a split view, instead of a screenshot of a code review:

Check the length before copying+3 −2
src/parse.c
@@ -41,7 +41,8 @@ int parse_header(int fd, struct hdr *out)
unsigned char buf[64];
ssize_t n = read(fd, buf, sizeof buf);
if (n < 0)
if (n < (ssize_t)sizeof *out)
return -1;
memcpy(out, buf, n);
memcpy(out, buf, sizeof *out);
out->len = be16toh(out->len);
return 0;
}

Two listings side by side, instead of two screenshots next to each other:

Smali
smali
.method public static check(I)Z
    const/4 v0, 0x1
    return v0
.end method
Java
java
static boolean check(int x) {
    return true;
}

Data

A JSON document to fold and search, instead of a screenshot of a decoded token:

token.json (decoded JWT)json
{
"header": {
"alg": "RS256",
"kid": "2026-09"
},
"payload": {
"iss": "https://login.example.com/",
"aud": "api.example.com",the API that must check it
"sub": "user-4711",
"exp": 1790000000,
"scope": [
"read:posts",
"write:posts"
],
"admin": false,
"nonce": null
},
"sig_bits": 2048
}
object · 3 keys · 328 B

A sortable, filterable table with typed columns, instead of a spreadsheet screenshot:

Listening services on 192.0.2.106 rows
Port Proto Service Banner Last seen
22 tcp ssh OpenSSH_9.6 2025-03-02
53 udp domain — 2025-02-28
161 udp snmp — 2025-02-27
443 tcp https nginx 2025-03-02
3306 tcp mysql 8.0.36 2025-03-01
8080 tcp http-alt Werkzeug/3.0.1 2025-03-01

A chart drawn from the numbers, with its data table, instead of a chart image:

Fuzzer crashes per build
Unique crashes
  • AFL++
  • libFuzzer

Build

Data table 4 × 2
BuildAFL++libFuzzer
v1.0128
v1.11815
v1.2911
v1.32219

A log to filter by level and text, instead of a screenshot of a log console:

auth-service.loglog
7 linesERROR 1WARN 4INFO 2
2025-03-02T09:14:00.120Z INFO  [main] auth - listening on 127.0.0.1:8443
2025-03-02T09:14:07.004Z WARN  [http-3] auth - login failed user=admin src=198.51.100.7
2025-03-02T09:14:07.513Z WARN  [http-3] auth - login failed user=admin src=198.51.100.7
2025-03-02T09:14:08.020Z WARN  [http-3] auth - login failed user=admin src=198.51.100.7
2025-03-02T09:14:08.533Z WARN  [http-3] auth - login failed user=admin src=198.51.100.7
2025-03-02T09:14:09.041Z ERROR [http-3] auth - rate limit reached, blocking 198.51.100.7 for 900s
2025-03-02T09:14:31.870Z INFO  [http-5] auth - login ok user=deploy src=192.0.2.24 mfa=totp

Formulas in TeX instead of pictures of equations: inline, XOR cancels itself (a⊕a=0a \oplus a = 0), and on a line of their own:

crc⁡(a⊕b⊕c)=crc⁡(a)⊕crc⁡(b)⊕crc⁡(c)\operatorname{crc}(a \oplus b \oplus c) = \operatorname{crc}(a) \oplus \operatorname{crc}(b) \oplus \operatorname{crc}(c)

Security artefacts

An advisory card whose badge follows the CVSS score, instead of a screenshot of a CVE page:

CVE-2026-XXXXXCVSS 5.5 MEDIUMsample data

Out-of-bounds read in a sample ELF parsing library

A sample ELF parsing library reads out of bounds on a malformed e_shnum, which can crash the process.

AVNALP
ACLH
PRNLH
UINR
SCU
CHLN
IHLN
AHLN
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
Affected
< 2.4.1
Fixed in
2.4.1
CWE
CWE-125
  1. Reported
  2. Confirmed
  3. Fixed
  4. Disclosed

Multi-engine scan results, instead of a screenshot of an online scanner (the sample is the EICAR test file; the engine names are made up):

Multi-engine scanCOM

58/66

eicar.com

58 of 66 engines flagged it as malicious, 1 as suspicious

Type
EICAR antivirus test file (ASCII text)
Size
68 bytes
Scanned
  • malicious 58
  • suspicious 1
  • undetected 7
  • unsupported 4
MD5
44d88612fea8a8f36de82e1278abb02f
SHA-1
3395856ce81f2b7382dee72602f798b642f14140
SHA-256
275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
EngineVerdictDetectionVersionUpdated
AegismaliciousEICAR-Test-File (not a virus)4.2.1
BastionmaliciousEICAR_Test_File—
CindersuspiciousHeur.TestString——
Daggerundetected———
Emberunsupported———
5 of 70 engines listed

A certificate chain judged against a stated date, instead of a screenshot of a browser's certificate viewer:

www.example.comX.509
  1. leafwww.example.comvalid
    Subject
    CN=www.example.com, O=Example Corp, C=US
    Issuer
    CN=Example TLS RSA CA 2026, O=Example Trust, C=US
    Validity
    → 111 days left · 365-day period
    Key
    EC P-256
    Signature
    sha256WithRSAEncryption
    SANs
    • DNS www.example.com
    • DNS example.com
    Detailsserial · 1 extension · usages
    Serial
    04:7A:C1:9E:5B:20:3D:8F:61:0E:A4:C7:92:1B:58:E3
    Key usage
    digitalSignature
    EKU
    serverAuth, clientAuth
    Extensions
    • basicConstraints criticalCA:FALSE

    issued by the next certificate

  2. intermediateExample TLS RSA CA 2026valid
    Subject
    CN=Example TLS RSA CA 2026, O=Example Trust, C=US
    Issuer
    CN=Example Root CA, O=Example Trust, C=US
    Validity
    → 1661 days left · 3652-day period
    Key
    RSA 2048
    Signature
    sha256WithRSAEncryption

    issued by the next certificate

  3. rootExample Root CAtrustedvalidself-signed
    Subject
    CN=Example Root CA, O=Example Trust, C=US
    Issuer
    CN=Example Root CA, O=Example Trust, C=US
    Validity
    → 1872 days left · 9132-day period
    Key
    RSA 4096
    Signature
    sha1WithRSAEncryption
checked · validity is judged against this date

Indicators of compromise, grouped and defanged, instead of a screenshot of a threat report table:

Loader campaign, September 2026TLP:AMBER
SHA-256 1
  • 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
    dropper (EICAR test file)first seen
IPv4 1
  • 192[.]0[.]2[.]44:8443
    C2 listener
IPv6 1
  • 2001[:]db8[:][:]44
Domains 1
  • update[.]example[.]com
    C2, resolves to the address belowfirst seen
URLs 1
  • hxxps://cdn[.]example[.]net/assets/app[.]js?v=3
    second stage
Email addresses 1
  • billing[@]example[.]test
    phishing sender
Registry keys 1
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run\ExampleSync
    persistence
Mutexes 1
  • Global\example-sync-7f3a
8 indicators · 8 types · defanged

Narrative

A dated timeline, instead of a timeline slide:

Disclosure timeline, sample router2024-03 → 2024-06
2024
  1. Reported Reported to the vendor

    Proof of concept sent to security@example.com.

  2. +2 days
    Acknowledged Vendor acknowledged the report
  3. +12 days
    CVE assigned CVE-2024-XXXX reserved
  4. +2 days
    Fixed Fix developed and tested

    → · 37 days

  5. +43 days
    Released Firmware 2.4.1 released
  6. +31 days
    Disclosed Advisory published

    90 days after the report, as agreed.

Reported → Released 59 days · Released → Disclosed 31 days

Numbered steps with folded output, instead of a series of screenshots:

Reproduce the path traversal3 steps
  1. 1

    Start the vulnerable build

    bash
    docker run --rm -p 127.0.0.1:8080:8080 example/fileserver:1.4.2
  2. 2

    Request a file outside the web root

    The server joins the path without normalising it:

    bash
    curl -s --path-as-is 'http://127.0.0.1:8080/static/../../etc/hostname'
    Outputresponse2 linesfileserver-7f3c
    responseoutput
    fileserver-7f3c
    
  3. 3

    Confirm the fix

    Version 1.4.3 answers 400 Bad Request for the same request.

The same task per platform, instead of one screenshot per system:

Check the TLS certificate
Linux
bash
openssl s_client -connect example.com:443 -servername example.com </dev/null | openssl x509 -noout -dates
Windows

PowerShell has no openssl; read the certificate from the connection:

powershell
$tcp = [Net.Sockets.TcpClient]::new("example.com", 443)
$tls = [Net.Security.SslStream]::new($tcp.GetStream())
$tls.AuthenticateAsClient("example.com")
$tls.RemoteCertificate.GetExpirationDateString()

A sequence diagram drawn in the browser, instead of an exported drawing:

sequenceDiagram
  accTitle: A cross-site POST under SameSite=Lax
  accDescr: A page on evil.example submits a form to app.example.com; the browser sends no session cookie, and the server refuses.
  participant E as evil.example
  participant B as Browser
  participant A as app.example.com
  E->>B: auto-submitted form POST
  B->>A: POST /transfer (no session cookie)
  A-->>B: 403 Forbidden

A terminal recording that plays in the page, instead of a GIF:

guest@lab:~/demo — forge.py
Download the terminal recording crc32-forge.cast

An image, for what only a picture can show:

xxd output: admin=0 in config.ini changed to admin=1 (offset 0x18), with four bytes ce 1a 39 22 appended at the end; the CRC32 is still 102da2c5

Compiler-style callouts for asides, pitfalls and the bug itself:

And a CTF flag behind a spoiler:

FLAGflag{c0mp0n3nts_3v3rywh3r3}
NORMAL~/components/README.md§--
0%en