diff --git a/Server/Server.py b/Server/Server.py new file mode 100644 index 00000000..63270dda --- /dev/null +++ b/Server/Server.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +''' +@Description:Server.py +@Date :2023/02/25 17:03:32 +@Author :JohnserfSeed +@version :0.0.1 +@License :MIT License +@Github :https://github.com/johnserf-seed +@Mail :johnserf-seed@foxmail.com +------------------------------------------------- +Change Log : +2023/02/25 17:03:32 - Create Flask Server XB Gen +2023/08/03 16:48:34 - Fix ttwid +------------------------------------------------- +''' + +import time +import execjs +# import sqlite3 +import requests + +from flask import Flask +from flask import request +from flask import jsonify +# from flask import make_response +# from flask import render_template + +from urllib.parse import urlencode +from urllib.parse import unquote +from urllib.parse import parse_qsl + +class Server: + def __init__(self) -> None: + # 工厂模式 + self.app = Flask(__name__) + + self.app.config.from_mapping( + SECRET_KEY='douyin-xbogus' + ) + + self.app.config['JSON_AS_ASCII'] = False + + with open("x-bogus.js", "r", encoding="utf-8") as fp: + self.xbogust_func = execjs.compile(fp.read()) + + with open("x-tt-params.js", "r", encoding="utf-8") as fp: + self.xttm_func = execjs.compile(fp.read()) + + self.ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" + + # 获取xg参数 + def getXG(self, url_path, params): + xbogus = self.xbogust_func.call("getXB", url_path) + # 字典中添加xg + params["X-Bogus"] = xbogus + tips = { + "status_code": "200", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "result": [{ + "params": params, + "paramsencode": urlencode(params, safe="="), + "user-agent": self.ua, + "X-Bogus": { + 0: xbogus, + 1: "X-Bogus=%s" % xbogus + } + }] + } + print(tips) + return jsonify(tips) + + # 生成x-tt-params + def getxttparams(self, url_path): + xttp = self.xttm_func.call("getXTTP", url_path) + tips = { + "status_code": "200", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "result": [{ + "headers": { + "user-agent": self.ua, + "x-tt-params": xttp + } + }] + } + print(tips) + return jsonify(tips) + + def gen_ttwid(self) -> str: + """生成请求必带的ttwid + param :None + return:ttwid + """ + url = 'https://ttwid.bytedance.com/ttwid/union/register/' + data = '{"region":"cn","aid":1768,"needFid":false,"service":"www.ixigua.com","migrate_info":{"ticket":"","source":"node"},"cbUrlProtocol":"https","union":true}' + response = requests.request("POST", url, data=data) + # j = ttwid k = 1%7CfPx9ZM..... + for j, k in response.cookies.items(): + tips = { + "status_code": "200", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "result": [{ + "headers": { + "user-agent": self.ua, + "cookie": "ttwid=%s;" % k + } + }] + } + print(tips) + return jsonify(tips) + + +if __name__ == "__main__": + server = Server() + # 首页 + @server.app.route('/', methods=['GET', 'POST']) + def index(): + tips = { + "status_code": "-1", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "path": { + 0: "/xg/path/?url=", + 2: "/x-tt-params/path" + } + } + print(tips) + return jsonify(tips) + + # xg参数 + @server.app.route('/xg/path/', methods=['GET', 'POST']) + def xgpath(): + path = request.args.get('url', '') + # 如果str路径为空 + if not path: + tips = { + "status_code": "-3", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "message": { + 0: "The key url cannot be empty and the need for url encoding, The '&' sign needs to be escaped to '%26', Use urllib.parse.quote(url) to escape. Example:/xg/path/?url=aid=6383%26sec_user_id=xxx%26max_cursor=0%26count=10", + 1: "url参数不能为空,且需要注意传入值中的“&”需要转义成“%26”,使用urllib.parse.quote(url)转义. 例如:/xg/path/?url=aid=6383%26sec_user_id=xxx%26max_cursor=0%26count=10" + } + } + print(tips) + return jsonify(tips) + else: + # url转字典 + params = dict(parse_qsl(path)) + # 字典转url + url_path = urlencode(params, safe="=") + return server.getXG(url_path, params) + + # x-tt-params参数 + @server.app.route('/x-tt-params/path', methods=['GET', 'POST']) + def xttppath(): + try: + path = request.json + except: + pass + if not path: + tips = { + "status_code": "-5", + "time": { + "strftime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), + "timestamp": int(round(time.time() * 1000)) + }, + "message": { + 0: "Body uses raw JSON format to pass dictionary parameters, such as %s" % '{"aid": 1988,"app_name": "tiktok_web","channel": "tiktok_web".........}', + 1: "body中使用raw json格式传递字典参数,如%s" % '{"aid": 1988,"app_name": "tiktok_web","channel": "tiktok_web".........}' + } + } + print(tips) + return jsonify(tips) + else: + return server.getxttparams(path) + + # ttwid + @server.app.route('/xg/ttwid', methods=['GET', 'POST']) + def ttwid(): + return server.gen_ttwid() + + + server.app.run(host='0.0.0.0',port='8889') diff --git a/Server/Server.txt b/Server/Server.txt new file mode 100644 index 00000000..8356b57c --- /dev/null +++ b/Server/Server.txt @@ -0,0 +1,41 @@ +# UTF-8 +# +# For more details about fixed file info 'ffi' see: +# http://msdn.microsoft.com/en-us/library/ms646997.aspx +VSVersionInfo( + ffi=FixedFileInfo( + # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) + # Set not needed items to zero 0. + filevers=(1, 4, 2, 2), + prodvers=(1, 4, 2, 2), + # Contains a bitmask that specifies the valid bits 'flags'r + mask=0x3f, + # Contains a bitmask that specifies the Boolean attributes of the file. + flags=0x0, + # The operating system for which this file was designed. + # 0x4 - NT and there is no need to change it. + OS=0x40004, + # The general type of file. + # 0x1 - the file is an application. + fileType=0x1, + # The function of the file. + # 0x0 - the function is not defined for this fileType + subtype=0x0, + # Creation date and time stamp. + date=(0, 0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + u'080404b0', + [StringStruct(u'CompanyName', u'JohnserfSeed'), + StringStruct(u'FileDescription', u'本地解析服务'), + StringStruct(u'FileVersion', u'1.4.2.2'), + StringStruct(u'LegalCopyright', u'Copyright (C) 2019-2023 JohnserfSeed. All Rights Reserved'), + StringStruct(u'ProductName', u'本地解析服务'), + StringStruct(u'ProductVersion', u'1.4.2.2')]) + ]), + VarFileInfo([VarStruct(u'Translation', [2052, 1200])]) + ] +) \ No newline at end of file diff --git a/Server/build-win.bat b/Server/build-win.bat new file mode 100644 index 00000000..77f8201d --- /dev/null +++ b/Server/build-win.bat @@ -0,0 +1,9 @@ +@echo off +echo Install Npm Require +npm i +echo Install Pip Require +pip install -r requirements.txt +echo Build EXE version, Press Ctrl + C to Exit +echo Build Server +pyinstaller -F -i f2-logo.ico --version-file Server.txt --hidden-import=charset_normalizer.md__mypyc Server.py +pause \ No newline at end of file diff --git a/Server/package.json b/Server/package.json new file mode 100644 index 00000000..6f318077 --- /dev/null +++ b/Server/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "crypto-js": "^4.1.1", + "md5": "^2.3.0" + } +} diff --git a/Server/requirements.txt b/Server/requirements.txt new file mode 100644 index 00000000..6da28983 --- /dev/null +++ b/Server/requirements.txt @@ -0,0 +1,2 @@ +Flask==2.2.5 +PyExecJS==1.5.1 \ No newline at end of file diff --git a/Server/s_v_web_id.js b/Server/s_v_web_id.js new file mode 100644 index 00000000..6d620aca --- /dev/null +++ b/Server/s_v_web_id.js @@ -0,0 +1,15 @@ +function create_s_v_web_id() { + var e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("") + , t = e.length + , n = (new Date).getTime().toString(36) + , r = []; + + r[8] = r[13] = r[18] = r[23] = "_", + r[14] = "4"; + for (var o, i = 0; i < 36; i++) + r[i] || (o = 0 | Math.random() * t, + r[i] = e[19 == i ? 3 & o | 8 : o]); + return "verify_" + n + "_" + r.join("") +} + +console.log(create_s_v_web_id()) \ No newline at end of file diff --git a/Server/s_v_web_id.py b/Server/s_v_web_id.py new file mode 100644 index 00000000..c93d99f5 --- /dev/null +++ b/Server/s_v_web_id.py @@ -0,0 +1,31 @@ +import time +import random + +def create_s_v_web_id(): + e = list("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") + t = len(e) + n = base36_encode(int(time.time()*1000)) # Convert timestamp to base 36 + + r = [''] * 36 + r[8] = r[13] = r[18] = r[23] = "_" + r[14] = "4" + + for i in range(36): + if not r[i]: + o = int(random.random() * t) + r[i] = e[3 & o | 8 if i == 19 else o] + + return "verify_" + n + "_" + "".join(r) + +def base36_encode(number): + """Converts an integer to a base36 string.""" + alphabet = '0123456789abcdefghijklmnopqrstuvwxyz' + base36 = [] + + while number: + number, i = divmod(number, 36) + base36.append(alphabet[i]) + + return ''.join(reversed(base36)) + +print(create_s_v_web_id()) \ No newline at end of file diff --git a/Server/x-bogus.js b/Server/x-bogus.js new file mode 100644 index 00000000..6e73604a --- /dev/null +++ b/Server/x-bogus.js @@ -0,0 +1,132 @@ +let MD5 = require("md5"); + +let Array = [ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 10, 11, 12, 13, 14, 15 ]; + +// let _0x4129ad = 'Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe'; +// let _0x127ecb = '='; +let _0x377d66 = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe="; + +function _0x39ced2(l) { + let n = []; + for (let u = 0; u < l.length; ) { + n.push(Array[l.charCodeAt(u++)] << 4 | Array[l.charCodeAt(u++)]); + } + return n; +} + +function _0x1da120(l) { + return _0x39ced2(MD5(_0x39ced2(MD5(l)))); +} + +function _0x2efd11(l) { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(l); +} + +function _0x2d9dba(l) { + var n, u, e, t, r, o = ""; + for (n = 0; n < l.length - 3; n += 4) { + u = _0x2efd11(l.charAt(n)), e = _0x2efd11(l.charAt(n + 1)), t = _0x2efd11(l.charAt(n + 2)), + r = _0x2efd11(l.charAt(n + 3)), o += String.fromCharCode(u << 2 | e >>> 4), "=" !== l.charAt(n + 2) && (o += String.fromCharCode(e << 4 & 240 | t >>> 2 & 15)), + "=" !== l.charAt(n + 3) && (o += String.fromCharCode(t << 6 & 192 | r)); + } + return o; +} + +function _0x24e7c9() { + var l = ""; + try { + window.sessionStorage && (l = window.sessionStorage.getItem("_byted_param_sw")), + l && !window.localStorage || (l = window.localStorage.getItem("_byted_param_sw")); + } catch (l) {} + if (l) { + try { + var n = _0x3459bb(_0x2d9dba(l.slice(8)), l.slice(0, 8)); + if ("on" === n) { + return !0; + } + if ("off" === n) { + return !1; + } + } catch (l) {} + } + return !1; +} + +function _0x4d54ed(l) { + try { + return window.localStorage ? window.localStorage.getItem(l) : null; + } catch (l) { + return null; + } +} + +function _0x478bb3(l, n, u) { + let e = (255 & l) << 16; + let t = (255 & n) << 8; + let r = e | t | u; + return _0x377d66[(16515072 & r) >> 18] + _0x377d66[(258048 & r) >> 12] + _0x377d66[(4032 & r) >> 6] + _0x377d66[63 & r]; +} + +function _0x481826(l) { + void 0 !== l && "" != l && (_0x402a35.ttwid = l); +} + +function _0x37f15d() { + var l = _0x4d54ed("xmst"); + return l || ""; +} + +function _0x330d11(l, n, u, e, t, r, o, d, a, c, i, f, x, _, h, g, C, s, p) { + let w = new Uint8Array(19); + w[0] = l, w[1] = i, w[2] = n, w[3] = f, w[4] = u, w[5] = x, w[6] = e, w[7] = _, + w[8] = t, w[9] = h, w[10] = r, w[11] = g, w[12] = o, w[13] = C, w[14] = d, w[15] = s, + w[16] = a, w[17] = p, w[18] = c; + return String.fromCharCode.apply(null, w); +} + +function _0x330d112(l, n) { + let u, e = [], t = 0, r = "", o = 0, d = 0, a = 0; + for (let l = 0; l < 256; l++) { + e[l] = l; + } + for (;o < 256; o++) { + t = (t + e[o] + l.charCodeAt(o % l.length)) % 256, u = e[o], e[o] = e[t], e[t] = u; + } + t = 0; + for (;d < n.length; d++) { + t = (t + e[a = (a + 1) % 256]) % 256, u = e[a], e[a] = e[t], e[t] = u, r += String.fromCharCode(n.charCodeAt(d) ^ e[(e[a] + e[t]) % 256]); + } + return r; +} + +function _0x33baa6(l, n, u) { + return String.fromCharCode(l) + String.fromCharCode(n) + u; +} + +function getXB(l) { + // douyin + let n = _0x39ced2(MD5("d4+pTKoNjJFb5tMtAC3XB9XrDDxlig1kjbh32u+x5YcwWb/me2pvLTh6ZdBVN5skEeIaOYNixbnFK6wyJdl/Lcy9CDAcpXLLQc3QFKIDQ3KkQYie3n258eLS1YFUqFLDjn7dqCRp1jjoORamU2SV")); + // douyin & tiktok + let u = _0x39ced2(MD5(_0x39ced2("d41d8cd98f00b204e9800998ecf8427e"))); + let e = _0x1da120(l), t = new Date().getTime() / 1e3, r = 536919696, o = [], d = [], a = ""; + let c = [ 64, .00390625, 1, 8, e[14], e[15], u[14], u[15], n[14], n[15], t >> 24 & 255, t >> 16 & 255, t >> 8 & 255, t >> 0 & 255, r >> 24 & 255, r >> 16 & 255, r >> 8 & 255, r >> 0 & 255 ]; + c.push(c.reduce(function(l, n) { + return l ^ n; + })); + for (let l = 0; l < c.length; l += 2) { + o.push(c[l]); + d.push(c[l + 1]); + } + //unescape('%FF') + let i = _0x33baa6.apply(null, [ 2, 255, _0x330d112.apply(null, [String.fromCharCode(255), _0x330d11.apply(null, o.concat(d).slice(0, 19)) ]) ]); + for (let l = 0; l < i.length; ) { + a += _0x478bb3(i.charCodeAt(l++), i.charCodeAt(l++), i.charCodeAt(l++)); + } + return a; +} + +_0x180b4c = _0x37f15d(); + +module.exports = { + getXB: getXB +}; \ No newline at end of file diff --git a/Server/x-tt-params.js b/Server/x-tt-params.js new file mode 100644 index 00000000..8522576f --- /dev/null +++ b/Server/x-tt-params.js @@ -0,0 +1,27 @@ +let CryptoJS = require("crypto-js"); +getXTTP = e => { + const t = []; + return Object.keys(e).forEach((i => { + const o = `${i}=${e[i]}`; + t.push(o) + })), + t.push("is_encryption=1"), + ((e, t) => { + const i = ((e, t) => { + let i = e.toString(); + const o = i.length; + return o < 16 ? i = new Array(16 - o + 1).join("0") + i : o > 16 && (i = i.slice(0, 16)), + i + })("webapp1.0+20210628"), + n = CryptoJS.enc.Utf8.parse(i); + return CryptoJS.AES.encrypt(e, n, { + iv: n, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7 + }).toString() + })(t.join("&")) +} + +module.exports = { + getXTTP: getXTTP +}; \ No newline at end of file diff --git a/run-server.bat b/run-server.bat new file mode 100644 index 00000000..497226d6 --- /dev/null +++ b/run-server.bat @@ -0,0 +1,2 @@ +cd Server +py Server.py \ No newline at end of file diff --git a/run-server.sh b/run-server.sh new file mode 100644 index 00000000..db662fe4 --- /dev/null +++ b/run-server.sh @@ -0,0 +1,2 @@ +cd Server +python3 Server.py \ No newline at end of file diff --git a/server.bat b/server.bat deleted file mode 100644 index fe40b8dc..00000000 --- a/server.bat +++ /dev/null @@ -1,3 +0,0 @@ -cd Util -cd algorithm -python Server.py \ No newline at end of file diff --git a/server.sh b/server.sh deleted file mode 100644 index 95c80c85..00000000 --- a/server.sh +++ /dev/null @@ -1,3 +0,0 @@ -cd Util -cd algorithm -python3 Server.py \ No newline at end of file