r2pipe

repository·master·Indexed 19 days ago

https://github.com/radareorg/radare2-r2pipe

Language bindings for the radare2 framework that allow developers to interact with radare2 via command strings and JSON output. It provides implementations for multiple programming languages, including C (via libr_socket), Clojure, .NET (C#), Erlang, Go, and Node.js (including the asynchronous r2pipe-promise wrapper). Supported connection channels include spawn, TCP, HTTP, and in-process calls to libr_core.

Tokens
20.9K
Snippets
107
Records
125
Agent score
63%

What's inside r2pipe

  1. Use r2pipe-promise for asynchronous radare2 scripting

    master

    The r2pipe-promise module is a frontend for r2pipe that provides a promisified API. It allows you to interact with radare2 using modern asynchronous patterns instead of callbacks, making scripts cleaner and more readable. It supports standard JavaScript .then()/.catch() chains, the co module, bluebird, and native async/await (Node.js 7.6+).

    const r2promise = require('r2pipe-promise');
    
    const radare2FTW = async () => {
      try {
        const r2 = await r2promise.open('/bin/ls');
        const msg = await r2.cmd('?E hello world');
        console.log(msg);
        return r2.quit();
      } catch (err) {
        console.error(err);
      }
    }
    
    radare2FTW();
  2. Use r2pipe.go to interact with radare2

    master

    The r2pipe.go module provides Go bindings to allow Go applications to interact with the radare2 framework via its pipe interface. For detailed API documentation, refer to the official GoDoc page.

    https://godoc.org/github.com/radare/r2pipe-go
  3. Use R2Pipe.Swift to communicate with radare2

    master

    R2Pipe.Swift is a Swift 2.0 API that allows you to run commands in a radare2 session. It supports multiple communication channels and execution modes:

    Communication Channels

    • http
    • spawn
    • pipe

    Execution Modes

    • Sync: Synchronous command execution.
    • Async: Asynchronous command execution using closures.

    JSON Support

    Native JSON parsing is not built-in; you should integrate libraries like SwiftyJSON or swift-json to handle JSON responses from radare2.

    if let r2p = R2Pipe("http://cloud.radare.org/cmd/") {
    	if let str = r2p.cmdSync ("?V") {
    		print ("Version: \(str)");
    	} else {
    		print ("ERROR: HTTP Sync Call failed");
    	}
    	r2p.cmd("pi 5 @ entry0", closure:{
    		(str:String)->() in
    		print ("Disasm:\n\(str)");
    	});
    }
  4. How r2pipe works and its core design

    master

    The r2pipe APIs are built around a single primitive: sending a string describing a radare2 command and receiving a string containing the result. This is based on the r_core_cmd_str() function.

    Key Design Principles:

    • Command Strings over Native APIs: Using raw command strings and parsing the output is faster and less complex than using native libffi-based APIs.
    • JSON for Data Exchange: It is highly recommended to use JSON output from radare2 commands and deserialize them into native language objects. This is more reliable than manual parsing of text output.
    • Simplified Memory Management: Users only need to manage the memory of the resulting string returned by the command.

    Communication Backends:

    Depending on the language implementation, r2pipe can communicate via:

    • R2PIPE{_IN|_OUT} environment variables
    • Spawning r2 -q0 and using pipe(2)
    • Plain TCP connections
    • HTTP queries (remote webservers)
    • RAP protocol (radare2's remote protocol)
  5. Execute radare2 commands with r2pipe-ts

    master

    The core functionality of the API is centered around a single function, cmd, which executes a radare2 command and returns the output as a string.

    For better integration with TypeScript/JavaScript, use cmdj() when executing commands that return JSON. This method automatically parses the output and converts it into a JavaScript object, making it ideal for structured data manipulation.

    // Conceptual usage
    const output = await r2.cmd('aaa'); // returns string
    const data = await r2.cmdj('aaa');  // returns parsed JSON object
  6. Supported r2pipe.vala transports

    master

    The R2Pipe.sync constructor supports several transport mechanisms to connect to radare2:

    • spawn: Spawns a local process. Example: new R2Pipe.sync ("/bin/ls")
    • HTTP: Connects to a radare2 instance listening via HTTP. Example: new R2Pipe.sync ("http://127.0.0.1:9090")
    • in-process pipe: Connects via an in-process pipe. Example: new R2Pipe.sync () or new R2Pipe.sync ("#!pipe")

    Additionally, you can use cmdj("ij") for JSON parsing of command outputs.

  7. Use the default r2pipe instance

    master

    For simple use cases, you can use the default global instance provided by r2pipe.core. This is suitable for single-instance interactions.

    • r2open: Opens a connection using a URI (e.g., spawn://, tcp://, or http://).
    • cmd: Executes a command and returns a string representation.
    • cmdj: Executes a command and returns a Clojure map (JSON output).
    • close: Closes and cleans up the pipe.
    • configure-path: Sets the path to the radare2 binary.
    • proto/set-deny-inquiry: Allows or denies inquiry-style commands (e.g., pd?) by interacting with r2pipe.proto.
    (use 'r2pipe.core)
    
    (r2open "spawn:///./program.bin")    ; spawn r2 and open file
    (r2open "tcp://127.0.0.1:1337")      ; use TCP connection
    (r2open "http://127.0.0.1:9090/cmd") ; use HTTP
    
    (cmd "pd" "8")   ; returns string
    (cmdj "pdj" "8") ; returns Clojure map
    
    (close) ; closes the pipe
    
    ;; Allow inquiries (e.g., "pd?")
    (require '[r2pipe.proto :as proto])
    (proto/set-deny-inquiry false)
    
    ;; Change radare2 binary location
    (configure-path "/usr/bin/r2")