package main import ( "bytes" "crypto/rsa" "crypto/x509" "encoding/hex" "fmt" "log" "net" "sync" ) const ( host = `ownme.ipredator.se` // 198.167.222.202 clientPort = `:10002` serverPort = `:10000` ) type Direction int const ( ServerClient Direction = iota ClientServer ) func (d Direction) String() string { switch d { case ServerClient: return "Server → Client" case ClientServer: return "Client → Server" } return "unknown" } type Data struct { Key *rsa.PublicKey Rnd []byte } func (d Data) String() string { s := fmt.Sprintf("N: %v\n", d.Key.N) s += fmt.Sprintf("E: %v\n", d.Key.E) s += fmt.Sprintf("R: %x\n", d.Rnd) return s } var data = make(map[Direction]Data) func (dir Direction) sniffCert(b []byte) error { if i := bytes.Index(b, []byte{0x30, 0x82, 0x04, 0x2f}); i > 0 { cert := b[i : i+1075] crt, err := x509.ParseCertificate(cert) if err != nil { return err } d := data[dir] d.Key = crt.PublicKey.(*rsa.PublicKey) data[dir] = d } return nil } func (dir Direction) sniffRnd(b []byte) error { rnd := b[0x0b:0x2b] fmt.Println(dir, "rnd", len(rnd), "bytes") d := data[dir] d.Rnd = rnd data[dir] = d return nil } // Remove DHE_RSA Chifers in Client Hello // altering any value leads to Handshake Failure after Cert Verify ??? func downgrade(b []byte) int { fmt.Println("downgrade") fmt.Println(hex.Dump(b)) //b[0x0a] -= 2 // TLS 1.0 b[0x04] -= 14 // handshake len b[0x08] -= 14 // hello len b[0x2d] -= 14 // cipher set len copy(b[0x2e:], b[0x2e+14:]) // copy second half over first (7 non dhe ciphers) //copy(b[0x2e+14:], b[0x2e+28:]) // preserve fist half (7 dhe ciphers) return len(b) - 14 } var trydowngrade = false func (dir Direction) sniff(src, dst net.Conn, wg *sync.WaitGroup) { defer wg.Done() buf := make([]byte, 4096) // 1452 for k := 1; ; k++ { n, err := src.Read(buf) if err != nil { dst.Close() return } pkg := buf[:n] if k == 1 { dir.sniffRnd(pkg) if trydowngrade && dir == ClientServer { n = downgrade(pkg) } } fmt.Println(k, dir, n, "bytes") fmt.Println(hex.Dump(pkg)) dir.sniffCert(pkg) _, err = dst.Write(pkg) if err != nil { log.Println(dir, err) return } } } func main() { var wg sync.WaitGroup srv, err := net.Dial("tcp", host+serverPort) if err != nil { log.Fatal(err) } defer srv.Close() cnt, err := net.Dial("tcp", host+clientPort) if err != nil { log.Fatal(err) } defer cnt.Close() wg.Add(2) go ServerClient.sniff(srv, cnt, &wg) go ClientServer.sniff(cnt, srv, &wg) wg.Wait() fmt.Println(ClientServer) fmt.Println(data[ClientServer]) fmt.Println(ServerClient) fmt.Println(data[ServerClient]) }