Skip to content

Instantly share code, notes, and snippets.

@justhyped
Created April 21, 2024 12:59
Show Gist options
  • Save justhyped/8ad4a5dbd32387ac6dda1c78c67a5ad9 to your computer and use it in GitHub Desktop.
Save justhyped/8ad4a5dbd32387ac6dda1c78c67a5ad9 to your computer and use it in GitHub Desktop.
This script shows how to solve Akamai's Crypto Challenge using the Hyper Solutions SDK
package main
import (
"errors"
"fmt"
"github.com/Hyper-Solutions/hyper-sdk-go/akamai"
customHttp "github.com/bogdanfinn/fhttp"
tls_client "github.com/bogdanfinn/tls-client"
"github.com/bogdanfinn/tls-client/profiles"
"io"
"net/url"
"strings"
)
const (
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
clientHints = `"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"`
)
func main() {
client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(),
tls_client.WithClientProfile(profiles.Chrome_120),
tls_client.WithCharlesProxy("", ""),
tls_client.WithNotFollowRedirects(),
tls_client.WithCookieJar(tls_client.NewCookieJar()),
tls_client.WithTimeoutSeconds(10),
tls_client.WithRandomTLSExtensionOrder(),
)
if err != nil {
panic(err)
}
challenge := &Challenge{
pageUrl: "https://www.similarweb.com/website/google.com",
client: client,
}
if err := challenge.solveSecCpt(); err != nil {
panic(err)
}
}
type Challenge struct {
client tls_client.HttpClient
challenge *akamai.SecCptChallenge
pageUrl string
baseUrl string
}
func (c *Challenge) solveSecCpt() error {
if err := c.makeInitialRequest(); err != nil {
return err
}
c.challenge.Sleep()
if err := c.postPow(); err != nil {
return err
}
if err := c.verifyChallenge(); err != nil {
return err
}
if sec := c.getCookie("sec_cpt"); !strings.Contains(sec, "~3~") {
return errors.New("invalid sec_cpt cookie returned")
}
return nil
}
func (c *Challenge) makeInitialRequest() error {
req, err := customHttp.NewRequest("GET", c.pageUrl, nil)
if err != nil {
return err
}
req.Header = customHttp.Header{
"sec-ch-ua": {clientHints},
"sec-ch-ua-mobile": {"?0"},
"sec-ch-ua-platform": {`"Windows"`},
"upgrade-insecure-requests": {"1"},
"user-agent": {userAgent},
"accept": {"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},
"sec-fetch-site": {"none"},
"sec-fetch-mode": {"navigate"},
"sec-fetch-user": {"?1"},
"sec-fetch-dest": {"document"},
"accept-encoding": {"gzip, deflate, br"},
"accept-language": {"en-US,en;q=0.9"},
customHttp.HeaderOrderKey: {"sec-ch-ua", "sec-ch-ua-mobile", "sec-ch-ua-platform", "upgrade-insecure-requests", "user-agent", "accept", "sec-fetch-site", "sec-fetch-mode", "sec-fetch-user", "sec-fetch-dest", "accept-encoding", "accept-language"},
customHttp.PHeaderOrderKey: {":method", ":authority", ":scheme", ":path"},
}
response, err := c.client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
uri, err := url.Parse(c.pageUrl)
if err != nil {
return err
}
c.baseUrl = fmt.Sprintf("%s://%s", uri.Scheme, uri.Host)
challenge, err := akamai.ParseSecCptChallenge(response.Body)
if err != nil {
return err
}
c.challenge = challenge
return nil
}
func (c *Challenge) postPow() error {
payload, err := c.challenge.GenerateSecCptPayload(c.getCookie("sec_cpt"))
if err != nil {
return err
}
req, err := customHttp.NewRequest("POST", fmt.Sprintf("%s/_sec/verify?provider=crypto", c.baseUrl), strings.NewReader(string(payload)))
if err != nil {
return err
}
req.Header = customHttp.Header{
"sec-ch-ua": {clientHints},
"sec-ch-ua-platform": {`"Windows"`},
"sec-ch-ua-mobile": {"?0"},
"user-agent": {userAgent},
"content-type": {"text/plain;charset=UTF-8"},
"accept": {"*/*"},
"origin": {c.baseUrl},
"sec-fetch-site": {"same-origin"},
"sec-fetch-mode": {"cors"},
"sec-fetch-dest": {"empty"},
"referer": {fmt.Sprintf("%s%s", c.baseUrl, c.challenge.ChallengePath)},
"accept-encoding": {"gzip, deflate, br, zstd"},
"accept-language": {"en-US,en;q=0.9"},
customHttp.HeaderOrderKey: {"content-length", "sec-ch-ua", "sec-ch-ua-platform", "sec-ch-ua-mobile", "user-agent", "content-type", "accept", "origin", "sec-fetch-site", "sec-fetch-mode", "sec-fetch-dest", "referer", "accept-encoding", "accept-language", "cookie"},
customHttp.PHeaderOrderKey: {":method", ":authority", ":scheme", ":path"},
}
resp, err := c.client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
return err
}
return nil
}
func (c *Challenge) verifyChallenge() error {
req, err := customHttp.NewRequest("GET", fmt.Sprintf("%s/_sec/cp_challenge/verify", c.baseUrl), nil)
if err != nil {
return err
}
req.Header = customHttp.Header{
"user-agent": {userAgent},
"accept": {"*/*"},
"sec-gpc": {"1"},
"sec-fetch-site": {"same-origin"},
"sec-fetch-mode": {"cors"},
"sec-fetch-dest": {"empty"},
"referer": {c.pageUrl},
"accept-encoding": {"gzip, deflate, br"},
"accept-language": {"en-US,en;q=0.9"},
customHttp.HeaderOrderKey: {"user-agent", "accept", "sec-gpc", "sec-fetch-site", "sec-fetch-mode", "sec-fetch-dest", "referer", "accept-encoding", "accept-language", "cookie"},
customHttp.PHeaderOrderKey: {":method", ":authority", ":scheme", ":path"},
}
response, err := c.client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
if _, err := io.Copy(io.Discard, response.Body); err != nil {
return err
}
return nil
}
func (c *Challenge) getCookie(cookieName string) string {
uri, _ := url.Parse(c.pageUrl)
cookies := c.client.GetCookies(uri)
for _, v := range cookies {
if v.Name == cookieName {
return v.Value
}
}
return ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment