Skip to content

Instantly share code, notes, and snippets.

@xl00t
Created February 20, 2023 22:06
Show Gist options
  • Save xl00t/2e89448e2170a5cb1d58893f77e4832f to your computer and use it in GitHub Desktop.
Save xl00t/2e89448e2170a5cb1d58893f77e4832f to your computer and use it in GitHub Desktop.
API BattleHack
#!/usr/bin/env python3
import requests
import base64
import getpass
# as i see there is no rate limit implemented , we can bruteforce through all API endpoints.
# the register page can also be used in order to spam their backend.
API_FORGOT_PAGE = "https://api.seela.io/hub/auth/forgot-password" # Permit email enumeration
API_LOGIN_PAGE = "https://api.seela.io/hub/auth/login"
API_USER_INFO = "https://api.seela.io/hub/auth/user"
API_MISSIONS_INFO = "https://api.seela.io/battle/missions/get-missions"
MISSION_START_MODE = ["normal", "speedrun"]
MISSION_START_PAGE = "https://api.seela.io/battle/missions/mission-start"
MISSION_SUBMIT_FLAG = "https://api.seela.io/battle/missions/submit-flag"
MISSION_STOP_PAGE = "https://api.seela.io/battle/missions/mission-stop"
MISSION_INFO_PAGE = "https://api.seela.io/battle/missions/get-user-mission-by-uuid/"
MISSION_SEND_FLAG = "https://api.seela.io/battle/missions/submit-flag"
GET_LOCAL_PAGE = "https://api.seela.io/broadcasting/auth"
class BattleHackAPI:
def __init__(self, email, password):
self.access_token = self.Get_Access_Token(email, password)
self.bearer = {
"Authorization": f"Bearer {self.access_token}"
}
self.user_info = self.Get_User_Info()
self.battle_info = self.Get_Battle_Info()
self.missions_info = self.Get_Missisons_info()
self.selected_mission = None
self.started_mission = None
def Get_Access_Token(self, email, password):
r = requests.post(API_LOGIN_PAGE, json={
"email":email,
"password": password
}).json()
return r["access_token"] if "access_token" in r else "Bad Email/Password"
def Get_User_Info(self):
r = requests.get(API_USER_INFO, headers = self.bearer).json()
return r
def Get_Battle_Info(self):
return self.user_info["get_battle_profile"] if "get_battle_profile" in self.user_info else "Error"
def Get_VPN_Configuration(self):
if "vpn_conf" in self.battle_info:
vpn = base64.b64decode(self.battle_info["vpn_conf"]).decode()
open('../vpns/battle_hack.ovpn', 'w').write(vpn).close()
def Get_Missisons_info(self):
r = requests.get(API_MISSIONS_INFO, headers = self.bearer).json()
return r
def Select_Mission(self, mission):
for x in self.missions_info:
if x['title'] == mission:
return x
return None
def Start_Mission(self, mission):
self.selected_mission = self.Select_Mission("Welcome")
r = requests.post(MISSION_START_PAGE, headers = self.bearer, json={
"missionId": self.selected_mission["id"],
"mode": MISSION_START_MODE[0],
"accessType": "vpn"
}).json()
self.started_mission = r
return self.Get_Mission_Ip()
def Get_Local(self, socket_id):
r = requests.post(GET_LOCAL_PAGE, headers=self.bearer, json={
"socket_id": socket_id,
"channel_name": f"private-user.{self.user_info['id']}"
}).json()
return r['auth'].replace('local:','')
def Get_Mission_Ip(self):
import re
from contextlib import closing
from websocket import create_connection
with closing(create_connection("wss://api.seela.io/app/local?protocol=7&client=js&version=8.0.0&flash=false")) as conn:
socket_id = conn.recv().split('"socket_id\\":\\"')[1].split('\\"')[0]
local = self.Get_Local(socket_id)
stre = f'{{"event":"pusher:subscribe","data":{{"auth":"local:{local}","channel":"private-user.{self.user_info["id"]}"}}}}'
conn.send(stre)
conn.recv()
import re
out = conn.recv()
pattern = re.compile('''((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)''')
return pattern.search(out)[0]
def Stop_Mission(self):
print(self.started_mission)
mission_started_id = requests.get(f"{MISSION_INFO_PAGE}{self.started_mission['user_mission_uuid']}", headers=self.bearer).json()["id"]
r = requests.post(MISSION_STOP_PAGE, headers=self.bearer, json={
"userMissionId": int(mission_started_id)
}).json()
print(r)
def Send_Flag(self, flag):
r = requests.post(MISSION_SEND_FLAG, headers=self.bearer, json={
"missionId": self.selected_mission['id'],
"flag": flag
}).json()
return r
def main():
email = '0xl00t@protonmail.com'
password = getpass.getpass(prompt='Password: ', stream=None)
api = BattleHackAPI(email, password)
print(api.battle_info)
# print(api.Start_Mission("Welcome"))
# print(api.Send_Flag("lol"))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment