tdo

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

decode.go (1880B)


      1 package main
      2 
      3 import (
      4 	"log"
      5 	"os"
      6 
      7 	"github.com/abtrout/tdo"
      8 )
      9 
     10 func main() {
     11 	bs, err := tdo.DecodePipedInput()
     12 	if err != nil {
     13 		log.Fatalf("Failed to read layer input: %v", err)
     14 	}
     15 
     16 	/*
     17 		// The key is 32 bits, and the plaintext is presumably a layer input.
     18 		// Hence we know how it will start.
     19 		key := make([]byte, 32)
     20 		knownPrefix := "==[ Layer 4/6: "
     21 		for i, b := range knownPrefix {
     22 			key[i] ^= bs[i] ^ byte(b)
     23 		}
     24 
     25 		// Bruteforce the rest of the key. We'll operate on the first
     26 		// 320 characters, since the plaintext also contains an ASCII85
     27 		// encoded payload which will mess up the frequencies.
     28 		search := bs[:320]
     29 		for i := len(knownPrefix); i < len(key); i++ {
     30 			var cand byte
     31 			var rank int
     32 			for j := 0; j < 256; j++ {
     33 				if gr := rankGuess(byte(j), i, search); gr > rank {
     34 					cand = byte(j)
     35 					rank = gr
     36 					log.Printf("Updated best guess %d with rank %d", j, gr)
     37 				} else {
     38 					log.Printf("Skipping %d", j)
     39 				}
     40 			}
     41 			key[i] = cand
     42 			log.Println("Key %d: candidate %d, rank %d", i, cand, rank)
     43 		}
     44 	*/
     45 
     46 	// MANUAL OVERRIDE::: After bruteforcing, I am hand tweaking the key
     47 	// based on the prefix I see in the decoded data. My guesses weren't
     48 	// perfect, but they were close!
     49 	key := make([]byte, 32)
     50 	prefix := "==[ Layer 4/6: Network Traffic ]"
     51 	for i, b := range prefix {
     52 		key[i] ^= bs[i] ^ byte(b)
     53 	}
     54 	out := repeatingKeyXOR(key, bs)
     55 
     56 	if _, err := os.Stdout.Write(out); err != nil {
     57 		log.Fatalf("Failed to write decoded output: %v", err)
     58 	}
     59 }
     60 
     61 /*
     62 const freqs = "ULDRHS NIOATEuldrhs nioate"
     63 
     64 func rankGuess(k byte, idx int, bs []byte) int {
     65 	var rank int
     66 	for i := 0; i < len(bs)/32; i++ {
     67 		b := bs[idx+(32*i)]
     68 		rank += 1 + strings.IndexByte(freqs, b^k)
     69 	}
     70 	return rank
     71 }
     72 */
     73 
     74 func repeatingKeyXOR(key, ct []byte) []byte {
     75 	res := make([]byte, len(ct))
     76 	for i, b := range ct {
     77 		res[i] = b ^ key[i%len(key)]
     78 	}
     79 	return res
     80 }