Arrow exprs parser!

This commit is contained in:
DarkCat09 2022-03-17 10:24:58 +04:00
parent 08743f69bd
commit bb5978f8f5
7 changed files with 29 additions and 172 deletions

View file

@ -1,11 +1,9 @@
import hashlib import hashlib
import lxml.html import lxml.html
from typing import Optional, Union, List from typing import List
from . import atserver
from . import atconnect
from . import aterrors
from .atserver import AternosServer
from .atconnect import AternosConnect
from .aterrors import AternosCredentialsError from .aterrors import AternosCredentialsError
class Client: class Client:
@ -17,7 +15,7 @@ class Client:
@classmethod @classmethod
def from_hashed(cls, username:str, md5:str): def from_hashed(cls, username:str, md5:str):
atconn = atconnect.AternosConnect() atconn = AternosConnect()
atconn.parse_token() atconn.parse_token()
atconn.generate_sec() atconn.generate_sec()
@ -50,7 +48,7 @@ class Client:
@classmethod @classmethod
def from_session(cls, session:str): def from_session(cls, session:str):
atconn = atconnect.AternosConnect() atconn = AternosConnect()
atconn.session.cookies.set('ATERNOS_SESSION', session) atconn.session.cookies.set('ATERNOS_SESSION', session)
atconn.parse_token() atconn.parse_token()
atconn.generate_sec() atconn.generate_sec()
@ -60,7 +58,7 @@ class Client:
@staticmethod @staticmethod
def google() -> str: def google() -> str:
atconn = atconnect.AternosConnect() atconn = AternosConnect()
auth = atconn.request_cloudflare( auth = atconn.request_cloudflare(
'https://aternos.org/auth/google-login', 'https://aternos.org/auth/google-login',
atconnect.REQGET, redirect=False atconnect.REQGET, redirect=False
@ -79,6 +77,6 @@ class Client:
servers = [] servers = []
for server in serverslist: for server in serverslist:
servid = server.xpath('./div[@class="server-body"]/@data-id')[0] servid = server.xpath('./div[@class="server-body"]/@data-id')[0]
servers.append(atserver.AternosServer(servid, self.atconn)) servers.append(AternosServer(servid, self.atconn))
return servers return servers

View file

@ -1,57 +1,21 @@
import re import regex
import base64 import base64
import js2py import js2py
from typing import Optional, Union, List, Any from typing import Optional, Union, List, Any
# regexr.com/6el10 # Thanks to http://regex.inginf.units.it/
arrowexp = re.compile(r'(\(?(\w+(?:,\s*\w+)*)\)?|\(\))\s*=>\s*(({\s*.+\s*})|(.+;|.+$))') arrowexp = regex.compile(r'\w[^\}]*+')
# Thanks to https://stackoverflow.com/a/1651562/17901968
def brackets(s:str, search:Optional[str]=None) -> List[Union[int]]:
result = []
content = [s]
repeated = False
for expr in content:
if expr.find('(') == -1: continue
count = -1
indexes = []
cont = False
for i, ch in enumerate(expr):
if ch == '(':
indexes.append(i)
if count == -1:
count = 1
else:
count += 1
if ch == ')':
if len(indexes) > 1:
indexes.pop()
else:
indexes.append(i)
if expr.find('(', i) != -1:
cont = True
count -= 1
if count == 0: break
if count != 0:
raise ValueError('Unmatched parenthesis')
else:
inner = expr[indexes[0]+1:indexes[1]]
if repeated:
content.pop()
repeated = False
content.append(inner)
if search == None \
or search in inner:
result.append(indexes)
if cont:
content.append(content[len(content)-2])
repeated = True
return result
def to_ecma5_function(f:str) -> str: def to_ecma5_function(f:str) -> str:
pass match = arrowexp.search(f)
conv = '(function(){' + match.group(0) + '})()'
return regex.sub(
r'(?:s|\(s\)) => s.split\([\'"]{2}\).reverse\(\).join\([\'"]{2}\)',
'function(s){return s.split(\'\').reverse().join(\'\')}',
conv
)
def atob(s): def atob(s:str) -> str:
return base64.standard_b64decode(str(s)).decode('utf-8') return base64.standard_b64decode(str(s)).decode('utf-8')
def exec(f:str) -> Any: def exec(f:str) -> Any:

View file

@ -1,4 +1,4 @@
lxml==4.6.2 lxml==4.8.0
requests==2.25.1 requests==2.25.1
cloudscraper==1.2.58 cloudscraper==1.2.58
js2py==0.71 js2py==0.71

View file

@ -22,6 +22,7 @@ setuptools.setup(
'Documentation': 'https://github.com/DarkCat09/python-aternos/wiki/Client-(entry-point)', 'Documentation': 'https://github.com/DarkCat09/python-aternos/wiki/Client-(entry-point)',
}, },
classifiers=[ classifiers=[
'Development Status :: 4 - Beta',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent' 'Operating System :: OS Independent'

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python3
import re import re
import base64 from python_aternos import atjsparse
import js2py
# Use tests from a file # Use tests from a file
tests = [] tests = []
@ -10,43 +8,10 @@ with open('../token.txt', 'rt') as f:
del lines[len(lines)-1] # Remove empty string del lines[len(lines)-1] # Remove empty string
tests = lines tests = lines
arrowre = re.compile(r'(\w+?|\(\w+?(?:,\s*\w+?)*\)|\(\))\s*=>\s*({\s*[\s\S]+\s*}|[^\r\n]+?(?:;|$))')
def to_ecma5_function(f):
# return "(function() { " + f[f.index("{")+1 : f.index("}")] + "})();"
fnstart = f.find('{')+1
fnend = f.rfind('}')
f = arrow_conv(f[fnstart:fnend])
return f
def atob(s):
return base64.standard_b64decode(str(s)).decode('utf-8')
def arrow_conv(f):
m = arrowre.search(f)
while m != None:
print(f)
params = m.group(1).strip('()')
body = m.group(2)
if body.startswith('{')\
and body.endswith('}'):
body = body.strip('{}')
else:
body = f'return {body}'
f = arrowre.sub(f'function({params}){{{body}}}', f)
m = arrowre.search(f)
print(f)
#print('function(' + m.group(1).strip("()") + '){return ' + m.group(2) + ';}')
return f
ctx = js2py.EvalJs({'atob': atob})
for f in tests: for f in tests:
c = to_ecma5_function(f) ctx = atjsparse.exec(f)
ctx.execute(c)
print(ctx.window['AJAX_TOKEN']) print(ctx.window['AJAX_TOKEN'])
# Expected output:
# 2rKOA1IFdBcHhEM616cb # 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb # 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb # 2rKOA1IFdBcHhEM616cb
@ -59,6 +24,7 @@ for f in tests:
# 2iXh5W5uEYq5fWJIazQ6 # 2iXh5W5uEYq5fWJIazQ6
# CuUcmZ27Fb8bVBNw12Vj # CuUcmZ27Fb8bVBNw12Vj
# YPPe8Ph7vzYaZ9PF9oQP # YPPe8Ph7vzYaZ9PF9oQP
# ... # UfLlemvKEE16ltk0hZNM
# (Note: The last four # q6pYdP6r7xiVHhbotvlN
# tokens are different) # q6pYdP6r7xiVHhbotvlN
# XAIbksgkVX9JYboMDI7D

View file

@ -1,75 +0,0 @@
#!/usr/bin/env python3
import re
import base64
import js2py
# Use tests from a file
tests = []
with open('../token.txt', 'rt') as f:
lines = re.split(r'[\r\n]', f.read())
del lines[len(lines)-1] # Remove empty string
tests = lines
brkregex = re.compile(r'\((?!\)|[\'\"])(.+?)(?<!\(|[\'\"])\)')
def parse_brackets(f, arrow=True):
match = brkregex.finditer(f)
if not arrow:
return match[0].group(1)
for r in match:
func = r.group(1)
if '=>' in func:
return func
def to_ecma5_function(f):
# return "(function() { " + f[f.index("{")+1 : f.index("}")] + "})();"
fnstart = f.find('{')+1
fnend = f.rfind('}')
f = arrow_conv(f[fnstart:fnend])
return f
def atob(s):
return base64.standard_b64decode(str(s)).decode('utf-8')
def arrow_conv(f):
if '=>' in f:
inner = parse_brackets(f)
print(inner)
while brkregex.match(inner) != None:
print(inner)
inner = parse_brackets(inner)
func = re.sub(
r'(\w+)\s*=>\s*(.+)',
r'function(\1){return \2}', inner
)
start = f.find(inner)
end = start + len(inner)
f = f[:start] + func + f[end:]
print('*r:', f)
return f
ctx = js2py.EvalJs({'atob': atob})
for f in tests:
c = to_ecma5_function(f)
ctx.execute(c)
print(ctx.window['AJAX_TOKEN'])
# Expected output:
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2rKOA1IFdBcHhEM616cb
# 2iXh5W5uEYq5fWJIazQ6
# CuUcmZ27Fb8bVBNw12Vj
# YPPe8Ph7vzYaZ9PF9oQP
# (Note: The last four
# tokens are different)

View file

@ -11,3 +11,6 @@
(() => {window[["_XAJA","NEKOT"].map(s => s.split('').reverse().join('')).join('')]=!window[("encodeURI" + "Componen" + "t")] || atob('Q3VVY21aMjdGYjhiVkJOdzEyVmo=');})(); (() => {window[["_XAJA","NEKOT"].map(s => s.split('').reverse().join('')).join('')]=!window[("encodeURI" + "Componen" + "t")] || atob('Q3VVY21aMjdGYjhiVkJOdzEyVmo=');})();
(() => {window[["N","_TOKE","AJAX"].reverse().join('')]=!window[("en" + "co" + "deURICo" + "mpone" + "nt")] || ["zv7hP8ePPY","FP9ZaY","PQo9"].map(s => s.split('').reverse().join('')).join('');})(); (() => {window[["N","_TOKE","AJAX"].reverse().join('')]=!window[("en" + "co" + "deURICo" + "mpone" + "nt")] || ["zv7hP8ePPY","FP9ZaY","PQo9"].map(s => s.split('').reverse().join('')).join('');})();
(() => {window[["XAJA","OT_","EK","N"].map(s => s.split('').reverse().join('')).join('')]=["fU","61EEKvmelL","Zh0ktl","MN"].map(s => s.split('').reverse().join('')).join('');})(); (() => {window[["XAJA","OT_","EK","N"].map(s => s.split('').reverse().join('')).join('')]=["fU","61EEKvmelL","Zh0ktl","MN"].map(s => s.split('').reverse().join('')).join('');})();
(() => {window[["AJA","X_T","OKEN"].join('')]=window['document']&&window[("Map")]&&window[("se" + "tTi" + "meo" + "u" + "t")]?["Ew9q","VIepR","GRX","S1Oban9U"].reverse().join(''):"q6pYdP6r7xiVHhbotvlN";})();
(() => {window["AJAX_TOKEN"]=window['document']&&window["Map"]&&window[["out","e","Tim","et","s"].reverse().join('')]?["pREw9q","XVIe","UGR","S1Oban9"].reverse().join(''):["dYp6q","Vix7r6P","tobhH","Nlv"].map(s => s.split('').reverse().join('')).join('');})();
(() => {window[["OKEN", "T", "_", "AJAX"].reverse().join("")] = window["document"] && window["Map"] && window["set" + "T" + "im" + "e" + "o" + "u" + "t"] ? ["DYK", "OWD1TyD", "TJ", "JtNpZ", "MhW"].map((s) => s.split("").reverse().join("")).join("") : "XAIbksgkVX9JYboMDI7D";})();