Notes on a book
Black Hat Go
Tom Steele, Chris Patten, and Dan Kottmann · No Starch Press, 2020
Offensive tooling written from scratch in Go: scanners, proxies, packet handling, cryptography and PNG steganography, all in a language whose standard library does the work in the open.
Go is an odd choice for a security book and the authors are direct about why they made it: the standard library implements the cryptography natively rather than binding to OpenSSL, concurrency is a language feature rather than a library, and the result compiles to one static binary you can drop anywhere. All three matter when the thing you are writing is a one-off tool for one challenge.
Six modules cite it, five of them cryptography modules pointing at the same chapter. That is not padding: implementing a cipher and then attacking your own implementation is the fastest way to stop thinking of ciphers as magic, and this is the only book here that asks you to do it.
Why it is on this shelf
Because a large fraction of CTF work is writing throwaway code - a client that speaks a custom protocol, a script that tries ten thousand keys, a parser for a format nobody documented - and reading somebody competent do exactly that is the fastest way to get good at it. The language is incidental; the habit of writing the tool instead of looking for one is the point. Writing CTF tooling in Go is the local version of that argument.
Chapter 2, TCP, Scanners, and Proxies
Starts with the handshake, drawn out for all three cases: syn then syn-ack then ack for an open port, syn then rst for a closed one, and silence when a firewall is dropping it. Those three outcomes are the whole of port scanning, and the chapter builds a scanner from them, then adds concurrency with a worker pool, then builds a TCP proxy.
The proxy is the part with the most CTF value. A challenge that gives you a client and a server and asks you to interfere is asking for a proxy, and one that logs both directions to a file will teach you the protocol while you sit there. The distinction between closed and filtered also survives everywhere - in a misc challenge, a timeout and a refusal mean different things.
Chapter 11, Implementing and Attacking Cryptography
Cited by five modules, and the one chapter here that treats implementing and attacking as the same activity. It walks hashing, message authentication, symmetric and asymmetric encryption through Go's standard library, and finishes by brute-forcing an RC2 ciphertext.
What makes it work is that Go's crypto packages are readable. When you call the block cipher interface you can see that a mode is a wrapper around a block function, that a stream cipher is a keystream generator plus XOR, and that a MAC is a hash with a key mixed in twice. Once you have seen that, several attack classes stop being tricks and become obvious consequences: XOR key reuse is what a stream cipher does when you reuse the keystream, ECB pattern leakage is what happens when the wrapper does not chain, and length extension is what a Merkle-Damgard hash does when you mistake it for a signature.
The brute-force finale is the honest ending: the attack that works on a weak algorithm is not clever, it is a loop. Knowing which algorithms deserve a loop is what the identification step is for.
Chapter 13, Hiding Data with Steganography
A complete tour of the PNG container, motivated by hiding data in it, which means it is also a complete tour of how to find data hidden in it. The eight-byte magic header, then chunks all the way down, each one four bytes of size, four of type, the data, and a CRC-32 over the type and data together. IHDR carries the metadata, IDAT carries the pixels, IEND terminates the stream.
That structure is why PNG stego challenges are so tractable. A chunk with a type nobody recognises is still a legal chunk and decoders skip it, so arbitrary data survives in plain sight. A CRC that does not match its chunk is a fingerprint of tampering. Data after IEND is not part of the image at all. All three are things the PNG chunk analyzer checks for you, and the stego workflow is the order to check them in.
The chapter injects into chunks rather than pixels, which is worth noting: this is container steganography, not least-significant-bit steganography. For the pixel case use the LSB tool. Knowing which of the two you are looking at is most of the battle.
Where it stops
It is a Go book first. If you do not want to write Go, roughly half of every chapter is not for you, and the material is thinner than a dedicated treatment would be - the crypto chapter is an implementation tour rather than a course, and the steganography chapter covers one container.
It is also aimed at red-team tooling, so the last chapters build command-and-control infrastructure, which is out of scope here. Nothing in it is about analysing somebody else's artefact, which is what most challenges actually ask for.
What to take into a challenge
Write the client. When a challenge involves a service that speaks something custom, thirty lines that open a socket and speak it will outrun any amount of clicking, and once written you can loop it. The same instinct applies to formats: a parser you wrote is a parser you can make deliberately wrong, which is how you find out what the other end tolerates.