Skip to content

Commit

Permalink
Add new ClientHellos
Browse files Browse the repository at this point in the history
Also add faked support for token binding, ALPS, and delegated credentials
  • Loading branch information
hwh33 committed Oct 8, 2022
1 parent f781b69 commit b702e96
Show file tree
Hide file tree
Showing 4 changed files with 1,042 additions and 10 deletions.
44 changes: 40 additions & 4 deletions u_common.go
Expand Up @@ -23,7 +23,11 @@ const (
utlsExtensionCompressCertificate uint16 = 27

// extensions with 'fake' prefix break connection, if server echoes them back
fakeExtensionChannelID uint16 = 30032 // not IANA assigned
fakeExtensionTokenBinding uint16 = 24
fakeExtensionChannelIDOld uint16 = 30031 // not IANA assigned
fakeExtensionChannelID uint16 = 30032 // not IANA assigned
fakeExtensionALPS uint16 = 17513 // not IANA assigned
fakeExtensionDelegatedCredentials uint16 = 34

fakeRecordSizeLimit uint16 = 0x001c

Expand All @@ -44,16 +48,25 @@ const (

FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = uint16(0x0033)
FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = uint16(0x0039)
FAKE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = uint16(0x009f)
FAKE_TLS_RSA_WITH_RC4_128_MD5 = uint16(0x0004)
FAKE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = uint16(0x009f)
FAKE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = uint16(0x0032)
FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = uint16(0x006b)
FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = uint16(0x0067)
FAKE_TLS_EMPTY_RENEGOTIATION_INFO_SCSV = uint16(0x00ff)

// https://docs.microsoft.com/en-us/dotnet/api/system.net.security.tlsciphersuite?view=netcore-3.1
FAKE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = uint16(0xc008)
)

// newest signatures
var (
FakePKCS1WithSHA224 SignatureScheme = 0x0301
FakeECDSAWithSHA224 SignatureScheme = 0x0303

FakeSHA1WithDSA SignatureScheme = 0x0202
FakeSHA256WithDSA SignatureScheme = 0x0402

// fakeEd25519 = SignatureAndHash{0x08, 0x07}
// fakeEd448 = SignatureAndHash{0x08, 0x08}
)
Expand Down Expand Up @@ -109,6 +122,11 @@ const (
helloChrome = "Chrome"
helloIOS = "iOS"
helloAndroid = "Android"
helloEdge = "Edge"
helloExplorer = "InternetExplorer"
helloSafari = "Safari"
hello360 = "360Browser"
helloQQ = "QQBrowser"

// versions
helloAutoVers = "0"
Expand Down Expand Up @@ -146,15 +164,16 @@ var (
HelloRandomizedNoALPN = ClientHelloID{helloRandomizedNoALPN, helloAutoVers, nil}

// The rest will will parrot given browser.
HelloFirefox_Auto = HelloFirefox_102
HelloFirefox_Auto = HelloFirefox_105
HelloFirefox_55 = ClientHelloID{helloFirefox, "55", nil}
HelloFirefox_56 = ClientHelloID{helloFirefox, "56", nil}
HelloFirefox_63 = ClientHelloID{helloFirefox, "63", nil}
HelloFirefox_65 = ClientHelloID{helloFirefox, "65", nil}
HelloFirefox_99 = ClientHelloID{helloFirefox, "99", nil}
HelloFirefox_102 = ClientHelloID{helloFirefox, "102", nil}
HelloFirefox_105 = ClientHelloID{helloFirefox, "105", nil}

HelloChrome_Auto = HelloChrome_102
HelloChrome_Auto = HelloChrome_106
HelloChrome_58 = ClientHelloID{helloChrome, "58", nil}
HelloChrome_62 = ClientHelloID{helloChrome, "62", nil}
HelloChrome_70 = ClientHelloID{helloChrome, "70", nil}
Expand All @@ -164,6 +183,7 @@ var (
HelloChrome_96 = ClientHelloID{helloChrome, "96", nil}
HelloChrome_100 = ClientHelloID{helloChrome, "100", nil}
HelloChrome_102 = ClientHelloID{helloChrome, "102", nil}
HelloChrome_106 = ClientHelloID{helloChrome, "106", nil}

HelloIOS_Auto = HelloIOS_14
HelloIOS_11_1 = ClientHelloID{helloIOS, "111", nil} // legacy "111" means 11.1
Expand All @@ -172,6 +192,22 @@ var (
HelloIOS_14 = ClientHelloID{helloIOS, "14", nil}

HelloAndroid_11_OkHttp = ClientHelloID{helloAndroid, "11", nil}

HelloEdge_Auto = HelloEdge_85 // HelloEdge_106 seems to be incompatible with this library
HelloEdge_85 = ClientHelloID{helloEdge, "85", nil}
HelloEdge_106 = ClientHelloID{helloEdge, "106", nil}

HelloExplorer_11 = ClientHelloID{helloExplorer, "11", nil}

HelloSafari_Auto = HelloSafari_16_0
HelloSafari_16_0 = ClientHelloID{helloSafari, "16.0", nil}

Hello360_Auto = Hello360_7_5 // Hello360_11_0 seems to be incompatible with this library
Hello360_7_5 = ClientHelloID{hello360, "7.5", nil}
Hello360_11_0 = ClientHelloID{hello360, "11.0", nil}

HelloQQ_Auto = HelloQQ_11_1
HelloQQ_11_1 = ClientHelloID{helloQQ, "11.1", nil}
)

// based on spec's GreaseStyle, GREASE_PLACEHOLDER may be replaced by another GREASE value
Expand Down
61 changes: 58 additions & 3 deletions u_fingerprinter.go
Expand Up @@ -318,8 +318,63 @@ func (f *Fingerprinter) FingerprintClientHello(data []byte) (*ClientHelloSpec, e
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &UtlsCompressCertExtension{methods})

case fakeExtensionChannelID, fakeRecordSizeLimit:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &GenericExtension{extension, extData})
case fakeExtensionChannelID:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeChannelIDExtension{})

case fakeExtensionChannelIDOld:
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeChannelIDExtension{true})

case fakeExtensionTokenBinding:
var tokenBindingExt FakeTokenBindingExtension
var keyParameters cryptobyte.String
if !extData.ReadUint8(&tokenBindingExt.MajorVersion) ||
!extData.ReadUint8(&tokenBindingExt.MinorVersion) ||
!extData.ReadUint8LengthPrefixed(&keyParameters) {
return nil, errors.New("unable to read token binding extension data")
}
tokenBindingExt.KeyParameters = keyParameters
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &tokenBindingExt)

case fakeExtensionALPS:
// Similar to ALPN (RFC 7301, Section 3.1):
// https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps#section-3
var protoList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
return nil, errors.New("unable to read ALPS extension data")
}
supportedProtocols := []string{}
for !protoList.Empty() {
var proto cryptobyte.String
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
return nil, errors.New("unable to read ALPS extension data")
}
supportedProtocols = append(supportedProtocols, string(proto))
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeALPSExtension{supportedProtocols})

case fakeRecordSizeLimit:
recordSizeExt := new(FakeRecordSizeLimitExtension)
if !extData.ReadUint16(&recordSizeExt.Limit) {
return nil, errors.New("unable to read record size limit extension data")
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, recordSizeExt)

case fakeExtensionDelegatedCredentials:
//https://datatracker.ietf.org/doc/html/draft-ietf-tls-subcerts-15#section-4.1.1
var supportedAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&supportedAlgs) || supportedAlgs.Empty() {
return nil, errors.New("unable to read signature algorithms extension data")
}
supportedSignatureAlgorithms := []SignatureScheme{}
for !supportedAlgs.Empty() {
var sigAndAlg uint16
if !supportedAlgs.ReadUint16(&sigAndAlg) {
return nil, errors.New("unable to read signature algorithms extension data")
}
supportedSignatureAlgorithms = append(
supportedSignatureAlgorithms, SignatureScheme(sigAndAlg))
}
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &FakeDelegatedCredentialsExtension{supportedSignatureAlgorithms})

case extensionPreSharedKey:
// RFC 8446, Section 4.2.11
Expand Down Expand Up @@ -351,7 +406,7 @@ func (f *Fingerprinter) FingerprintClientHello(data []byte) (*ClientHelloSpec, e
} else if f.AllowBluntMimicry {
clientHelloSpec.Extensions = append(clientHelloSpec.Extensions, &GenericExtension{extension, extData})
} else {
return nil, fmt.Errorf("unsupported extension %#x", extension)
return nil, fmt.Errorf("unsupported extension %d", extension)
}

continue
Expand Down

0 comments on commit b702e96

Please sign in to comment.