Files

237 lines
9.7 KiB
Markdown

# Using r2xsql with radare2 and an agent
The plugin supplies SQL over a live radare2 core. The skills teach an agent
how to choose tables, query and annotate that core, and manage its lifetime.
The user can ask in natural language in either tandem or headless mode.
## Installation
Install radare2, then install a matching r2xsql plugin:
```sh
r2pm -U
r2pm -bi r2xsql
```
Release `v0.0.1` targets radare2 6.2.6. For a source build on Linux/macOS,
use `r2pm -ci r2xsql` or `make user-install`. Windows source builds use
`cmake --build build --config Release --target user-install` after
[configuring CMake](development.md).
Installed plugins load automatically on normal startup. `make user-install`
does the same for a local build. Manual installation uses the directory
reported by `r2 -NN -H R2_USER_PLUGINS`. Restart a host after installation.
The plugin's radare2 ABI must match the engine loading it; iaito can use a
different engine from the standalone r2 on PATH. Binary installation with
`r2pm -bi r2xsql` requires an available asset matching the host and platform.
See [building and packaging](development.md).
For a build that is not installed:
```sh
r2 -i ./core_r2xsql.so -A ./target
```
Use the actual `.so`, `.dylib` or `.dll` file. `-i` also accepts native r2
command scripts. Inside an existing console, load a plugin with
`L ./core_r2xsql.so`; `L r2xsql` is not a package-name loader.
`-N` skips startup scripts while retaining plugins; `-NN` disables automatic
plugin loading too. For a deterministic local-build check, use `-NN -i FILE`.
Verify `r2xsql` in `Lcj`, then try `sql?` and `sqlj SELECT 1`.
Install the [r2xsql skills](https://github.com/radareorg/radare2-skills/tree/main/r2xsql#install)
in the coding agent's harness. Skills and the binary plugin are separate
installations. The harness selects the `r2xsql` entry skill and routes to
connection and domain instructions; explicit skill selection can be used
when the harness does not select it automatically.
## Tandem mode
Tandem shares an existing analysis in an interactive r2 CLI, its visual/panels
text interface, or [iaito](https://github.com/radareorg/iaito). For a fresh
binary run `r2 -A ./target`, or open it in iaito and let analysis finish.
For a saved project run `r2 -p PROJECT` without `-A`.
At the r2 prompt or iaito's **View > Console**, verify the plugin with `Lcj`,
then start background HTTP:
```text
e http.bind=127.0.0.1
e http.sandbox=false
e http.port=9090
=h&
```
Choose a free port. `http.port` selects it; `=h&` starts the background
server and leaves the console/UI available. It is an alias for `& =h`,
using r2's background-task facility. `=h` serves in the foreground instead.
Start HTTP at the prompt before entering the text interface.
Wait for `open http://127.0.0.1:9090/`, then tell the agent:
> Use r2xsql at http://127.0.0.1:9090 on the binary already open here.
> Show me the largest functions.
The agent checks the host, plugin and binary identity, authors SQL and reuses
the endpoint on later questions. It should not open another UI or rerun
analysis merely to attach. Renames and comments affect the human's analysis
too. Take turns with the agent when running analysis-changing native commands.
Use `=h-` at the interactive console to stop background HTTP while keeping
the human's host open.
For several hosts, select a distinct port per process and provide a mapping:
**application = http://127.0.0.1:9090, library = http://127.0.0.1:9091**.
The agent verifies each target and labels findings by source. SQL executes
inside one host; comparisons across hosts combine results in the client.
## Fully headless
With the plugin installed, an agent can start the native r2 process without
a human console or GUI. For a fresh binary, POSIX shell:
```sh
r2 -N -q -A -e scr.html=false -e http.bind=127.0.0.1 \
-e http.sandbox=false -e http.port=9090 -c '=h' ./target \
>r2.stdout.log 2>r2.stderr.log &
r2_pid=$!
```
Windows PowerShell:
```powershell
$engine = Get-Command r2,radare2 -CommandType Application -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $engine) { throw 'Install radare2 or supply its executable location.' }
$target = (Resolve-Path -LiteralPath '.\target.exe').Path
$port = 9090 # choose a free port
$logDir = Join-Path $env:TEMP ('r2-session-' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $logDir | Out-Null
$arguments = '-N -q -A -e scr.html=false -e http.bind=127.0.0.1 -e http.sandbox=false -e http.port={0} -c "=h" "{1}"' -f $port,$target
$process = Start-Process -FilePath $engine.Source -ArgumentList $arguments -WindowStyle Hidden `
-RedirectStandardOutput (Join-Path $logDir 'stdout.log') `
-RedirectStandardError (Join-Path $logDir 'stderr.log') -PassThru
$endpoint = 'http://127.0.0.1:{0}/cmd/' -f $port
```
These launch radare2 directly. No Python session/query wrapper or build
orchestrator is needed. `-A` runs analysis once; foreground `=h` keeps the
background OS process alive. Queries use that same core until shutdown.
For an uninstalled plugin, substitute `-NN -i PLUGIN_FILE` for `-N`.
Wait for the server banner on stderr, then verify the endpoint with curl.
A bind failure is not readiness. Retain the PID, endpoint, binary/project
and log locations; subsequent prompts reuse this session.
## HTTP queries
For radare2 **6.2.4**, POST the complete r2 command to `/cmd/`:
```sh
curl -d '?V' http://127.0.0.1:9090/cmd/
curl -d 'Lcj' http://127.0.0.1:9090/cmd/
curl -d '"sqlj SELECT * FROM binary"' http://127.0.0.1:9090/cmd/
curl -d '"sqlj SELECT name,size FROM funcs WHERE size > 100 LIMIT 5"' \
http://127.0.0.1:9090/cmd/
```
In PowerShell use `curl.exe` to avoid the shell alias:
```powershell
$command = '"sqlj SELECT name,size FROM funcs ORDER BY size DESC LIMIT 10"'
curl.exe --silent --show-error --max-time 30 -d $command $endpoint
```
The body is an r2 command. The **double quotes are part of that body** and
protect SQL operators such as `>` and `|` from r2's parser. Use `sqlj`
for the JSON envelope; `sql,:json` is a table format with different NULL and
empty-string behavior. Inspect top-level and per-statement success/error
fields; HTTP 200 alone does not establish success. See [SQL access](sql.md).
Native commands such as `pdf` and `Ps` travel over the same endpoint.
The command-prefix-plus-body form is implemented in development radare2
and is planned for **6.2.6**:
```sh
curl -d 'SELECT name,size FROM funcs ORDER BY size DESC LIMIT 5' \
http://127.0.0.1:9090/cmd/sqlj
```
Here the URL selects `sqlj` and the body contains only SQL. This is a
version-dependent alternative, not a 6.2.4 example. Use the full-command
form until the host is known to support it. An agent should verify the JSON
response to a harmless query before choosing this form for mutations.
The combined command still passes through r2's parser. For SQL containing
operators such as `>` or `|`, keep the full double-quoted command form above.
## Saving and reopening
Analysis lives in memory until saved. Ask the agent to save the project beside
the binary, or select another location. The save operation is native radare2;
there is no SQL `save_database()` in r2xsql.
```sh
curl -d 'Ps /absolute/path/target.exe.r2' http://127.0.0.1:9090/cmd/
```
PowerShell, using the absolute target path from the launch:
```powershell
$project = ($target + '.r2').Replace('\','/')
curl.exe --silent --show-error --max-time 30 -d ('Ps ' + $project) $endpoint
Get-Item -LiteralPath $project
```
Use forward slashes in native r2 commands on Windows. Verify the actual saved
artifact, host log and requested annotations; a refused save can return an
empty HTTP 200. Keep the original binary and any companion `.r2.d` directory.
Saving analysis does not patch the executable or shut down the host.
Reopen the saved project with `-p`, without a separate target or reanalysis:
```sh
r2 -N -q -p /absolute/path/target.exe.r2 \
-e scr.html=false -e http.bind=127.0.0.1 \
-e http.sandbox=false -e http.port=9090 -c '=h' \
>r2.stdout.log 2>r2.stderr.log &
```
The project stores the binary path. On Windows replace `-A` and the target
in the launch arguments with `-p "PROJECT"`; keep the same `-e` options
and `-c "=h"`. Verify binary identity and saved annotations after reopening,
rather than checking only function counts. Preserve the checkpoint and logs
if verification fails.
### Projects and command scripts
Native projects support binary serialization and script compatibility; do not
infer their format from the filename alone. `Ps PROJECT` and `-p PROJECT`
are the normal save/reopen interface. A bare project name uses `dir.projects`;
an absolute filename selects a sidecar. `Pl` lists named projects, not every
sidecar elsewhere.
Where available, `prj?` documents the binary-container operations, including
`prj save FILE` and `prj open FILE`. Select the matching native loader for
an existing container; a standalone container is not interchangeable with a
named `-p` project on every host. Explicit command-script exports use `PS`
or `PS*` and can be interpreted with `-i SCRIPT`; they are not a reason to
describe all projects as scripts. Check `P?` and `prj?` on the chosen host.
## Shutdown and session ownership
On a save-and-shutdown request, save and verify first, then stop an agent-owned
foreground server:
```sh
curl 'http://127.0.0.1:9090/cmd/=h--'
```
`=h--` is intercepted in the GET path; putting it in a POST body does not
stop that accept loop. With the headless `-q` launch and no later commands,
r2 exits when serving ends. Verify the intended PID and listener stopped.
Do not close the user's tandem UI; stop its background server at the console
only when requested. Saving alone leaves the host available for follow-ups.
The server provides local command access, including writes when
`http.sandbox=false`. Bind to `127.0.0.1` and do not expose it as a public
service.