adding validated services? patching forcad_local.py

This commit is contained in:
Your Name
2026-08-13 08:32:35 +07:00
parent d485f61169
commit e795614e45
1459 changed files with 420036 additions and 436 deletions

View File

@@ -0,0 +1,166 @@
#!/usr/bin/env python3
import socket
import sys
import random
import string
import requests
import time
import json
import drone_client
import random_flight_plan
from checklib import *
def print(*args, **kwargs):
pass # disable print
def generate_random_datastring(length):
characters = string.ascii_letters + string.digits
random_string = "".join(random.choice(characters) for _ in range(length))
return random_string
def percent_50():
return random.randint(1, 2) == 1
class Checker(BaseChecker):
vulns: int = 1
timeout: int = 20
uses_attack_data: bool = True
def __init__(self, *args, **kwargs):
super(Checker, self).__init__(*args, **kwargs)
def action(self, action, *args, **kwargs):
try:
super(Checker, self).action(action, *args, **kwargs)
except requests.exceptions.ConnectionError:
self.cquit(
Status.DOWN,
"Connection error",
"Got requests.exceptions.ConnectionError",
)
def check(self):
client = drone_client.DroneClient(ip=self.host)
label = generate_random_datastring(random.randint(10, 30))
client.create_drone(
label=label, secret_data=generate_random_datastring(random.randint(10, 30))
)
time.sleep(1)
client.connect_to_drone()
vel = [random.randint(-3, 3), random.randint(-3, 3)]
pos = [random.randint(-20, 20), random.randint(-20, 20)]
client.update_velocity(vel)
vel_msg = client.wait_for_vel_msg(timeout=30)
self.assert_eq(
vel, vel_msg["new_velocity"], "Incorrect velocity handling", Status.CORRUPT
)
client.update_position(pos)
pos_msg = client.wait_for_pos_msg(timeout=30)
self.assert_eq(
pos, pos_msg["new_position"], "Incorrect position handling", Status.CORRUPT
)
drone_obj = client.wait_for_data_msg(timeout=30)
for _ in range(5):
if vel == drone_obj["velocity"]:
break
drone_obj = client.wait_for_data_msg(timeout=30)
self.assert_eq(
vel, drone_obj["velocity"], "Incorrect velocity handling", Status.CORRUPT
)
drone_obj_via_httpapi = client.get_drones_with_details(
json.dumps([{"$match": {"label": label}}])
)[0]
self.assert_eq(
drone_obj_via_httpapi["label"],
label,
"Incorrect HTTP API response",
Status.CORRUPT,
)
self.assert_eq(
drone_obj_via_httpapi["velocity"],
vel,
"Incorrect HTTP API response",
Status.CORRUPT,
)
self.assert_eq(
drone_obj_via_httpapi["id"],
drone_obj["id"],
"Incorrect HTTP API response",
Status.CORRUPT,
)
self.cquit(Status.OK)
def put(self, flag_id: str, flag: str, vuln: str):
fp = "\n".join(random_flight_plan.generate_plan(4, 7))
client = drone_client.DroneClient(ip=self.host)
client.create_drone(
label=generate_random_datastring(random.randint(10, 30)),
secret_data=flag,
flight_plan=fp,
)
self.cquit(
Status.OK,
f"{client.drone_id}",
json.dumps(
{
"drone_id": client.drone_id,
"control_key": client.control_key,
"flight_plan": fp,
}
),
)
def get(self, flag_id: str, flag: str, vuln: str):
# print('get FLAG by!', flag_id, '!!<-id')
drone = json.loads(flag_id)
if vuln == "1":
client = drone_client.DroneClient(ip=self.host)
client.drone_id = drone["drone_id"]
client.control_key = drone["control_key"]
client.connect_to_drone()
drone_obj = client.wait_for_data_msg(timeout=30)
expected_fl = random_flight_plan.get_expected_flight_log(
drone["flight_plan"], drone_obj["cur_time"], drone_obj
)
real_fl = drone_obj["flight_log"]
self.assert_eq(
sorted(expected_fl.split("\n")),
sorted(real_fl.split("\n")),
"Incorrect flight log",
Status.CORRUPT,
)
self.assert_eq(
flag, drone_obj["secret_data"], "Incorrect flag", Status.CORRUPT
)
self.cquit(Status.OK)
# if __name__ == '__main__':
# c = Checker("127.0.0.1")
# try:
# c.action("put", "", "TestFLAG234Fofkdjfn", "1")
# c.action("get",r'{"drone_id": "6756e4e9fb6b9f5011e88fa8", "control_key": "c3ff78e2", "flight_plan": "7 BOOSTY [drone] 1\n7 BOOSTX [drone] -1\n7 BOOSTX [drone] -2\n13 BOOSTY [drone] 2\n5 BOOSTY [drone] -1\n10 BOOSTY [drone] 2\n10 FIRE [drone]"}', "TestFLAG234Fofkdjfn", "1")
# c.action("check")
# except c.get_check_finished_exception():
# cquit(Status(c.status), c.public, c.private)
if __name__ == "__main__":
c = Checker(sys.argv[2])
try:
c.action(sys.argv[1], *sys.argv[3:])
except c.get_check_finished_exception():
cquit(Status(c.status), c.public, c.private)

View File

@@ -0,0 +1,132 @@
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):
if isinstance(data, dict):
self.last_received_data = data
self.data_received_event.set()
@sio.on("velocity_updated")
def on_velocity_updated(data):
if isinstance(data, dict):
self.last_received_veldata = data
self.velocity_updated_event.set()
@sio.on("position_updated")
def on_position_updated(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}")

View File

@@ -0,0 +1,88 @@
import random
def print(*args, **kwargs):
pass # disable print
def BOOSTX(drone, value):
drone["velocity"][0] += value
return f"Drone {drone['id']} boosted at X axis by {value}!"
def BOOSTY(drone, value):
drone["velocity"][1] += value
return f"Drone {drone['id']} boosted at Y axis by {value}!"
def FIRE(drone):
return f"Drone {drone['id']} fired!"
def SETFREQ(drone, frequency):
return f"Drone {drone['id']} freq set to {frequency}!"
def get_expected_flight_log(flight_plan, curr_time, drone):
new_log = ""
commands = flight_plan.split("\n")
for command in commands:
if not command.strip():
continue
parts = command.split()
if len(parts) == 0:
continue
expected_time = int(parts[0])
if not (curr_time > expected_time or abs(curr_time - expected_time) < 0.2):
continue
command_name = parts[1]
args = parts[2:]
func = globals().get(command_name)
if func and callable(func):
try:
typed_args = []
if len(args) > 0 and args[0] == "[drone]":
typed_args.append(drone)
args = args[1:]
typed_args.extend(
[
int(arg) if arg.replace("-", "", 1).isdigit() else arg
for arg in args
]
)
new_log += str(func(*typed_args)) + "\n"
except Exception as e:
print(f"Error calling {command_name}: {e}", flush=True)
else:
print(f"Unknown command: {command_name}", flush=True)
return new_log
def generate_plan(min_count, max_count):
num_commands = random.randint(min_count, max_count)
commands = []
for _ in range(num_commands):
command_type = random.choice(["BOOSTX", "BOOSTY", "FIRE", "SETFREQ"])
if command_type == "BOOSTX":
commands.append(
f"{random.randint(0, 8)} BOOSTX [drone] {random.randint(-2, 2)}"
)
elif command_type == "BOOSTY":
commands.append(
f"{random.randint(0, 8)} BOOSTY [drone] {random.randint(-2, 2)}"
)
elif command_type == "FIRE":
commands.append(f"{random.randint(0, 8)} FIRE [drone]")
else:
commands.append(
f"{random.randint(0, 8)} SETFREQ [drone] {random.randint(10, 100)}"
)
return commands

View File

@@ -0,0 +1,4 @@
requests==2.32.3
python-socketio==5.11.4
checklib==0.7.0
websocket-client==1.8.0