From b1cd237a5bdff2e8c31bd7af93bc8718bb4bdee6 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Sat, 17 Jun 2023 11:21:02 +0200 Subject: [PATCH] Adding support for tls impersonate (#126) * Adding support for tls impersonate * fixing gh action * removing types - helpers should be used * running examples * fixing command --- .github/workflows/build-test.yml | 6 +- example/impersonate/main.go | 49 ++++++++++ example/{ => simple}/main.go | 21 ++-- fastdialer/dialer.go | 49 ++++++++-- fastdialer/ja3/error.go | 11 +++ fastdialer/ja3/extmap.go | 62 ++++++++++++ fastdialer/ja3/impersonate/doc.go | 3 + fastdialer/ja3/impersonate/types.go | 20 ++++ fastdialer/ja3/ja3.go | 144 ++++++++++++++++++++++++++++ go.mod | 5 + go.sum | 10 ++ 11 files changed, 359 insertions(+), 21 deletions(-) create mode 100644 example/impersonate/main.go rename example/{ => simple}/main.go (65%) create mode 100644 fastdialer/ja3/error.go create mode 100644 fastdialer/ja3/extmap.go create mode 100644 fastdialer/ja3/impersonate/doc.go create mode 100644 fastdialer/ja3/impersonate/types.go create mode 100644 fastdialer/ja3/ja3.go diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index b0c7698..d96c629 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -22,5 +22,7 @@ jobs: - name: Test run: go test ./... - - name: Build - run: go build example/main.go + - name: Testing Examples + run: | + go run -race example/simple/main.go + go run -race example/impersonate/main.go diff --git a/example/impersonate/main.go b/example/impersonate/main.go new file mode 100644 index 0000000..14359dd --- /dev/null +++ b/example/impersonate/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "context" + "crypto/tls" + "log" + + "github.com/projectdiscovery/fastdialer/fastdialer" + "github.com/projectdiscovery/fastdialer/fastdialer/ja3/impersonate" +) + +func main() { + options := fastdialer.DefaultOptions + + // Create new dialer using NewDialer(opts fastdialer.options) + fd, err := fastdialer.NewDialer(fastdialer.DefaultOptions) + if err != nil { + log.Fatal(err) + } + + // Configure Cache if required + // memory based (also support Hybrid and Disk Cache) + options.CacheType = fastdialer.Memory + options.CacheMemoryMaxItems = 100 + + ctx := context.Background() + + target := "www.projectdiscovery.io" + + conn, err := fd.DialTLSWithConfigImpersonate(ctx, "tcp", target+":443", &tls.Config{InsecureSkipVerify: true}, impersonate.Random, nil) + if err != nil || conn == nil { + log.Fatalf("couldn't connect to target: %s", err) + } + defer conn.Close() + log.Println("connected to the target") + + // To look up Host/ Get DNS details use + data, err := fd.GetDNSData(target) + if err != nil || data == nil { + log.Fatalf("couldn't retrieve dns data: %s", err) + } + + // To Print All Type of DNS Data use + jsonData, err := data.JSON() + if err != nil { + log.Fatalf("failed to marshal json: %s", err) + } + log.Println(jsonData) +} diff --git a/example/main.go b/example/simple/main.go similarity index 65% rename from example/main.go rename to example/simple/main.go index c6d5203..36f8edd 100644 --- a/example/main.go +++ b/example/simple/main.go @@ -9,14 +9,12 @@ import ( ) func main() { - - // refer fastdialer/options.go for options and customization options := fastdialer.DefaultOptions // Create new dialer using NewDialer(opts fastdialer.options) fd, err := fastdialer.NewDialer(fastdialer.DefaultOptions) if err != nil { - panic(err) + log.Fatal(err) } // Configure Cache if required @@ -26,19 +24,17 @@ func main() { ctx := context.Background() - // To dial and create connection use - // To create connection over TLS or older versions use - // fd.DialTLS() or fd.DialZTLS() - conn, err := fd.Dial(ctx, "tcp", "www.projectdiscovery.io:80") + target := "www.projectdiscovery.io" + + conn, err := fd.DialTLS(ctx, "tcp", target+":443") if err != nil || conn == nil { log.Fatalf("couldn't connect to target: %s", err) - } else { - fmt.Println("Connected: TCP stream created with www.projectdiscovery.io:80") } - conn.Close() + defer conn.Close() + log.Println("connected to the target") // To look up Host/ Get DNS details use - data, err := fd.GetDNSData("www.projectdiscovery.io") + data, err := fd.GetDNSData(target) if err != nil || data == nil { log.Fatalf("couldn't retrieve dns data: %s", err) } @@ -48,6 +44,5 @@ func main() { if err != nil { log.Fatalf("failed to marshal json: %s", err) } - fmt.Println(jsonData) - + fmt.Print(jsonData) } diff --git a/fastdialer/dialer.go b/fastdialer/dialer.go index d6abfc6..e4ee283 100644 --- a/fastdialer/dialer.go +++ b/fastdialer/dialer.go @@ -10,11 +10,14 @@ import ( "strings" "time" + "github.com/projectdiscovery/fastdialer/fastdialer/ja3/impersonate" "github.com/projectdiscovery/hmap/store/hybrid" "github.com/projectdiscovery/networkpolicy" retryabledns "github.com/projectdiscovery/retryabledns" cryptoutil "github.com/projectdiscovery/utils/crypto" iputil "github.com/projectdiscovery/utils/ip" + ptrutil "github.com/projectdiscovery/utils/ptr" + utls "github.com/refraction-networking/utls" "github.com/zmap/zcrypto/encoding/asn1" ztls "github.com/zmap/zcrypto/tls" "golang.org/x/net/proxy" @@ -109,7 +112,7 @@ func NewDialer(options Options) (*Dialer, error) { // Dial function compatible with net/http func (d *Dialer) Dial(ctx context.Context, network, address string) (conn net.Conn, err error) { - conn, err = d.dial(ctx, network, address, false, false, nil, nil) + conn, err = d.dial(ctx, network, address, false, false, nil, nil, impersonate.None, nil) return } @@ -130,7 +133,12 @@ func (d *Dialer) DialZTLS(ctx context.Context, network, address string) (conn ne // DialTLS with encrypted connection func (d *Dialer) DialTLSWithConfig(ctx context.Context, network, address string, config *tls.Config) (conn net.Conn, err error) { - conn, err = d.dial(ctx, network, address, true, false, config, nil) + conn, err = d.dial(ctx, network, address, true, false, config, nil, impersonate.None, nil) + return +} + +func (d *Dialer) DialTLSWithConfigImpersonate(ctx context.Context, network, address string, config *tls.Config, impersonate impersonate.Strategy, identity *impersonate.Identity) (conn net.Conn, err error) { + conn, err = d.dial(ctx, network, address, true, false, config, nil, impersonate, identity) return } @@ -141,12 +149,12 @@ func (d *Dialer) DialZTLSWithConfig(ctx context.Context, network, address string if err != nil { return nil, err } - return d.dial(ctx, network, address, true, false, stdTLSConfig, nil) + return d.dial(ctx, network, address, true, false, stdTLSConfig, nil, impersonate.None, nil) } - return d.dial(ctx, network, address, false, true, nil, config) + return d.dial(ctx, network, address, false, true, nil, config, impersonate.None, nil) } -func (d *Dialer) dial(ctx context.Context, network, address string, shouldUseTLS, shouldUseZTLS bool, tlsconfig *tls.Config, ztlsconfig *ztls.Config) (conn net.Conn, err error) { +func (d *Dialer) dial(ctx context.Context, network, address string, shouldUseTLS, shouldUseZTLS bool, tlsconfig *tls.Config, ztlsconfig *ztls.Config, impersonateStrategy impersonate.Strategy, impersonateIdentity *impersonate.Identity) (conn net.Conn, err error) { var hostname, port, fixedIP string if strings.HasPrefix(address, "[") { @@ -225,7 +233,36 @@ func (d *Dialer) dial(ctx context.Context, network, address string, shouldUseTLS case !iputil.IsIP(hostname): tlsconfigCopy.ServerName = hostname } - conn, err = tls.DialWithDialer(d.dialer, network, hostPort, tlsconfigCopy) + if impersonateStrategy == impersonate.None { + conn, err = tls.DialWithDialer(d.dialer, network, hostPort, tlsconfigCopy) + } else { + conn, err := d.dialer.DialContext(ctx, network, hostPort) + if err != nil { + return conn, err + } + // clone existing tls config + uTLSConfig := &utls.Config{ + InsecureSkipVerify: tlsconfigCopy.InsecureSkipVerify, + ServerName: tlsconfigCopy.ServerName, + MinVersion: tlsconfigCopy.MinVersion, + MaxVersion: tlsconfigCopy.MaxVersion, + CipherSuites: tlsconfigCopy.CipherSuites, + } + var uTLSConn *utls.UConn + if impersonateStrategy == impersonate.Random { + uTLSConn = utls.UClient(conn, uTLSConfig, utls.HelloRandomized) + } else if impersonateStrategy == impersonate.Custom { + uTLSConn = utls.UClient(conn, uTLSConfig, utls.HelloCustom) + clientHelloSpec := utls.ClientHelloSpec(ptrutil.Safe(impersonateIdentity)) + if err := uTLSConn.ApplyPreset(&clientHelloSpec); err != nil { + return nil, err + } + } + if err := uTLSConn.Handshake(); err != nil { + return nil, err + } + return uTLSConn, nil + } } else if shouldUseZTLS { ztlsconfigCopy := ztlsconfig.Clone() switch { diff --git a/fastdialer/ja3/error.go b/fastdialer/ja3/error.go new file mode 100644 index 0000000..987267c --- /dev/null +++ b/fastdialer/ja3/error.go @@ -0,0 +1,11 @@ +package ja3 + +import "fmt" + +// ErrExtensionNotExist is returned when an extension is not supported by the library +type ErrExtensionNotExist string + +// Error is the error value which contains the extension that does not exist +func (e ErrExtensionNotExist) Error() string { + return fmt.Sprintf("Extension does not exist: %s\n", string(e)) +} diff --git a/fastdialer/ja3/extmap.go b/fastdialer/ja3/extmap.go new file mode 100644 index 0000000..8e0ad14 --- /dev/null +++ b/fastdialer/ja3/extmap.go @@ -0,0 +1,62 @@ +// ja3 is a package for creating JA3 fingerprints from TLS clients. +// The original extension map and numeric id=>tls extension mapping is from https://github.com/CUCyber +package ja3 + +import ( + utls "github.com/refraction-networking/utls" + "golang.org/x/exp/maps" +) + +// extMap maps extension values to the TLSExtension object associated with the +// number. Some values are not put in here because they must be applied in a +// special way. For example, "10" is the SupportedCurves extension which is also +// used to calculate the JA3 signature. These JA3-dependent values are applied +// after the instantiation of the map. +var defaultExtensionMap = map[string]utls.TLSExtension{ + "0": &utls.SNIExtension{}, + "5": &utls.StatusRequestExtension{}, + // These are applied later + // "10": &tls.SupportedCurvesExtension{...} + // "11": &tls.SupportedPointsExtension{...} + "13": &utls.SignatureAlgorithmsExtension{ + SupportedSignatureAlgorithms: []utls.SignatureScheme{ + utls.ECDSAWithP256AndSHA256, + utls.PSSWithSHA256, + utls.PKCS1WithSHA256, + utls.ECDSAWithP384AndSHA384, + utls.PSSWithSHA384, + utls.PKCS1WithSHA384, + utls.PSSWithSHA512, + utls.PKCS1WithSHA512, + utls.PKCS1WithSHA1, + }, + }, + "16": &utls.ALPNExtension{ + AlpnProtocols: []string{"h2", "http/1.1"}, + }, + "18": &utls.SCTExtension{}, + "21": &utls.UtlsPaddingExtension{GetPaddingLen: utls.BoringPaddingStyle}, + "23": &utls.UtlsExtendedMasterSecretExtension{}, + "28": &utls.FakeRecordSizeLimitExtension{}, + "35": &utls.SessionTicketExtension{}, + "43": &utls.SupportedVersionsExtension{Versions: []uint16{ + utls.GREASE_PLACEHOLDER, + utls.VersionTLS13, + utls.VersionTLS12, + utls.VersionTLS11, + utls.VersionTLS10}}, + "44": &utls.CookieExtension{}, + "45": &utls.PSKKeyExchangeModesExtension{ + Modes: []uint8{ + utls.PskModeDHE, + }}, + "51": &utls.KeyShareExtension{KeyShares: []utls.KeyShare{}}, + "13172": &utls.NPNExtension{}, + "65281": &utls.RenegotiationInfoExtension{ + Renegotiation: utls.RenegotiateOnceAsClient, + }, +} + +func getExtensionMap() map[string]utls.TLSExtension { + return maps.Clone(defaultExtensionMap) +} diff --git a/fastdialer/ja3/impersonate/doc.go b/fastdialer/ja3/impersonate/doc.go new file mode 100644 index 0000000..c9ac8d8 --- /dev/null +++ b/fastdialer/ja3/impersonate/doc.go @@ -0,0 +1,3 @@ +// impersonate package contains strategy to impersonate a client and define an alias for the internal +// client tls spefications +package impersonate diff --git a/fastdialer/ja3/impersonate/types.go b/fastdialer/ja3/impersonate/types.go new file mode 100644 index 0000000..f60920f --- /dev/null +++ b/fastdialer/ja3/impersonate/types.go @@ -0,0 +1,20 @@ +package impersonate + +import ( + utls "github.com/refraction-networking/utls" +) + +// Strategy is the type of strategy to use for impersonation +type Strategy uint8 + +const ( + // None is the default strategy which use the default client hello spec + None Strategy = iota + // Random is the strategy which use a random client hello spec + Random + // JA3 or Raw is the strategy which parses a client hello spec from ja3 full string + Custom +) + +// Identity contains the structured client hello spec +type Identity utls.ClientHelloSpec diff --git a/fastdialer/ja3/ja3.go b/fastdialer/ja3/ja3.go new file mode 100644 index 0000000..ad171c5 --- /dev/null +++ b/fastdialer/ja3/ja3.go @@ -0,0 +1,144 @@ +package ja3 + +import ( + "crypto/sha256" + "errors" + "fmt" + "strconv" + "strings" + + tls "github.com/refraction-networking/utls" + utls "github.com/refraction-networking/utls" +) + +// ParseWithJa3Hash a JA3 string and returns a ClientHelloSpec +// ja3 string format: SSLVersion,CipherSuites,Extensions,SupportedCurves,SupportedPoints +func ParseWithJa3(ja3 string) (*utls.ClientHelloSpec, error) { + ja3tokens := strings.Split(ja3, ",") + if len(ja3tokens) != 5 { + return nil, fmt.Errorf("invalid ja3 string: %s", ja3) + } + + vid, err := parseVersion(ja3tokens[0]) + if err != nil { + return nil, err + } + + cipherSuites, err := parseCipherSuites(ja3tokens[1]) + if err != nil { + return nil, err + } + + extensions, err := parseExtensions(ja3tokens[2]) + if err != nil { + return nil, err + } + + supportedCurves, err := parseSupportedCurves(ja3tokens[3]) + if err != nil { + return nil, err + } + + supportedPoints, err := parseSupportedPoints(ja3tokens[4]) + if err != nil { + return nil, err + } + + extMap := getExtensionMap() + extMap["10"] = &tls.SupportedCurvesExtension{Curves: supportedCurves} + extMap["11"] = &tls.SupportedPointsExtension{SupportedPoints: supportedPoints} + + return &tls.ClientHelloSpec{ + TLSVersMin: vid, + TLSVersMax: vid, + CipherSuites: cipherSuites, + CompressionMethods: []byte{0}, + Extensions: extensions, + GetSessionID: sha256.Sum256, + }, nil +} + +func cleanup(s string) string { + return strings.TrimSpace(s) +} + +func parseVersion(version string) (uint16, error) { + vid64, err := strconv.ParseUint(version, 10, 16) + if err != nil { + return 0, err + } + return uint16(vid64), nil +} + +func parseCipherSuites(cipherToken string) ([]uint16, error) { + cipherToken = cleanup(cipherToken) + if cipherToken == "" { + return nil, errors.New("no cipher suites provided") + } + ciphers := strings.Split(cipherToken, "-") + var cipherSuites []uint16 + for _, cipher := range ciphers { + cid, err := strconv.ParseUint(cipher, 10, 16) + if err != nil { + return nil, err + } + cipherSuites = append(cipherSuites, uint16(cid)) + } + return cipherSuites, nil +} + +func parseExtensions(extensionToken string) ([]tls.TLSExtension, error) { + var extensions []tls.TLSExtension + extensionToken = cleanup(extensionToken) + if extensionToken == "" { + return nil, errors.New("no extensions provided") + } + exts := strings.Split(extensionToken, "-") + for _, ext := range exts { + te, ok := defaultExtensionMap[ext] + if !ok { + return nil, ErrExtensionNotExist(ext) + } + extensions = append(extensions, te) + } + return extensions, nil +} + +func parseSupportedCurves(supportedCurvesToken string) ([]tls.CurveID, error) { + var supportedCurves []tls.CurveID + supportedCurvesToken = cleanup(supportedCurvesToken) + if supportedCurvesToken == "" { + return supportedCurves, nil + } + curves := strings.Split(supportedCurvesToken, "-") + for _, c := range curves { + cid, err := strconv.ParseUint(c, 10, 16) + if err != nil { + return nil, err + } + supportedCurves = append(supportedCurves, tls.CurveID(cid)) + } + return supportedCurves, nil +} + +func parseSupportedPoints(supportedPointsToken string) ([]byte, error) { + var supportedPoints []byte + supportedPointsToken = cleanup(supportedPointsToken) + if supportedPointsToken == "" { + return supportedPoints, nil + } + points := strings.Split(supportedPointsToken, "-") + for _, p := range points { + pid, err := strconv.ParseUint(p, 10, 8) + if err != nil { + return nil, err + } + supportedPoints = append(supportedPoints, byte(pid)) + } + return supportedPoints, nil +} + +func ParseWithRaw(rawClientHello []byte) (*utls.ClientHelloSpec, error) { + fingerprinter := &utls.Fingerprinter{} + return fingerprinter.FingerprintClientHello(rawClientHello) +} diff --git a/go.mod b/go.mod index 9d65aab..1621806 100644 --- a/go.mod +++ b/go.mod @@ -9,20 +9,25 @@ require ( github.com/projectdiscovery/networkpolicy v0.0.6 github.com/projectdiscovery/retryabledns v1.0.29 github.com/projectdiscovery/utils v0.0.37 + github.com/refraction-networking/utls v1.3.2 github.com/stretchr/testify v1.8.4 github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 github.com/zmap/zcrypto v0.0.0-20220803033029-557f3e4940be + golang.org/x/exp v0.0.0-20221019170559-20944726eadf golang.org/x/net v0.10.0 ) require ( github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect github.com/akrylysov/pogreb v0.10.1 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gaukas/godicttls v0.0.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/css v1.0.0 // indirect + github.com/klauspost/compress v1.15.15 // indirect github.com/microcosm-cc/bluemonday v1.0.24 // indirect github.com/miekg/dns v1.1.54 // indirect github.com/nxadm/tail v1.4.8 // indirect diff --git a/go.sum b/go.sum index ab627fd..eeb4440 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb888350 github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809/go.mod h1:upgc3Zs45jBDnBT4tVRgRcgm26ABpaP7MoTSdgysca4= github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w= github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -16,6 +18,8 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk= +github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -26,6 +30,8 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -61,6 +67,8 @@ github.com/projectdiscovery/retryablehttp-go v1.0.17 h1:oppnrypatWsHxcMU5RuAcUsU github.com/projectdiscovery/retryablehttp-go v1.0.17/go.mod h1:zJh8bQdxhIsaEGnxsacvMbgiCKT4UAOr4T1kZBnSa68= github.com/projectdiscovery/utils v0.0.37 h1:axtIvjrguwhwKCBajj3N3MCmetfi4XLUI9UUpEhxtbQ= github.com/projectdiscovery/utils v0.0.37/go.mod h1:sy0CqulJzn95Ro24VQPlDvwxV9yxl8YMoTDYQNxr85U= +github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8= +github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -114,6 +122,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20221019170559-20944726eadf h1:nFVjjKDgNY37+ZSYCJmtYf7tOlfQswHqplG2eosjOMg= +golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=