mirror of
https://github.com/radareorg/r2xsql.git
synced 2026-11-07 06:36:02 -10:00
237 lines
9.7 KiB
Markdown
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.
|