adding validated services? patching forcad_local.py
This commit is contained in:
31
ctfcup24-school-ad/sploits/flysim/client/USAGE.txt
Normal file
31
ctfcup24-school-ad/sploits/flysim/client/USAGE.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
create drone:
|
||||
./client create --ip 10.80.1.2
|
||||
|
||||
you can also specify label and (or) flight plan
|
||||
./client create --ip 10.80.1.2 --label asdf --flight-plan "1 BOOSTX [drone] 200\n55 BOOSTY [drone] 400\n"
|
||||
|
||||
connect:
|
||||
./client connect --ip 10.80.1.2 --drone-id="676306da9da3a3b7141f3000" --control-key="c786e71f"
|
||||
|
||||
connect with setting position and (or) velocity:
|
||||
./client connect --ip 10.80.1.2 --drone-id="676306da9da3a3b7141f3000" --control-key="c786e71f" --position 0 0 --velocity 1 2
|
||||
|
||||
by default, client keeps connection for 30 seconds. if you need more, add --duration:
|
||||
./client connect --ip 10.80.1.2 --drone-id="676306da9da3a3b7141f3000" --control-key="c786e71f" --duration 9999
|
||||
|
||||
list drones (only ids):
|
||||
./client list-drones --ip 10.80.1.2
|
||||
|
||||
list drones (detailed):
|
||||
./client list-drones-details --ip 10.80.1.2
|
||||
|
||||
list details but only for one drone (by label):
|
||||
./client list-drones-details --ip 10.80.1.2 --label p4MUiB5oEF5EHAnkMefO8
|
||||
|
||||
do not forget to use --help:
|
||||
|
||||
./client --help
|
||||
./client create --help
|
||||
./client connect --help
|
||||
./client list-drones --help
|
||||
./client list-drones-details --help
|
||||
10
ctfcup24-school-ad/sploits/flysim/client/building.txt
Normal file
10
ctfcup24-school-ad/sploits/flysim/client/building.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
sudo apt install python3.12-venv
|
||||
|
||||
python3.12 -m venv flysim_client
|
||||
source flysim_client/bin/activate
|
||||
pip3.12 install -r requirements.txt
|
||||
pip3.12 install pyinstaller staticx
|
||||
|
||||
python3.12 -m PyInstaller --onefile client
|
||||
staticx dist/client dist/client_static
|
||||
# dist/client_static is the file you need
|
||||
113
ctfcup24-school-ad/sploits/flysim/client/client
Executable file
113
ctfcup24-school-ad/sploits/flysim/client/client
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import click
|
||||
import drone_client
|
||||
import json
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class OrderedGroup(click.Group):
|
||||
def list_commands(self, ctx):
|
||||
# Return commands in the order they are defined
|
||||
return self.commands.keys()
|
||||
|
||||
|
||||
@click.group(cls=OrderedGroup)
|
||||
def cli():
|
||||
"""Drone Control CLI"""
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("--ip", default="127.0.0.1", help="Server IP address")
|
||||
@click.option("--label", help="Drone label")
|
||||
@click.option("--secret-data", help="Secret data for the drone")
|
||||
@click.option("--flight-plan", help="Flight plan for the drone")
|
||||
def create(ip, label, secret_data, flight_plan):
|
||||
"""Create a new drone"""
|
||||
client = drone_client.DroneClient(ip)
|
||||
|
||||
if not client.create_drone(
|
||||
label=label,
|
||||
secret_data=secret_data,
|
||||
flight_plan=flight_plan.replace(r"\n", "\n") if flight_plan else None,
|
||||
):
|
||||
click.echo("Failed to create drone")
|
||||
return
|
||||
|
||||
credentials = {
|
||||
"drone_id": client.drone_id,
|
||||
"control_key": client.control_key,
|
||||
"ip": ip,
|
||||
}
|
||||
|
||||
click.echo(f"Drone created successfully:")
|
||||
click.echo(f"Drone ID: {client.drone_id}")
|
||||
click.echo(f"Control Key: {client.control_key}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("--ip", default="127.0.0.1", help="Server IP address")
|
||||
@click.option("--drone-id", required=True, help="Drone ID")
|
||||
@click.option("--control-key", required=True, help="Control key")
|
||||
@click.option("--position", type=(float, float), help="Position coordinates (x, y)")
|
||||
@click.option("--velocity", type=(float, float), help="Velocity vector (vx, vy)")
|
||||
@click.option(
|
||||
"--duration", default=30, help="Duration to keep connection alive (seconds)"
|
||||
)
|
||||
def connect(ip, drone_id, control_key, position, velocity, duration):
|
||||
"""Connect to an existing drone"""
|
||||
client = drone_client.DroneClient(ip)
|
||||
client.drone_id = drone_id
|
||||
client.control_key = control_key
|
||||
|
||||
if not client.connect_to_drone():
|
||||
click.echo("Failed to connect to drone")
|
||||
return
|
||||
|
||||
click.echo(f"Connected to drone {drone_id}")
|
||||
|
||||
if position:
|
||||
client.update_position(list(position))
|
||||
click.echo(f"Updated position to {position}")
|
||||
|
||||
if velocity:
|
||||
client.update_velocity(list(velocity))
|
||||
click.echo(f"Updated velocity to {velocity}")
|
||||
|
||||
click.echo(f"Keeping connection alive for {duration} seconds...")
|
||||
time.sleep(duration)
|
||||
|
||||
client.disconnect()
|
||||
click.echo("Disconnected from drone")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("--ip", default="127.0.0.1", help="Server IP address")
|
||||
def list_drones(ip):
|
||||
"""List all available drones"""
|
||||
client = drone_client.DroneClient(ip)
|
||||
client.get_all_drones()
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("--ip", default="127.0.0.1", help="Server IP address")
|
||||
@click.option(
|
||||
"--label",
|
||||
"label",
|
||||
help="Target drone label. If label is not specified, all drones are shown.",
|
||||
)
|
||||
def list_drones_details(ip, label):
|
||||
"""List drone(s) with detailed information"""
|
||||
client = drone_client.DroneClient(ip)
|
||||
if label:
|
||||
print(
|
||||
client.get_drones_with_details(json.dumps([{"$match": {"label": label}}]))
|
||||
)
|
||||
else:
|
||||
print(client.get_drones_with_details(json.dumps([{"$match": {}}])))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
135
ctfcup24-school-ad/sploits/flysim/client/drone_client.py
Normal file
135
ctfcup24-school-ad/sploits/flysim/client/drone_client.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import socketio
|
||||
import requests
|
||||
import time
|
||||
import json
|
||||
from threading import Event
|
||||
|
||||
|
||||
# def print(*args, **kwargs):
|
||||
# pass # disable print
|
||||
|
||||
|
||||
class DroneClient:
|
||||
def __init__(self, ip="127.0.0.1"):
|
||||
sio = socketio.Client()
|
||||
self.base_url = f"http://{ip}:9000/"
|
||||
self.sio = sio
|
||||
|
||||
self.drone_id = None
|
||||
self.control_key = None
|
||||
self.data_received_event = Event()
|
||||
self.last_received_data = None
|
||||
|
||||
self.velocity_updated_event = Event()
|
||||
self.last_received_veldata = None
|
||||
|
||||
self.position_updated_event = Event()
|
||||
self.last_received_posdata = None
|
||||
|
||||
@sio.on("connect")
|
||||
def on_connect():
|
||||
print("Connected to server")
|
||||
|
||||
@sio.on("disconnect")
|
||||
def on_disconnect():
|
||||
print("Disconnected from server")
|
||||
|
||||
@sio.on("drone_connected")
|
||||
def on_drone_connected(data):
|
||||
print(f"Drone connection status: {data['data']}")
|
||||
|
||||
@sio.on("data_updated")
|
||||
def on_data_updated(data):
|
||||
print(data)
|
||||
if isinstance(data, dict):
|
||||
self.last_received_data = data
|
||||
self.data_received_event.set()
|
||||
|
||||
@sio.on("velocity_updated")
|
||||
def on_velocity_updated(data):
|
||||
print(data)
|
||||
if isinstance(data, dict):
|
||||
self.last_received_veldata = data
|
||||
self.velocity_updated_event.set()
|
||||
|
||||
@sio.on("position_updated")
|
||||
def on_position_updated(data):
|
||||
print(data)
|
||||
if isinstance(data, dict):
|
||||
self.last_received_posdata = data
|
||||
self.position_updated_event.set()
|
||||
|
||||
@sio.on("error")
|
||||
def on_error(data):
|
||||
print(f"Error: {data['data']}")
|
||||
|
||||
def wait_for_data_msg(self, timeout=None):
|
||||
self.data_received_event.clear()
|
||||
if self.data_received_event.wait(timeout):
|
||||
return self.last_received_data
|
||||
return None
|
||||
|
||||
def wait_for_vel_msg(self, timeout=None):
|
||||
self.velocity_updated_event.clear()
|
||||
if self.velocity_updated_event.wait(timeout):
|
||||
return self.last_received_veldata
|
||||
return None
|
||||
|
||||
def wait_for_pos_msg(self, timeout=None):
|
||||
self.position_updated_event.clear()
|
||||
if self.position_updated_event.wait(timeout):
|
||||
return self.last_received_posdata
|
||||
return None
|
||||
|
||||
def create_drone(self, label=None, secret_data=None, flight_plan=None):
|
||||
response = requests.post(
|
||||
f"{self.base_url}/create_drone",
|
||||
timeout=8000,
|
||||
json={}
|
||||
| ({"label": label} if label else {})
|
||||
| ({"secret_data": secret_data} if secret_data else {})
|
||||
| ({"flight_plan": flight_plan} if flight_plan else {}),
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
self.drone_id = data["id"]
|
||||
self.control_key = data["control_key"]
|
||||
print(
|
||||
f"Created drone with ID: {self.drone_id}, control key: {self.control_key}"
|
||||
)
|
||||
return True
|
||||
else:
|
||||
print(f"Failed to create drone: {response.text}")
|
||||
return False
|
||||
|
||||
def get_all_drones(self):
|
||||
response = requests.get(f"{self.base_url}/get_drones")
|
||||
print("All drones:", response.json())
|
||||
|
||||
def get_drones_with_details(self, with_what_details):
|
||||
response = requests.get(f"{self.base_url}/get_drones?with={with_what_details}")
|
||||
return response.json()
|
||||
|
||||
def connect_to_drone(self):
|
||||
try:
|
||||
self.sio.connect(self.base_url, socketio_path="/socket.io")
|
||||
self.sio.emit(
|
||||
"join_drone",
|
||||
{"drone_id": self.drone_id, "control_key": self.control_key},
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Connection error: {e}")
|
||||
return False
|
||||
|
||||
def update_position(self, position):
|
||||
self.sio.emit("set_position", {"drone_id": self.drone_id, "position": position})
|
||||
|
||||
def update_velocity(self, velocity):
|
||||
self.sio.emit("set_velocity", {"drone_id": self.drone_id, "velocity": velocity})
|
||||
|
||||
def disconnect(self):
|
||||
try:
|
||||
self.sio.disconnect()
|
||||
except Exception as e:
|
||||
print(f"Disconnection error: {e}")
|
||||
@@ -0,0 +1,4 @@
|
||||
requests==2.32.3
|
||||
python-socketio==5.11.4
|
||||
websocket-client==1.8.0
|
||||
click==8.1.7
|
||||
Reference in New Issue
Block a user