commit 6c9427bf7b51432e5a5f7bc7c1e478df440d30e3
parent c53dbc278c89a74361f379a21e76fe028686a475
Author: david cochran <about.trout@gmail.com>
Date: Mon, 31 Jan 2022 02:47:41 +0000
add layer3 solution
Diffstat:
| A | cmd/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
+}