r2pipe.el

r2pipe.el

As it turns out we can script radare2 with emacs , Found this code snippet online

;;
;; R2PIPE in Emacs Lisp
;; Judge Dredd (jjdredd @ github) the.guard@mail.ru
;;

(require 'json)

;; Temporary storage for r2 process std output
(setq r2-pipe-out-string nil)

(defun r2-pipe-filter (process output)
  "This filter callback is used by emacs whenever a process has output"
  (setq r2-pipe-out-string (concat r2-pipe-out-string output)))

(defun r2-pipe-new (cmdline)
  "Spawn r2 with cmdline and return process object on success or nil on failure"
  (let ((process (start-process "radare2" nil "r2" "-q0" cmdline)))
    (if (equal (process-status process) 'run)
	(progn (set-process-filter process 'r2-pipe-filter) process)
      nil)))

(defun r2-cmd (process command)
  "Executes an r2 command and returns output in a string"
  (setq r2-pipe-out-string nil)
  (process-send-string process (format "%s\n" command))
  (accept-process-output process)
  r2-pipe-out-string)

(defun r2-cmd-json (process command)
  "Executes a json r2 command and returns output in an elisp object"
  (json-read-from-string (r2-cmd process command)))

(defun r2-pipe-close (process)
  "Closes r2"
  (process-send-string process "q!!\n"))

(defun r2-kill (process)
  "Kills r2"
  (kill-process process))
 
(provide 'r2pipe)

Now we can script our reversing tasks from emacs lisp . Mainly there are three function

  1. r2-pipe-new : It opens up radare with the given argument and returns a process object with which we can later interact .

  2. r2-cmd : Runs a command and returns the output .

  3. r2-cmd-json : Just like the previous but it parses the json output and returns a elisp object.

That’s all you need . Let’s look at an example

First we need to create a new session

(setq process (r2-pipe-new "/bin/ls"))

Let’s run a simple command

(r2-cmd-json process "iIj")
((arch . x86) (binsz . 128811) (bintype . elf) (bits . 64) (canary . t) (class . ELF64) (compiled . ) (crypto . :json-false) (dbg_file . ) (endian . little) (havecode . t) (guid . ) (intrp . /lib64/ld-linux-x86-64.so.2) (lang . c) (linenum . :json-false) (lsyms . :json-false) (machine . AMD x86-64 architecture) (maxopsz . 16) (minopsz . 1) (nx . t) (os . linux) (pcalign . 0) (pic . t) (relocs . :json-false) (relro . partial) (rpath . NONE) (static . :json-false) (stripped . t) (subsys . linux) (va . t) (checksums))

So it returned a alist , for more detail about json parsing in emacs i recommend to read the json.el file . Now we can use elisp to manipulate the data

(format "Architecture: %s " (cdr (assoc 'arch (r2-cmd-json process "iIj"))))
Architecture: x86 
(setq output (r2-cmd-json process "pdj 10 @ main"))
;; We are iterating over the vector to retrive the 
(setq result "")
(let ((len (length output))
      (i 0))
  (while (< i len)
    (setq result
	  (concat result
		  (format "%s \n" ( cdr (assoc 'opcode (aref output i))))))
    (setq i (+ i 1 )))
  ) 
result 
push r15 
push r14 
push r13 
push r12 
mov r12d, edi 
push rbp 
push rbx 
mov rbp, rsi 
sub rsp, 0x48 
mov rdi, qword [rsi]