tdo

Dicing the onion
git clone git@abtrout.com:tdo.git
Log | Files | Refs | README

commit 6c9427bf7b51432e5a5f7bc7c1e478df440d30e3
parent c53dbc278c89a74361f379a21e76fe028686a475
Author: david cochran <about.trout@gmail.com>
Date:   Mon, 31 Jan 2022 02:47:41 +0000

add layer3 solution

Diffstat:
Acmd/layer3/decode.go | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+), 0 deletions(-)

diff --git a/cmd/layer3/decode.go b/cmd/layer3/decode.go @@ -0,0 +1,80 @@ +package main + +import ( + "log" + "os" + + "github.com/abtrout/tdo" +) + +func main() { + bs, err := tdo.DecodePipedInput() + if err != nil { + log.Fatalf("Failed to read layer input: %v", err) + } + + /* + // The key is 32 bits, and the plaintext is presumably a layer input. + // Hence we know how it will start. + key := make([]byte, 32) + knownPrefix := "==[ Layer 4/6: " + for i, b := range knownPrefix { + key[i] ^= bs[i] ^ byte(b) + } + + // Bruteforce the rest of the key. We'll operate on the first + // 320 characters, since the plaintext also contains an ASCII85 + // encoded payload which will mess up the frequencies. + search := bs[:320] + for i := len(knownPrefix); i < len(key); i++ { + var cand byte + var rank int + for j := 0; j < 256; j++ { + if gr := rankGuess(byte(j), i, search); gr > rank { + cand = byte(j) + rank = gr + log.Printf("Updated best guess %d with rank %d", j, gr) + } else { + log.Printf("Skipping %d", j) + } + } + key[i] = cand + log.Println("Key %d: candidate %d, rank %d", i, cand, rank) + } + */ + + // MANUAL OVERRIDE::: After bruteforcing, I am hand tweaking the key + // based on the prefix I see in the decoded data. My guesses weren't + // perfect, but they were close! + key := make([]byte, 32) + prefix := "==[ Layer 4/6: Network Traffic ]" + for i, b := range prefix { + key[i] ^= bs[i] ^ byte(b) + } + out := repeatingKeyXOR(key, bs) + + if _, err := os.Stdout.Write(out); err != nil { + log.Fatalf("Failed to write decoded output: %v", err) + } +} + +/* +const freqs = "ULDRHS NIOATEuldrhs nioate" + +func rankGuess(k byte, idx int, bs []byte) int { + var rank int + for i := 0; i < len(bs)/32; i++ { + b := bs[idx+(32*i)] + rank += 1 + strings.IndexByte(freqs, b^k) + } + return rank +} +*/ + +func repeatingKeyXOR(key, ct []byte) []byte { + res := make([]byte, len(ct)) + for i, b := range ct { + res[i] = b ^ key[i%len(key)] + } + return res +}