diff --git a/internal/client/chrome.go b/internal/client/chrome.go index 042c6f0..067473c 100644 --- a/internal/client/chrome.go +++ b/internal/client/chrome.go @@ -1,4 +1,4 @@ -// Fingerprint of Chrome 97 +// Fingerprint of Chrome 99 package client @@ -46,7 +46,7 @@ func (c *Chrome) composeExtensions(serverName string, keyShare []byte) []byte { // extension length is always 403, and server name length is variable - var ext [17][]byte + var ext [18][]byte ext[0] = addExtRec(makeGREASE(), nil) // First GREASE ext[1] = addExtRec([]byte{0x00, 0x00}, generateSNI(serverName)) // server name indication ext[2] = addExtRec([]byte{0x00, 0x17}, nil) // extended_master_secret @@ -62,16 +62,18 @@ func (c *Chrome) composeExtensions(serverName string, keyShare []byte) []byte { ext[10] = addExtRec([]byte{0x00, 0x12}, nil) // signed cert timestamp ext[11] = addExtRec([]byte{0x00, 0x33}, makeKeyShare(keyShare)) // key share ext[12] = addExtRec([]byte{0x00, 0x2d}, []byte{0x01, 0x01}) // psk key exchange modes - suppVersions, _ := hex.DecodeString("0a9A9A0304030303020301") // 9A9A needs to be a GREASE + suppVersions, _ := hex.DecodeString("069A9A03040303") // 9A9A needs to be a GREASE copy(suppVersions[1:3], makeGREASE()) ext[13] = addExtRec([]byte{0x00, 0x2b}, suppVersions) // supported versions ext[14] = addExtRec([]byte{0x00, 0x1b}, []byte{0x02, 0x00, 0x02}) // compress certificate - ext[15] = addExtRec(makeGREASE(), []byte{0x00}) // Last GREASE - // len(ext[1]) + 170 + len(ext[16]) = 403 - // len(ext[16]) = 233 - len(ext[1]) - // 2+2+len(padding) = 233 - len(ext[1]) - // len(padding) = 229 - len(ext[1]) - ext[16] = addExtRec([]byte{0x00, 0x15}, make([]byte, 229-len(ext[1]))) // padding + applicationSettings, _ := hex.DecodeString("0003026832") + ext[15] = addExtRec([]byte{0x44, 0x69}, applicationSettings) // application settings + ext[16] = addExtRec(makeGREASE(), []byte{0x00}) // Last GREASE + // len(ext[1]) + 175 + len(ext[16]) = 403 + // len(ext[16]) = 228 - len(ext[1]) + // 2+2+len(padding) = 228 - len(ext[1]) + // len(padding) = 224 - len(ext[1]) + ext[17] = addExtRec([]byte{0x00, 0x15}, make([]byte, 224-len(ext[1]))) // padding var ret []byte for _, e := range ext { ret = append(ret, e...) diff --git a/internal/client/chrome_test.go b/internal/client/chrome_test.go index 629e23c..b147078 100644 --- a/internal/client/chrome_test.go +++ b/internal/client/chrome_test.go @@ -31,7 +31,7 @@ func TestComposeExtension(t *testing.T) { keyShare, _ := hex.DecodeString("690f074f5c01756982269b66d58c90c47dc0f281d654c7b2c16f63c9033f5604") result := (&Chrome{}).composeExtensions(serverName, keyShare) - target, _ := hex.DecodeString("8a8a00000000000f000d00000a6769746875622e636f6d00170000ff01000100000a000a00088a8a001d00170018000b00020100002300000010000e000c02683208687474702f312e31000500050100000000000d0012001004030804040105030805050108060601001200000033002b00298a8a000100001d0020690f074f5c01756982269b66d58c90c47dc0f281d654c7b2c16f63c9033f5604002d00020101002b000b0a3a3a0304030303020301001b00030200024a4a000100001500d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + target, _ := hex.DecodeString("3a3a00000000000f000d00000a6769746875622e636f6d00170000ff01000100000a000a00080a0a001d00170018000b00020100002300000010000e000c02683208687474702f312e31000500050100000000000d0012001004030804040105030805050108060601001200000033002b00296a6a000100001d0020690f074f5c01756982269b66d58c90c47dc0f281d654c7b2c16f63c9033f5604002d00020101002b000706dada03040303001b0003020002446900050003026832eaea000100001500cd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") for p := 0; p < len(result); p++ { if result[p] != target[p] { if result[p]&0x0F == 0xA && target[p]&0x0F == 0xA && diff --git a/internal/client/firefox.go b/internal/client/firefox.go index 10c48b6..a7862cc 100644 --- a/internal/client/firefox.go +++ b/internal/client/firefox.go @@ -1,4 +1,4 @@ -// Fingerprint of Firefox 96 +// Fingerprint of Firefox 99 package client @@ -22,26 +22,30 @@ func (f *Firefox) composeExtensions(serverName string, keyShare []byte) []byte { common.CryptoRandRead(ret[42:107]) return ret } - // extension length is always 399, and server name length is variable - var ext [12][]byte + // extension length is always 401, and server name length is variable + var ext [15][]byte ext[0] = addExtRec([]byte{0x00, 0x00}, generateSNI(serverName)) // server name indication ext[1] = addExtRec([]byte{0x00, 0x17}, nil) // extended_master_secret ext[2] = addExtRec([]byte{0xff, 0x01}, []byte{0x00}) // renegotiation_info suppGroup, _ := hex.DecodeString("000c001d00170018001901000101") ext[3] = addExtRec([]byte{0x00, 0x0a}, suppGroup) // supported groups ext[4] = addExtRec([]byte{0x00, 0x0b}, []byte{0x01, 0x00}) // ec point formats + ext[5] = addExtRec([]byte{0x00, 0x23}, nil) // session ticket ALPN, _ := hex.DecodeString("000c02683208687474702f312e31") - ext[5] = addExtRec([]byte{0x00, 0x10}, ALPN) // app layer proto negotiation - ext[6] = addExtRec([]byte{0x00, 0x05}, []byte{0x01, 0x00, 0x00, 0x00, 0x00}) // status request - ext[7] = addExtRec([]byte{0x00, 0x33}, composeKeyShare(keyShare)) // key share - suppVersions, _ := hex.DecodeString("080304030303020301") - ext[8] = addExtRec([]byte{0x00, 0x2b}, suppVersions) // supported versions + ext[6] = addExtRec([]byte{0x00, 0x10}, ALPN) // app layer proto negotiation + ext[7] = addExtRec([]byte{0x00, 0x05}, []byte{0x01, 0x00, 0x00, 0x00, 0x00}) // status request + delegatedCredentials, _ := hex.DecodeString("00080403050306030203") + ext[8] = addExtRec([]byte{0x00, 0x22}, delegatedCredentials) // delegated credentials + ext[9] = addExtRec([]byte{0x00, 0x33}, composeKeyShare(keyShare)) // key share + suppVersions, _ := hex.DecodeString("0403040303") + ext[10] = addExtRec([]byte{0x00, 0x2b}, suppVersions) // supported versions sigAlgo, _ := hex.DecodeString("001604030503060308040805080604010501060102030201") - ext[9] = addExtRec([]byte{0x00, 0x0d}, sigAlgo) // Signature Algorithms - ext[10] = addExtRec([]byte{0x00, 0x1c}, []byte{0x40, 0x01}) // record size limit - // len(ext[0]) + 218 + 4 + len(padding) = 399 + ext[11] = addExtRec([]byte{0x00, 0x0d}, sigAlgo) // Signature Algorithms + ext[12] = addExtRec([]byte{0x00, 0x2d}, []byte{0x01, 0x01}) // psk key exchange modes + ext[13] = addExtRec([]byte{0x00, 0x1c}, []byte{0x40, 0x01}) // record size limit + // len(ext[0]) + 238 + 4 + len(padding) = 401 // len(padding) = 177 - len(ext[0]) - ext[11] = addExtRec([]byte{0x00, 0x15}, make([]byte, 177-len(ext[0]))) // padding + ext[14] = addExtRec([]byte{0x00, 0x15}, make([]byte, 159-len(ext[0]))) // padding var ret []byte for _, e := range ext { ret = append(ret, e...) @@ -57,8 +61,8 @@ func (f *Firefox) composeClientHello(hd clientHelloFields) (ch []byte) { clientHello[3] = hd.random // random clientHello[4] = []byte{0x20} // session id length 32 clientHello[5] = hd.sessionId // session id - clientHello[6] = []byte{0x00, 0x24} // cipher suites length 36 - cipherSuites, _ := hex.DecodeString("130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035000a") + clientHello[6] = []byte{0x00, 0x22} // cipher suites length 34 + cipherSuites, _ := hex.DecodeString("130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035") clientHello[7] = cipherSuites // cipher suites clientHello[8] = []byte{0x01} // compression methods length 1 clientHello[9] = []byte{0x00} // compression methods diff --git a/internal/client/firefox_test.go b/internal/client/firefox_test.go index 6b6a338..20ae821 100644 --- a/internal/client/firefox_test.go +++ b/internal/client/firefox_test.go @@ -7,14 +7,14 @@ import ( ) func TestComposeExtensions(t *testing.T) { - target, _ := hex.DecodeString("000000170015000012636f6e73656e742e676f6f676c652e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b000201000010000e000c02683208687474702f312e310005000501000000000033006b0069001d00208d8ea1b80430b7710b65f0d89b0144a5eeb218709ce6613d4fc8bfb117657c150017004104bcffff92fc5a5aa656a04342cef647cf59a365678743ec64409a1444360c58b552c92ee6d0aad8573d1b8ca91a160e28de18bf9b46f8950c50957f606e04a970002b0009080304030303020301000d0018001604030503060308040805080604010501060102030201001c0002400100150096000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + target, _ := hex.DecodeString("000000170015000012636f6e73656e742e676f6f676c652e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b00020100002300000010000e000c02683208687474702f312e310005000501000000000022000a000804030503060302030033006b0069001d00208d8ea1b80430b7710b65f0d89b0144a5eeb218709ce6613d4fc8bfb117657c1500170041947458330e3553dcde0a8741eb1dde26ebaee8262029c5edb3cbacc9ee1d7c866085b9cf483d943248997a65c5fa1d35725213895d0e5569d4e291863061b7d075002b00050403040303000d0018001604030503060308040805080604010501060102030201002d00020101001c0002400100150084000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") serverName := "consent.google.com" keyShare, _ := hex.DecodeString("8d8ea1b80430b7710b65f0d89b0144a5eeb218709ce6613d4fc8bfb117657c15") result := (&Firefox{}).composeExtensions(serverName, keyShare) // skip random secp256r1 - if !bytes.Equal(result[:133], target[:133]) || !bytes.Equal(result[198:], target[198:]) { + if !bytes.Equal(result[:151], target[:151]) || !bytes.Equal(result[216:], target[216:]) { t.Errorf("got %x", result) } }