Car Theft
Car Theft
Platform: hackerlab | Category: GamePwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-04-05 | Status: Solved Techniques: class_selection_navigation, custom_protocol_client, position_sync_sweeping, raknet_stringcompressor_decoding, samp_query_fingerprinting
Summary
Task: an IP:port led to a SA-MP UDP server instead of a web service, with hints about Bone County and aliens. Solution: fingerprint the server, adapt a custom SA-MP client, sweep Bone County for Infernus spawns, then decode a RakNet StringCompressor 3D label near Lil Probe Inn to recover the flag.
Car Theft — Hackerlab
Description
Подсказка в задании указывала на Bone County и инопланетян.
English summary: the target was a single IP:port. Recon showed it was not a web service but a SA-MP game server. The goal was to connect as a client, find the correct vehicle hinted by the challenge, and extract the flag.
Analysis
The first useful observation was transport-level: the service did not behave like HTTP or a regular TCP daemon. A SA-MP query packet (SAMP + IP bytes + little-endian port + opcode) identified the server as CODEBY GAMES, gamemode codeby.games, version 0.3.7-R2.
A stock client implementation did not join successfully, so the Python SA-MP client was adjusted to match the server handshake: version 4057, mod byte 1, client version 0.3.7, and duplicated challenge response handling.
After joining, class-selection textdraws rotated through Los Santos → San Fierro → Las Venturas. Because the clue mentioned Bone County and aliens, Las Venturas was the correct branch. Sweeping Bone County with fake on-foot position sync packets revealed several vehicles of model 411 (Infernus).
The strongest candidate was the Infernus near Lil Probe Inn at about (-109.726, 1370.466, 9.808), which matched the alien hint. It also had the expected visual cues: orange-like color and wheel mod in vehicle mod slot 81.
The final detail was protocol-specific: the flag was not sent as a plain string. SA-MP RPC 36 (ScrCreate3DTextLabel) carried a 3D label attached to vehicle 1791, and its text field was encoded with RakNet StringCompressor. Decoding that payload yielded the flag, with one harmless trailing padding artifact after the closing brace.
Solution
- Probe the target with a SA-MP UDP query and confirm it is a SA-MP server.
- Patch the custom Python client so it can complete the join sequence accepted by this server.
- Join class selection and watch the textdraws until the city sequence shows Las Venturas as the relevant destination.
- Select Las Venturas, spawn, and sweep Bone County by sending fake on-foot sync positions.
- Filter streamed vehicles by model
411(Infernus) and inspect the one near Lil Probe Inn. - Parse RPC 36 (
ScrCreate3DTextLabel) and decode its StringCompressor payload. - Truncate the decoded text at the closing brace and recover the valid flag.
python read-only • copy allowed#!/usr/bin/env python3 import os import sys import time import threading BASE = os.path.join("tasks", "hackerlab", "Автокража", "samp-client-python") sys.path.insert(0, BASE) from client import SAMPClient from packet_ids import RPC from inspect_lil_probe_inn import decode_samp_encoded_string4096 TARGET = (-109.726, 1370.466, 10.0) KEY_FIRE = 4 KEY_RIGHT = 128 INFERNUS_MODEL = 411 def pulse_spectator_key(client, lr=0, keys=0, repeats=4, delay=0.12): for _ in range(repeats): client.send_spectator_sync(lr, 0, keys) time.sleep(delay) client.send_spectator_sync(0, 0, 0) def move_to(client, x, y, z, repeats=8, delay=0.08): client.position = [float(x), float(y), float(z)] for _ in range(repeats): client.send_onfoot_sync() time.sleep(delay) def read_vehicle(bs): vehicle_id = bs.read_u16() model_id = bs.read_u32() x, y, z = bs.read_float(), bs.read_float(), bs.read_float() bs.read_float() # angle color1, color2 = bs.read_u8(), bs.read_u8() bs.read_float() # health bs.read_u8() # interior bs.read_u32(); bs.read_u32(); bs.read_u8(); bs.read_u8(); bs.read_u8() mods = [bs.read_u8() for _ in range(14)] return { "vehicle_id": vehicle_id, "model_id": model_id, "x": round(x, 3), "y": round(y, 3), "z": round(z, 3), "color1": color1, "color2": color2, "mods": mods, } def read_3d_label(bs): bs.read_u16() # label_id bs.read_u32() # color x, y, z = bs.read_float(), bs.read_float(), bs.read_float() bs.read_float() # draw distance bs.read_u8() # test_los bs.read_u16() # attached_player attached_vehicle = bs.read_u16() text = decode_samp_encoded_string4096(bytes(bs._data), bs._read_bit_offset) return attached_vehicle, (x, y, z), text client = SAMPClient("62.173.140.174", 10350, "ProbeInn1") target_vehicle_id = None def scenario(): time.sleep(3) for _ in range(3): pulse_spectator_key(client, lr=KEY_RIGHT) time.sleep(0.6) pulse_spectator_key(client, keys=KEY_FIRE) # select Las Venturas time.sleep(1.5) client.send_request_spawn() time.sleep(0.7) client.send_spawn() time.sleep(2) move_to(client, *TARGET) time.sleep(3) client.disconnect() def on_connected(): threading.Thread(target=scenario, daemon=True).start() def on_rpc(rpc_id, bs): global target_vehicle_id if rpc_id == RPC.WorldVehicleAdd: vehicle = read_vehicle(bs) if vehicle["model_id"] == INFERNUS_MODEL and abs(vehicle["x"] - TARGET[0]) < 30 and abs(vehicle["y"] - TARGET[1]) < 30: target_vehicle_id = vehicle["vehicle_id"] print("candidate:", vehicle) elif rpc_id == RPC.ScrCreate3DTextLabel: attached_vehicle, pos, text = read_3d_label(bs) if attached_vehicle == target_vehicle_id or attached_vehicle == 1791: flag = text[: text.find("}") + 1] print("label:", pos, text) print("flag:", flag) client.on_connected = on_connected client.on_rpc = on_rpc client.connect() client.wait()