fix: aliyun tvtoken connector

This commit is contained in:
DDSRem
2024-08-22 21:45:49 +08:00
parent e501230749
commit 0576fa44ac
6 changed files with 112 additions and 151 deletions
+14 -8
View File
@@ -1,15 +1,21 @@
FROM golang:1.22-alpine3.20 as builder
FROM python:3.12-alpine3.20
WORKDIR /app/
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY . .
RUN go build
FROM alpine:3.20
COPY --from=builder --chmod=755 /app/aliyuntvtoken_connector /aliyuntvtoken_connector
RUN set -ex && \
apk add --no-cache \
bash \
tzdata && \
python3 -m pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r /app/requirements.txt && \
rm -rf \
/root/.cache \
/tmp/*
EXPOSE 34278
ENTRYPOINT ["/aliyuntvtoken_connector"]
ENTRYPOINT [ "python3", "/app/main.py" ]
-9
View File
@@ -1,9 +0,0 @@
module aliyuntvtoken_connector
go 1.22
require (
github.com/tidwall/gjson v1.17.3
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
)
-26
View File
@@ -1,26 +0,0 @@
github.com/cossacklabs/acra v0.0.0-20240710145658-5ce84537e918 h1:qB2I/aGWRmaoZ4kFdn2+BKhlGcL5mFRTmN9fBynj+NI=
github.com/cossacklabs/acra v0.0.0-20240710145658-5ce84537e918/go.mod h1:x514dvzz+Gyq3u7G4C/aZgamU3ryUj78iVhmIUxdkMs=
github.com/cossacklabs/themis/gothemis v0.14.0 h1:b+LU09HBcmhmGP444gz7P64Nfrd7b/Sj1s+9Ibt4PkU=
github.com/cossacklabs/themis/gothemis v0.14.0/go.mod h1:6fvSguI8fMmChlgdG0cZywirhtTsRmp+/PsCWLDUID8=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-108
View File
@@ -1,108 +0,0 @@
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/tidwall/gjson"
)
type Token struct {
TokenType string `json:"token_type"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
}
func decrypt_AES256_CBC_PKCS7(ciphertext, key, iv string) (string, error) {
decoded_ciphertext, _ := base64.StdEncoding.DecodeString(ciphertext)
ivBytes, _ := hex.DecodeString(iv)
key = key[:32]
key = key + strings.Repeat("\x00", 32-len(key))
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
if len(decoded_ciphertext) < aes.BlockSize {
return "", errors.New("ciphertext too short")
}
cbc := cipher.NewCBCDecrypter(block, ivBytes)
cbc.CryptBlocks(decoded_ciphertext, decoded_ciphertext)
var unpad = func(ciphertext []byte) ([]byte, error) {
padding := ciphertext[len(ciphertext)-1]
if int(padding) > len(ciphertext) {
return nil, errors.New("padding is invalid")
}
for i := 0; i < int(padding); i++ {
if ciphertext[len(ciphertext)-i-1] != padding {
return nil, errors.New("padding is invalid")
}
}
return ciphertext[:len(ciphertext)-int(padding)], nil
}
unpadded_data, err := unpad(decoded_ciphertext)
if err != nil {
return "", err
}
return string(unpadded_data), nil
}
func main() {
http.HandleFunc("/oauth/alipan/token", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
refresh_token := r.FormValue("refresh_token")
if refresh_token == "" {
var body map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if val, ok := body["refresh_token"]; ok {
refresh_token = val.(string)
}
}
reqBodyJson := `{"refresh_token": "` + refresh_token + `"}`
resp, err := http.Post("http://api.extscreen.com/aliyundrive/v2/token", "application/json", strings.NewReader(reqBodyJson))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
if gjson.Get(string(respBody), "code").Int() == 200 {
ciphertext := gjson.Get(string(respBody), "data.ciphertext").String()
iv := gjson.Get(string(respBody), "data.iv").String()
key := "^(i/x>>5(ebyhumz*i1wkpk^orIs^Na."
token_data, _ := decrypt_AES256_CBC_PKCS7(ciphertext, key, iv)
var token Token
json.Unmarshal([]byte(token_data), &token)
fmt.Println(token)
json.NewEncoder(w).Encode(token)
} else {
json.NewEncoder(w).Encode(string(respBody))
}
})
fmt.Println("Running on 34278")
err := http.ListenAndServe(":34278", nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
+95
View File
@@ -0,0 +1,95 @@
from flask import Flask, request, Response
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import json
import base64
import requests
import requests
import json
import uuid
import hashlib
import base64
import random
app = Flask(__name__)
headers = {
"token": "6733b42e28cdba32",
'User-Agent': 'Mozilla/5.0 (Linux; U; Android 9; zh-cn; SM-S908E Build/TP1A.220624.014) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1',
'Host': 'api.extscreen.com'
}
def h(char_array, modifier):
unique_chars = list(dict.fromkeys(char_array))
numeric_modifier = int(modifier[7:])
transformed_string = "".join([chr(abs(ord(c) - (numeric_modifier % 127) - 1) + 33 if abs(ord(c) - (numeric_modifier % 127) - 1) < 33 else
abs(ord(c) - (numeric_modifier % 127) - 1)) for c in unique_chars])
return transformed_string
def decrypt(ciphertext, iv, t, unique_id, wifimac):
try:
key = generate_key(t, unique_id, wifimac)
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv = bytes.fromhex(iv))
decrypted = unpad(cipher.decrypt(base64.b64decode(ciphertext)), AES.block_size)
dec = decrypted.decode('utf-8')
return dec
except Exception as error:
print("Decryption failed", error)
raise error
def get_params(t, unique_id, wifimac):
params = {
'akv': '2.8.1496',
'apv': '1.3.6',
'b': 'OnePlus',
'd': unique_id,
'm': 'PJX110',
'mac': '',
'n': 'PJX110',
't': t,
'wifiMac': wifimac,
}
return params
def generate_key(t, unique_id, wifimac):
params = get_params(t, unique_id, wifimac)
sorted_keys = sorted(params.keys())
concatenated_params = "".join([params[key] for key in sorted_keys if key != "t"])
hashed_key = h(list(concatenated_params), t)
return hashlib.md5(hashed_key.encode('utf-8')).hexdigest()
@app.route('/oauth/alipan/token', methods=['POST'])
def oauth_token():
data = request.get_json()
refresh_token = data.get('refresh_token', None)
if not refresh_token:
return Response(json.dumps({"error": "No refresh_token provided"}), status=400, mimetype='application/json')
req_body = {
"refresh_token": refresh_token
}
timestamp = str(requests.get('http://api.extscreen.com/timestamp').json()['data']['timestamp'])
unique_id = uuid.uuid4().hex
wifimac = str(random.randint(10**11, 10**12 - 1))
resp = requests.post("http://api.extscreen.com/aliyundrive/v3/token", data=req_body, headers={**get_params(timestamp, unique_id, wifimac), **headers})
if resp.status_code == 200:
resp_data = resp.json()
ciphertext = resp_data["data"]["ciphertext"]
iv = resp_data["data"]["iv"]
token_data = decrypt(ciphertext, iv, timestamp, unique_id, wifimac)
token = json.loads(token_data)
return Response(json.dumps(token), status=200, mimetype='application/json')
else:
return Response(resp.content, status=resp.status_code, mimetype='application/json')
if __name__ == '__main__':
app.run(debug=True, port=34278)
+3
View File
@@ -0,0 +1,3 @@
flask
requests
pycryptodome