Off Apple the xz container was unpacked by running /usr/bin/env xz, which Windows has no answer for: Process reports that the file does not exist, and the message reaches the user as it stands. Decode in-process instead, the way Compression already does on Apple, and ask for the library the platforms package.
209 lines
6.3 KiB
Markdown
209 lines
6.3 KiB
Markdown
# Luma
|
|
|
|
Interactive dynamic instrumentation app built on
|
|
[Frida](https://frida.re). All business logic lives in **LumaCore**,
|
|
a cross-platform Swift package; the current shipping frontend is a
|
|
macOS SwiftUI app, with a GTK/Adwaita frontend for Linux on the way.
|
|
|
|
## Repository layout
|
|
|
|
```
|
|
Sources/LumaCore/ # cross-platform Swift package — engine, sessions,
|
|
# persistence, disassembly, collaboration, hook
|
|
# packs, GitHub auth, address annotations, …
|
|
Agent/ # TypeScript agent injected into the target process
|
|
Luma/ # macOS SwiftUI frontend
|
|
Luma.xcodeproj/ # Xcode project (Luma app + LumaBundleCompiler)
|
|
Package.swift # SPM manifest for LumaCore
|
|
```
|
|
|
|
## Requirements
|
|
|
|
- macOS ≥ 15.0
|
|
- Xcode ≥ 26 (with the Metal toolchain installed — open Xcode once
|
|
and accept the Metal SDK download prompt, or install it via
|
|
**Settings → Components**)
|
|
|
|
`LumaCore` itself only needs Swift 6 and the package dependencies
|
|
listed in `Package.swift`. It builds on Linux too:
|
|
|
|
```sh
|
|
swift build --target LumaCore
|
|
```
|
|
|
|
## Building the macOS app
|
|
|
|
### Option 1: Xcode (recommended)
|
|
|
|
1. Open the project:
|
|
|
|
```sh
|
|
open Luma.xcodeproj
|
|
```
|
|
|
|
2. Ensure the build destination is set to **My Mac** (Luma currently
|
|
uses AppKit-only components and does not yet build for iOS).
|
|
|
|
3. Choose **Product → Build** (⌘B).
|
|
|
|
This performs an incremental build and is the most convenient
|
|
workflow during development.
|
|
|
|
### Option 2: Command line (also incremental)
|
|
|
|
A `Makefile` is provided for building Luma without opening Xcode.
|
|
This build is **also incremental**, because it uses a persistent
|
|
derived-data directory.
|
|
|
|
The output app is produced in `./build/`, and intermediate build
|
|
files are stored in `./build/.derived`.
|
|
|
|
To build:
|
|
|
|
```sh
|
|
make
|
|
```
|
|
|
|
To clean:
|
|
|
|
```sh
|
|
make clean
|
|
```
|
|
|
|
The resulting app will be located at:
|
|
|
|
build/Luma.app
|
|
|
|
## Nix
|
|
|
|
Luma provides a [Nix](https://nixos.org) flake for running and
|
|
installing on Linux:
|
|
|
|
```sh
|
|
nix run github:frida/luma # run Luma without installing
|
|
nix shell github:frida/luma # shell with luma in PATH
|
|
nix build github:frida/luma # build into the Nix store
|
|
```
|
|
|
|
The flake exposes an overlay so you can add Luma to your own Nix
|
|
configuration:
|
|
|
|
```nix
|
|
inputs.luma.url = "github:frida/luma";
|
|
nixpkgs.overlays = [ luma.overlays.default ];
|
|
```
|
|
|
|
After applying the overlay, `pkgs.luma` is available in your
|
|
package set.
|
|
|
|
## Building the GTK frontend (Linux)
|
|
|
|
### Prerequisites (Fedora)
|
|
|
|
Install the toolchains and `-devel` packages for Luma and its native
|
|
dependencies:
|
|
|
|
```sh
|
|
sudo dnf install -y \
|
|
gcc-c++ libstdc++-static patch golang-bin nodejs swift-lang \
|
|
libadwaita-devel atk-devel \
|
|
libepoxy-devel librsvg2-devel \
|
|
libgee-devel json-glib-devel libsoup3-devel xz-devel \
|
|
libunwind-devel libdwarf-devel libnice-devel \
|
|
ngtcp2-crypto-ossl-devel libbpf-devel capstone-devel \
|
|
lzfse-devel
|
|
```
|
|
|
|
Build and install `frida-core` into `/usr/local` (Fedora's `libbpf`
|
|
is too old, so force a subproject fallback):
|
|
|
|
```sh
|
|
cd ~/src
|
|
git clone [email protected]:frida/frida-core.git
|
|
cd frida-core
|
|
./configure --enable-shared --without-prebuilds=sdk \
|
|
--enable-barebone-backend --enable-compiler-backend \
|
|
-- --force-fallback-for=libbpf
|
|
make
|
|
sudo make install
|
|
```
|
|
|
|
Build and install `radare2` into `/usr/local`. The stock
|
|
`sys/install.sh` builds without optimization, so override `CFLAGS`
|
|
and strip unused code with `--gc-sections`:
|
|
|
|
```sh
|
|
cd ~/src
|
|
git clone [email protected]:radareorg/radare2.git
|
|
cd radare2
|
|
CFLAGS="-O2 -g -ffunction-sections -fdata-sections" \
|
|
LDFLAGS="-Wl,--gc-sections" \
|
|
./sys/install.sh --install
|
|
```
|
|
|
|
### Build and run
|
|
|
|
From `LumaGtk/`:
|
|
|
|
```sh
|
|
make # incremental build → .build/debug/LumaGtk
|
|
make run # build + launch
|
|
make install PREFIX=/usr/local
|
|
```
|
|
|
|
## Building the GTK frontend (Windows)
|
|
|
|
Install four things by hand, then let the scripts do the rest:
|
|
|
|
- **Visual Studio 2022** (or the Build Tools) with the *Desktop
|
|
development with C++* workload
|
|
- **[Swift for Windows](https://www.swift.org/install/windows/)** 6.2 or
|
|
newer, on `PATH`
|
|
- **Python 3** and **Node.js**, on `PATH`
|
|
- **Git for Windows**
|
|
|
|
Nothing else has to be a Developer PowerShell: the scripts load the MSVC
|
|
environment themselves. From `LumaGtk/`, in an ordinary PowerShell:
|
|
|
|
```powershell
|
|
.\scripts\windows\bootstrap.ps1 # one-time, ~1-2h
|
|
.\scripts\windows\build.ps1 # debug
|
|
.\scripts\windows\build.ps1 -Configuration release
|
|
.\scripts\windows\package-msi.ps1 -Version 0.1.0 # build\Luma-*.msi
|
|
.\scripts\windows\run.ps1 # launch with DLL PATH set
|
|
```
|
|
|
|
`bootstrap.ps1` provisions everything the build links against —
|
|
vcpkg with GTK 4, libadwaita and GtkSourceView, then `frida-core`,
|
|
`radare2` and a Pharo VM built from source — into
|
|
`%LOCALAPPDATA%\Luma\windows-deps`. It skips whatever is already
|
|
there, so re-running it after a failure resumes rather than restarts,
|
|
and `-Only <component>` (`vcpkg`, `gnu-tools`, `frida-core`,
|
|
`radare2`, `pharo-vm`) rebuilds just one. The upstream revisions come
|
|
from `.github/dependency-refs.env`, and CI runs the same script one
|
|
component at a time, so what a contributor builds is what CI builds.
|
|
|
|
One thing bootstrap cannot do for you: radare2 ships a collection of
|
|
shellcode as source, and Windows Defender quarantines it mid-build,
|
|
which surfaces as `fatal error C1083: Cannot open include file` for a
|
|
generated file. Bootstrap asks Defender what it took and says so, but
|
|
excluding a directory from your antivirus is your call to make, not a
|
|
build script's — from an elevated PowerShell:
|
|
|
|
```powershell
|
|
Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\Luma\windows-deps"
|
|
```
|
|
|
|
Or point `-R2Prefix` at a radare2 you already have and skip it.
|
|
|
|
No distribution packages a Pharo VM, and the one bootstrap builds comes
|
|
from our fork, which carries the Meson build and the tweaks that make it
|
|
compile with MSVC. It generates its own interpreter sources, so Meson,
|
|
Ninja and Python are all it needs beyond the compiler — bootstrap
|
|
installs the first two if they are missing.
|
|
|
|
Prefixes are found in `%LOCALAPPDATA%\Luma\windows-deps` first, then the
|
|
older `C:\vcpkg`, `C:\src\dist` and `C:\src\pharo` locations; override
|
|
any of them with `-VcpkgPrefix`, `-FridaPrefix`, `-R2Prefix`,
|
|
`-PharoPrefix` (or `$env:VCPKG_PREFIX` etc.) on every script here.
|