phantomrt 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. phantomrt-0.1.0/LICENSE +21 -0
  2. phantomrt-0.1.0/PKG-INFO +75 -0
  3. phantomrt-0.1.0/README.md +39 -0
  4. phantomrt-0.1.0/atlas/__init__.py +3 -0
  5. phantomrt-0.1.0/atlas/agents/__init__.py +8 -0
  6. phantomrt-0.1.0/atlas/agents/command_space.py +227 -0
  7. phantomrt-0.1.0/atlas/analysis/__init__.py +3 -0
  8. phantomrt-0.1.0/atlas/analysis/binary_agent.py +488 -0
  9. phantomrt-0.1.0/atlas/analysis/binary_fuzz.py +389 -0
  10. phantomrt-0.1.0/atlas/analysis/frida_live.py +261 -0
  11. phantomrt-0.1.0/atlas/analysis/graph_annotator.py +147 -0
  12. phantomrt-0.1.0/atlas/analysis/spectrida_bridge.py +84 -0
  13. phantomrt-0.1.0/atlas/analysis/unicorn_harness.py +337 -0
  14. phantomrt-0.1.0/atlas/core/__init__.py +14 -0
  15. phantomrt-0.1.0/atlas/core/decoder.py +65 -0
  16. phantomrt-0.1.0/atlas/core/dynamics.py +217 -0
  17. phantomrt-0.1.0/atlas/core/encoder.py +120 -0
  18. phantomrt-0.1.0/atlas/core/surprise.py +145 -0
  19. phantomrt-0.1.0/atlas/core/world_model.py +334 -0
  20. phantomrt-0.1.0/atlas/environments/__init__.py +5 -0
  21. phantomrt-0.1.0/atlas/environments/base.py +51 -0
  22. phantomrt-0.1.0/atlas/environments/grid_world.py +219 -0
  23. phantomrt-0.1.0/atlas/environments/physics_2d.py +283 -0
  24. phantomrt-0.1.0/atlas/environments/vm_world.py +168 -0
  25. phantomrt-0.1.0/atlas/knowledge/__init__.py +3 -0
  26. phantomrt-0.1.0/atlas/knowledge/instruction_vocab.py +534 -0
  27. phantomrt-0.1.0/atlas/monitor/__init__.py +5 -0
  28. phantomrt-0.1.0/atlas/monitor/execution_monitor.py +518 -0
  29. phantomrt-0.1.0/atlas/optimization/__init__.py +6 -0
  30. phantomrt-0.1.0/atlas/optimization/speed.py +457 -0
  31. phantomrt-0.1.0/atlas/planning/__init__.py +4 -0
  32. phantomrt-0.1.0/atlas/planning/goal.py +100 -0
  33. phantomrt-0.1.0/atlas/planning/mcts.py +228 -0
  34. phantomrt-0.1.0/atlas/training/__init__.py +4 -0
  35. phantomrt-0.1.0/atlas/training/continual.py +392 -0
  36. phantomrt-0.1.0/atlas/training/growth.py +213 -0
  37. phantomrt-0.1.0/atlas/training/loop.py +306 -0
  38. phantomrt-0.1.0/atlas/training/losses.py +101 -0
  39. phantomrt-0.1.0/atlas/training/self_train.py +307 -0
  40. phantomrt-0.1.0/atlas/utils/__init__.py +4 -0
  41. phantomrt-0.1.0/atlas/utils/logging.py +33 -0
  42. phantomrt-0.1.0/atlas/utils/math_helpers.py +30 -0
  43. phantomrt-0.1.0/atlas/utils/viz.py +136 -0
  44. phantomrt-0.1.0/atlas/vm/__init__.py +4 -0
  45. phantomrt-0.1.0/atlas/vm/wsl_vm.py +249 -0
  46. phantomrt-0.1.0/phantomrt.egg-info/PKG-INFO +75 -0
  47. phantomrt-0.1.0/phantomrt.egg-info/SOURCES.txt +64 -0
  48. phantomrt-0.1.0/phantomrt.egg-info/dependency_links.txt +1 -0
  49. phantomrt-0.1.0/phantomrt.egg-info/entry_points.txt +3 -0
  50. phantomrt-0.1.0/phantomrt.egg-info/requires.txt +19 -0
  51. phantomrt-0.1.0/phantomrt.egg-info/top_level.txt +1 -0
  52. phantomrt-0.1.0/pyproject.toml +67 -0
  53. phantomrt-0.1.0/setup.cfg +4 -0
  54. phantomrt-0.1.0/tests/test_binary_fuzz.py +89 -0
  55. phantomrt-0.1.0/tests/test_dynamics.py +93 -0
  56. phantomrt-0.1.0/tests/test_emulated_fuzz.py +54 -0
  57. phantomrt-0.1.0/tests/test_encoder.py +86 -0
  58. phantomrt-0.1.0/tests/test_frida_live.py +83 -0
  59. phantomrt-0.1.0/tests/test_graph_annotator.py +112 -0
  60. phantomrt-0.1.0/tests/test_growth.py +74 -0
  61. phantomrt-0.1.0/tests/test_planning.py +73 -0
  62. phantomrt-0.1.0/tests/test_self_train.py +91 -0
  63. phantomrt-0.1.0/tests/test_surprise.py +90 -0
  64. phantomrt-0.1.0/tests/test_unicorn_harness.py +56 -0
  65. phantomrt-0.1.0/tests/test_vm_world.py +57 -0
  66. phantomrt-0.1.0/tests/test_world_model.py +76 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ggfuchsi-oss
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: phantomrt
3
+ Version: 0.1.0
4
+ Summary: Atlas — dynamic reverse-engineering: emulate, live-instrument, and fuzz functions, with a self-improving world model. The runtime companion to spectrIDA.
5
+ Author: ggfuchsi-oss
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ggfuchsi-oss/spectrIDA-Reverse_Engineering_Stack
8
+ Project-URL: Repository, https://github.com/ggfuchsi-oss/spectrIDA-Reverse_Engineering_Stack
9
+ Keywords: reverse-engineering,fuzzing,emulation,unicorn,frida,binary-analysis,world-model,security
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Security
15
+ Classifier: Topic :: Software Development :: Disassemblers
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: numpy>=1.24.0
20
+ Requires-Dist: torch>=2.1.0
21
+ Requires-Dist: torchdiffeq>=0.2.3
22
+ Requires-Dist: unicorn>=2.0.0
23
+ Requires-Dist: capstone>=5.0.0
24
+ Requires-Dist: neo4j>=5.0.0
25
+ Requires-Dist: tqdm>=4.65.0
26
+ Provides-Extra: live
27
+ Requires-Dist: frida>=16.0; extra == "live"
28
+ Provides-Extra: viz
29
+ Requires-Dist: matplotlib>=3.7.0; extra == "viz"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
32
+ Requires-Dist: keystone-engine>=0.9.2; extra == "dev"
33
+ Requires-Dist: black>=23.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # 🧠 PROJECT ATLAS — World Model AI
38
+
39
+ > An AI that doesn't just predict — it **understands**. Builds an internal model of reality, imagines futures, and plans actions.
40
+
41
+ ## Architecture
42
+
43
+ ```
44
+ Observation → [Encoder] → Latent State → [Neural ODE Dynamics] → Future State
45
+ ↑ ↓
46
+ Real World [Decoder] → Prediction
47
+
48
+ Surprise Detection
49
+ (only learn from surprises)
50
+ ```
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ # Install
56
+ cd project_atlas
57
+ pip install -e ".[dev]"
58
+
59
+ # Train on grid world
60
+ python scripts/train.py --env grid_world
61
+
62
+ # Visualize imagined trajectories
63
+ python scripts/imagine.py --checkpoint experiments/phase1_v1/best.pt
64
+
65
+ # Run tests
66
+ pytest tests/ -v
67
+ ```
68
+
69
+ ## Status
70
+
71
+ - [x] Phase 1: Core Engine (in progress)
72
+ - [ ] Phase 2: Perception Upgrade
73
+ - [ ] Phase 3: Causal Reasoning
74
+ - [ ] Phase 4: Continuous Learning
75
+ - [ ] Phase 5: Scale + Integration
@@ -0,0 +1,39 @@
1
+ # 🧠 PROJECT ATLAS — World Model AI
2
+
3
+ > An AI that doesn't just predict — it **understands**. Builds an internal model of reality, imagines futures, and plans actions.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ Observation → [Encoder] → Latent State → [Neural ODE Dynamics] → Future State
9
+ ↑ ↓
10
+ Real World [Decoder] → Prediction
11
+
12
+ Surprise Detection
13
+ (only learn from surprises)
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Install
20
+ cd project_atlas
21
+ pip install -e ".[dev]"
22
+
23
+ # Train on grid world
24
+ python scripts/train.py --env grid_world
25
+
26
+ # Visualize imagined trajectories
27
+ python scripts/imagine.py --checkpoint experiments/phase1_v1/best.pt
28
+
29
+ # Run tests
30
+ pytest tests/ -v
31
+ ```
32
+
33
+ ## Status
34
+
35
+ - [x] Phase 1: Core Engine (in progress)
36
+ - [ ] Phase 2: Perception Upgrade
37
+ - [ ] Phase 3: Causal Reasoning
38
+ - [ ] Phase 4: Continuous Learning
39
+ - [ ] Phase 5: Scale + Integration
@@ -0,0 +1,3 @@
1
+ """Project Atlas — World Model AI that understands reality."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,8 @@
1
+ """Agent-side pieces: the action space (command proposer + embedding)."""
2
+ from .command_space import (
3
+ CommandProposer, embed_command, command_family, primary_binary, ACTION_DIM,
4
+ )
5
+
6
+ __all__ = [
7
+ "CommandProposer", "embed_command", "command_family", "primary_binary", "ACTION_DIM",
8
+ ]
@@ -0,0 +1,227 @@
1
+ """
2
+ The action space: proposing shell commands and embedding them.
3
+
4
+ Two jobs:
5
+
6
+ 1. ``embed_command`` — turn a command string into a fixed, *structured* vector.
7
+ The embedding is deliberately compositional: it encodes the command's family,
8
+ argument structure, operators, and intent — NOT a memorized id. This is what
9
+ lets the world model generalize (predict `grep -c` from having learned `grep`
10
+ and `wc -c` separately) instead of memorizing exact strings.
11
+
12
+ 2. ``CommandProposer`` — generate candidate commands for the agent to choose
13
+ among. Unrestricted: bare binaries, discovered files, mutations/compositions
14
+ of past commands, file creation, compiling & running code, and yes destructive
15
+ ops too. The VM boundary + snapshot rollback are the containment, not a filter.
16
+ A self-expanding library of *working* commands becomes new building blocks —
17
+ the action space itself grows as the agent discovers what the machine offers.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import random
23
+ import re
24
+ import shlex
25
+ import numpy as np
26
+
27
+
28
+ ACTION_DIM = 32
29
+
30
+ # ── binary → (family, intent) knowledge, used only to *structure* the embedding.
31
+ # Unknown binaries fall back to "misc"; the agent still runs and learns them.
32
+ _FAMILY = {
33
+ "text": ["grep", "sed", "awk", "cut", "sort", "uniq", "tr", "wc", "head",
34
+ "tail", "cat", "tac", "rev", "fold", "paste", "join", "column", "nl"],
35
+ "file": ["ls", "cp", "mv", "rm", "mkdir", "rmdir", "touch", "stat", "find",
36
+ "ln", "readlink", "basename", "dirname", "du", "df", "file", "tree"],
37
+ "archive": ["tar", "gzip", "gunzip", "zip", "unzip", "xz", "bzip2", "cpio"],
38
+ "compile": ["gcc", "g++", "cc", "make", "ld", "as", "ar", "objdump", "nm", "strip"],
39
+ "interp": ["python3", "python", "perl", "bash", "sh", "node", "ruby", "lua", "awk"],
40
+ "proc": ["ps", "top", "kill", "pkill", "nice", "nohup", "jobs", "sleep",
41
+ "timeout", "watch", "pgrep", "pidof"],
42
+ "perm": ["chmod", "chown", "chgrp", "umask", "id", "whoami", "groups", "sudo"],
43
+ "system": ["uname", "hostname", "uptime", "date", "env", "printenv", "free",
44
+ "lscpu", "mount", "dmesg", "sysctl", "ulimit"],
45
+ "net": ["ip", "ss", "ping", "curl", "wget", "netstat", "nc", "host", "dig"],
46
+ "shell": ["echo", "printf", "test", "true", "false", "seq", "yes", "xargs",
47
+ "tee", "read", "expr", "let", "type", "which", "command"],
48
+ }
49
+ _BIN2FAM = {b: fam for fam, bins in _FAMILY.items() for b in bins}
50
+ _FAMILIES = list(_FAMILY.keys()) + ["misc"]
51
+
52
+ # rough intent per family (reads / writes / creates / deletes / executes / info)
53
+ _INTENT = {
54
+ "text": (1, 0, 0, 0, 0, 1), "file": (1, 1, 1, 1, 0, 1),
55
+ "archive":(1, 1, 1, 0, 0, 0), "compile":(1, 1, 1, 0, 1, 0),
56
+ "interp": (1, 1, 1, 0, 1, 0), "proc": (1, 0, 0, 1, 1, 1),
57
+ "perm": (1, 1, 0, 0, 0, 1), "system":(1, 0, 0, 0, 0, 1),
58
+ "net": (1, 1, 0, 0, 1, 1), "shell": (0, 1, 1, 0, 0, 1),
59
+ "misc": (1, 0, 0, 0, 1, 0),
60
+ }
61
+ # commands that tend to break the box — tracked as a feature, NOT blocked.
62
+ _DANGER = ("rm ", "rm -", "dd ", "mkfs", ":(){", "shutdown", "reboot", "> /dev",
63
+ "chmod -R", "chown -R", "mv /", "> /etc", "kill -9 -1")
64
+
65
+
66
+ def primary_binary(command: str) -> str:
67
+ """First real program token in a command (skips `sudo`, env assignments)."""
68
+ try:
69
+ toks = shlex.split(command)
70
+ except ValueError:
71
+ toks = command.split()
72
+ for t in toks:
73
+ if "=" in t and not t.startswith("-"): # VAR=val prefix
74
+ continue
75
+ if t in ("sudo", "nohup", "time", "nice", "timeout", "env"):
76
+ continue
77
+ return t.split("/")[-1]
78
+ return toks[0].split("/")[-1] if toks else ""
79
+
80
+
81
+ def embed_command(command: str) -> np.ndarray:
82
+ """Structured, compositional embedding of a command → [ACTION_DIM] in ~[0,1]."""
83
+ v = np.zeros(ACTION_DIM, dtype=np.float32)
84
+ cmd = command.strip()
85
+ binn = primary_binary(cmd)
86
+ fam = _BIN2FAM.get(binn, "misc")
87
+
88
+ # [0:11] family one-hot
89
+ v[_FAMILIES.index(fam)] = 1.0
90
+ # [11:17] intent bits for the family
91
+ v[11:17] = np.array(_INTENT[fam], dtype=np.float32)
92
+
93
+ try:
94
+ toks = shlex.split(cmd)
95
+ except ValueError:
96
+ toks = cmd.split()
97
+ args = toks[1:] if toks else []
98
+
99
+ # [17:32] structural features (all bounded)
100
+ v[17] = min(len(toks) / 8.0, 1.0) # n tokens
101
+ v[18] = min(len(cmd) / 80.0, 1.0) # length
102
+ v[19] = min(sum(a.startswith("-") for a in args) / 4.0, 1.0) # flags
103
+ v[20] = 1.0 if "|" in cmd else 0.0 # pipe
104
+ v[21] = 1.0 if (">" in cmd or ">>" in cmd) else 0.0 # redirect out
105
+ v[22] = 1.0 if "<" in cmd else 0.0 # redirect in
106
+ v[23] = 1.0 if any(c in cmd for c in "*?[") else 0.0 # glob
107
+ v[24] = min(sum("/" in a for a in args) / 3.0, 1.0) # path args
108
+ v[25] = min(sum(bool(re.fullmatch(r"-?\d+", a)) for a in args) / 3.0, 1.0) # numeric
109
+ v[26] = 1.0 if ("$(" in cmd or "`" in cmd) else 0.0 # subshell
110
+ v[27] = 1.0 if ("&&" in cmd or ";" in cmd or "||" in cmd) else 0.0 # chained
111
+ v[28] = 1.0 if cmd.rstrip().endswith("&") else 0.0 # background
112
+ v[29] = 1.0 if any(d in cmd for d in _DANGER) else 0.0 # destructive
113
+ v[30] = 1.0 if binn in _BIN2FAM else 0.0 # known binary
114
+ v[31] = 1.0 if ("--help" in cmd or " -h" in cmd or binn == "man") else 0.0 # self-doc
115
+ return v
116
+
117
+
118
+ def command_family(command: str) -> str:
119
+ """The behavior family a command belongs to (for per-family competence)."""
120
+ return _BIN2FAM.get(primary_binary(command), "misc")
121
+
122
+
123
+ class CommandProposer:
124
+ """Generates candidate commands. Unrestricted and self-expanding."""
125
+
126
+ def __init__(self, vm, rng: random.Random | None = None):
127
+ self.vm = vm
128
+ self.rng = rng or random.Random(0)
129
+ self.binaries: list[str] = []
130
+ self.files: set[str] = {"~", "/tmp", "/etc/hostname", "/proc/cpuinfo"}
131
+ # library of commands observed to *work* — grows into new building blocks
132
+ self.library: list[str] = [
133
+ "echo hello", "ls -la", "pwd", "whoami", "uname -a",
134
+ "cat /etc/os-release", "ls /usr/bin | head", "seq 1 5",
135
+ ]
136
+ self._discovered = False
137
+
138
+ # ── discovery ────────────────────────────────────────────────────────────
139
+ def discover(self) -> None:
140
+ """One-time enumeration of what the machine offers (PATH binaries)."""
141
+ r = self.vm.run("ls /usr/bin /bin 2>/dev/null | sort -u", timeout=20)
142
+ bins = [b.strip() for b in r.stdout.splitlines() if b.strip() and "/" not in b]
143
+ self.binaries = bins or list(_BIN2FAM.keys())
144
+ self._discovered = True
145
+
146
+ def observe(self, command: str, result) -> None:
147
+ """Learn from a run: keep working commands, harvest discovered paths."""
148
+ if result.exit_code == 0 and command not in self.library:
149
+ if len(self.library) < 2000:
150
+ self.library.append(command)
151
+ # harvest path-looking tokens from output the agent just saw
152
+ for tok in re.findall(r"/[\w./-]+", result.stdout[:4000]):
153
+ if len(self.files) < 5000:
154
+ self.files.add(tok)
155
+
156
+ # ── proposing ────────────────────────────────────────────────────────────
157
+ def propose(self, n: int = 16) -> list[str]:
158
+ if not self._discovered:
159
+ self.discover()
160
+ cands: set[str] = set()
161
+ strategies = [
162
+ self._bare_binary, self._binary_help, self._on_file, self._mutate,
163
+ self._compose_pipe, self._explore_fs, self._create_and_run, self._write_code,
164
+ ]
165
+ guard = 0
166
+ while len(cands) < n and guard < n * 6:
167
+ guard += 1
168
+ try:
169
+ c = self.rng.choice(strategies)()
170
+ except Exception:
171
+ c = None
172
+ if c:
173
+ cands.add(c.strip())
174
+ return list(cands)[:n]
175
+
176
+ def _rand_bin(self) -> str:
177
+ return self.rng.choice(self.binaries) if self.binaries else "echo"
178
+
179
+ def _rand_file(self) -> str:
180
+ return self.rng.choice(sorted(self.files))
181
+
182
+ def _bare_binary(self) -> str:
183
+ return self._rand_bin()
184
+
185
+ def _binary_help(self) -> str:
186
+ return f"{self._rand_bin()} --help 2>&1 | head -5"
187
+
188
+ def _on_file(self) -> str:
189
+ b = self.rng.choice(["cat", "ls -la", "stat", "wc -l", "head", "file", "du -h"])
190
+ return f"{b} {self._rand_file()}"
191
+
192
+ def _mutate(self) -> str:
193
+ base = self.rng.choice(self.library)
194
+ pipe = self.rng.choice(["| head -3", "| wc -l", "| sort", "| grep -c .", "| tr a-z A-Z"])
195
+ return f"{base} 2>&1 {pipe}"
196
+
197
+ def _compose_pipe(self) -> str:
198
+ a, b = self.rng.choice(self.library), self.rng.choice(
199
+ ["wc -c", "grep .", "sort", "uniq -c", "head -4", "tac", "rev"])
200
+ return f"{a} 2>/dev/null | {b}"
201
+
202
+ def _explore_fs(self) -> str:
203
+ return self.rng.choice([
204
+ f"ls -la {self._rand_file()}", "find / -maxdepth 2 -type d 2>/dev/null | head",
205
+ "ls /proc | head", f"cat {self._rand_file()} 2>&1 | head -3",
206
+ "df -h", "free -m", "ps aux | head", "env | head",
207
+ ])
208
+
209
+ def _create_and_run(self) -> str:
210
+ n = self.rng.randint(1, 999)
211
+ return self.rng.choice([
212
+ f"echo data{n} > /tmp/f{n}.txt && cat /tmp/f{n}.txt",
213
+ f"mkdir -p /tmp/d{n} && ls -la /tmp/d{n}",
214
+ f"seq 1 {n % 20 + 1} | sort -r",
215
+ f"printf 'a\\nb\\nc\\n' | grep b",
216
+ ])
217
+
218
+ def _write_code(self) -> str:
219
+ """Write and execute real code — learn compiling/running mechanics."""
220
+ n = self.rng.randint(1, 999)
221
+ return self.rng.choice([
222
+ f"python3 -c 'print(sum(range({n % 50 + 1})))'",
223
+ f"echo 'int main(){{return {n % 5};}}' > /tmp/p{n}.c "
224
+ f"&& gcc /tmp/p{n}.c -o /tmp/p{n} 2>&1 && /tmp/p{n}; echo rc=$?",
225
+ f"python3 -c 'import os; print(os.listdir(\"/tmp\")[:5])'",
226
+ f"echo 'print(2**{n % 16})' | python3",
227
+ ])
@@ -0,0 +1,3 @@
1
+ from .binary_agent import BinaryAnalysisAgent
2
+
3
+ __all__ = ["BinaryAnalysisAgent"]