mirror of
https://github.com/infinition/Bjorn.git
synced 2026-03-19 10:10:24 +00:00
feat: Add login page with dynamic RGB effects and password toggle functionality
feat: Implement package management utilities with JSON endpoints for listing and uninstalling packages feat: Create plugin management utilities with endpoints for listing, configuring, and installing plugins feat: Develop schedule and trigger management utilities with CRUD operations for schedules and triggers
This commit is contained in:
@@ -1,21 +1,6 @@
|
||||
"""
|
||||
Loki — HID Attack Engine for Bjorn.
|
||||
"""__init__.py - Loki HID attack engine for Bjorn.
|
||||
|
||||
Manages USB HID gadget lifecycle, script execution, and job tracking.
|
||||
Named after the Norse trickster god.
|
||||
|
||||
Loki is the 5th exclusive operation mode (alongside MANUAL, AUTO, AI, BIFROST).
|
||||
When active, the orchestrator stops and the Pi acts as a keyboard/mouse
|
||||
to the connected host via /dev/hidg0 (keyboard) and /dev/hidg1 (mouse).
|
||||
|
||||
HID GADGET STRATEGY:
|
||||
The HID functions (keyboard + mouse) are created ONCE at boot time alongside
|
||||
RNDIS networking by the usb-gadget.sh script. This avoids the impossible task
|
||||
of hot-adding HID functions to a running composite gadget (UDC rebind fails
|
||||
with EIO when RNDIS is active).
|
||||
|
||||
LokiEngine simply opens/closes the /dev/hidg0 and /dev/hidg1 device files.
|
||||
If /dev/hidg0 doesn't exist, the user needs to run the setup once and reboot.
|
||||
Manages USB HID gadget lifecycle, HIDScript execution, and job tracking.
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
@@ -27,7 +12,7 @@ from logger import Logger
|
||||
|
||||
logger = Logger(name="loki", level=logging.DEBUG)
|
||||
|
||||
# USB HID report descriptors — EXACT byte-for-byte copies from P4wnP1_aloa
|
||||
# USB HID report descriptors - EXACT byte-for-byte copies from P4wnP1_aloa
|
||||
# Source: P4wnP1_aloa-master/service/SubSysUSB.go lines 54-70
|
||||
#
|
||||
# These are written to the gadget at boot time by usb-gadget.sh.
|
||||
@@ -64,7 +49,7 @@ _MOUSE_REPORT_DESC = bytes([
|
||||
# The boot script that creates RNDIS + HID functions at startup.
|
||||
# This replaces /usr/local/bin/usb-gadget.sh
|
||||
_USB_GADGET_SCRIPT = '''#!/bin/bash
|
||||
# usb-gadget.sh — USB composite gadget: RNDIS networking + HID (keyboard/mouse)
|
||||
# usb-gadget.sh - USB composite gadget: RNDIS networking + HID (keyboard/mouse)
|
||||
# Auto-generated by Bjorn Loki. Do not edit manually.
|
||||
|
||||
modprobe libcomposite
|
||||
@@ -196,7 +181,7 @@ _GADGET_SCRIPT_PATH = "/usr/local/bin/usb-gadget.sh"
|
||||
|
||||
|
||||
class LokiEngine:
|
||||
"""HID attack engine — manages script execution and job tracking.
|
||||
"""HID attack engine - manages script execution and job tracking.
|
||||
|
||||
The USB HID gadget (keyboard + mouse) is set up at boot time by
|
||||
usb-gadget.sh. This engine simply opens /dev/hidg0 and /dev/hidg1.
|
||||
@@ -242,7 +227,7 @@ class LokiEngine:
|
||||
# Check if HID gadget is available (set up at boot)
|
||||
if not os.path.exists("/dev/hidg0"):
|
||||
logger.error(
|
||||
"/dev/hidg0 not found — HID gadget not configured at boot. "
|
||||
"/dev/hidg0 not found - HID gadget not configured at boot. "
|
||||
"Run install_hid_gadget() from the Loki API and reboot."
|
||||
)
|
||||
self._gadget_ready = False
|
||||
@@ -287,7 +272,7 @@ class LokiEngine:
|
||||
if job["status"] == "running":
|
||||
self._jobs.cancel_job(job["id"])
|
||||
|
||||
# Close HID devices (don't remove gadget — it persists)
|
||||
# Close HID devices (don't remove gadget - it persists)
|
||||
if self._hid:
|
||||
self._hid.close()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Low-level USB HID controller for Loki.
|
||||
"""hid_controller.py - Low-level USB HID controller for Loki.
|
||||
|
||||
Writes keyboard and mouse reports to /dev/hidg0 and /dev/hidg1.
|
||||
"""
|
||||
import os
|
||||
@@ -16,7 +16,7 @@ from loki.layouts import load as load_layout
|
||||
logger = Logger(name="loki.hid_controller", level=logging.DEBUG)
|
||||
|
||||
# ── HID Keycodes ──────────────────────────────────────────────
|
||||
# USB HID Usage Tables — Keyboard/Keypad Page (0x07)
|
||||
# USB HID Usage Tables - Keyboard/Keypad Page (0x07)
|
||||
|
||||
KEY_NONE = 0x00
|
||||
KEY_A = 0x04
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
"""
|
||||
HIDScript parser and executor for Loki.
|
||||
"""hidscript.py - P4wnP1-compatible HIDScript parser and executor.
|
||||
|
||||
Supports P4wnP1-compatible HIDScript syntax:
|
||||
- Function calls: type("hello"); press("GUI r"); delay(500);
|
||||
- var declarations: var x = 1;
|
||||
- for / while loops
|
||||
- if / else conditionals
|
||||
- // and /* */ comments
|
||||
- String concatenation with +
|
||||
- Basic arithmetic (+, -, *, /)
|
||||
- console.log() for job output
|
||||
|
||||
Zero external dependencies — pure Python DSL parser.
|
||||
Pure Python DSL parser supporting type/press/delay, loops, conditionals, and variables.
|
||||
"""
|
||||
import re
|
||||
import time
|
||||
@@ -240,7 +229,7 @@ class HIDScriptParser:
|
||||
else_body = source[after_else+1:eb_end]
|
||||
next_pos = eb_end + 1
|
||||
elif source[after_else:after_else+2] == 'if':
|
||||
# else if — parse recursively
|
||||
# else if - parse recursively
|
||||
inner_if, next_pos = self._parse_if(source, after_else)
|
||||
else_body = inner_if # will be a dict, handle in exec
|
||||
else:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Loki job manager — tracks HIDScript execution jobs.
|
||||
"""jobs.py - Loki job manager, tracks HIDScript execution jobs.
|
||||
|
||||
Each job runs in its own daemon thread.
|
||||
"""
|
||||
import uuid
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Keyboard layout loader for Loki HID subsystem.
|
||||
"""__init__.py - Keyboard layout loader for Loki HID subsystem.
|
||||
|
||||
Caches loaded layouts in memory.
|
||||
"""
|
||||
import json
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
"""generate_layouts.py - Generates localized keyboard layout JSON files from a US base layout."""
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
# Chargement de la base US existante
|
||||
# Load the US base layout
|
||||
with open("us.json", "r") as f:
|
||||
US_BASE = json.load(f)
|
||||
|
||||
# Définition des différences par rapport au clavier US
|
||||
# Key differences from the US layout
|
||||
# 0 = Normal, 2 = Shift, 64 = AltGr (Right Alt)
|
||||
LAYOUT_DIFFS = {
|
||||
"fr": {
|
||||
@@ -59,20 +61,18 @@ LAYOUT_DIFFS = {
|
||||
"б": [0, 54], "ю": [0, 55], "ё": [0, 53], ".": [0, 56], ",": [2, 56],
|
||||
"№": [2, 32], ";": [2, 33], ":": [2, 35], "?": [2, 36]
|
||||
},
|
||||
"zh": {} # ZH utilise exactement le layout US
|
||||
"zh": {} # ZH uses the exact US layout
|
||||
}
|
||||
|
||||
def generate_layouts():
|
||||
for lang, diff in LAYOUT_DIFFS.items():
|
||||
# Copie de la base US
|
||||
new_layout = dict(US_BASE)
|
||||
# Application des modifications
|
||||
new_layout.update(diff)
|
||||
|
||||
filename = f"{lang}.json"
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
json.dump(new_layout, f, indent=4, ensure_ascii=False)
|
||||
print(f"Généré : {filename} ({len(new_layout)} touches)")
|
||||
print(f"Generated: {filename} ({len(new_layout)} keys)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_layouts()
|
||||
Reference in New Issue
Block a user