radare2のエイリアス機能をソースコードレベルでいじって使いやすくしてみる
この記事はプログラムのソースコードを書き換えるものです.行う際は自己責任でお願いします.
radare2
でエイリアスやマクロを使っていたが,どうにもコマンドを打ちにくいのでソースコードをいじって試行錯誤してみた.マクロ機能をいじるのは大規模な改変になりそうだったため,今回はエイリアスのみをいじることにした.結果エイリアスの識別文字を$
からn
にすると,比較的使いやすくなったのでそのやり方をまとめておく.
ついでに,改変後のエイリアス機能を利用した動的解析用エイリアスも紹介する.作成したエイリアスはPeda
を使ったGDB
を意識した.
エイリアス機能
radare2
のエイリアス機能は以下のように定義・使用することができる.
* 定義 $dis=`af;pdf` * 使用 $dis
詳しくは$?
で見ることができる.
問題点
まず基礎知識として,radare2
は最初に機能を大別する文字(今回ならば$
)の後に個別のコマンドが続くようになっている.
エイリアス機能は多用するのにタイプしにくい.これは識別文字に$
を使っていることが原因であると考えた.
$
を入力するShift+4
って何回も打つのは苦痛だ,できればアルファベットのどれか,かつShift
を押さないで済ましたい.
ソースコードを読んでみると,$
を定義している部分のコメントにはprefix aliases with a dash
とあった.英語は苦手だが,とりあえず「dash
を参考にしてエイリアスのプレフィックスを$
にしました」と理解した(間違っていたらぜひ指摘してください).
恐らく,dash
を起動した時に左に出てくる$
のことだと思う.dash
に固執する特別な意味は感じなかったので変えても問題はないだろうと判断した.
そこで,エイリアス機能の識別子である$
を現在コマンドがマッピングされていないn
に変更することにした.
準備
Githubからソースコードをダウンロードする.この記事には関係はないが,Ubuntuのapt
などでインストールされるradare2
はバージョンが古いので,Githubからのインストールをおすすめしたい.
$ git clone https://github.com/radare/radare2 && cd radare2
編集
次に,libr/core/cmd.c
を以下のように編集する.やってることは,$
をn
に置き換えているだけ.現在マッピングされているコマンドとかぶらなければ良いので,n
でなくとも問題はない.他に現在コマンドがマッピングされていない文字はh j v
がある(大文字であればもっと存在するが,Shift
を押したくないので今回は考えない).行番号はバージョンによって異なるので,適宜修正すること.
// libr/core/cmd.c 128 static int cmd_alias(void *data, const char *input) { 129 int i; 130 char *def, *q, *desc, *buf; 131 RCore *core = (RCore *)data; // help_msgの'$'を'n'に置き換える 132 if (*input=='?') { 133 const char* help_msg[] = { 134 "Usage:", "nalias[=cmd] [args...]", "Alias commands", 135 "n", "", "list all defined aliases", 136 "n*", "", "same as above, but using r2 commands", 137 "n", "dis='af;pdf'", "create command - analyze to show function", 138 "n", "test=#!pipe node /tmp/test.js", "create command - rlangpipe script", 139 "n", "dis=", "undefine alias", 140 "n", "dis", "execute the previously defined alias", 141 "n", "dis?", "show commands aliased by 'analyze'", 142 NULL}; 143 r_core_cmd_help (core, help_msg); 144 return 0; 145 } ... // コマンド解析時の識別文字を変更.ここが要 149 *buf = 'n'; ... // 何も押さないでEnterした時に前回のコマンドが実行される機能を'n'で動くようにする. 2354 R_API void r_core_cmd_repeat(RCore *core, int next) { 2355 // Fix for backtickbug px`~` 2356 if (core->cmd_depth + 1 < R_CORE_CMD_DEPTH) 2357 return; 2358 if (core->lastcmd) 2359 switch (*core->lastcmd) { 2360 case 'd': // debug 2361 r_core_cmd0 (core, core->lastcmd); 2362 switch (core->lastcmd[1]) { 2363 case 's': 2364 case 'c': 2365 r_core_cmd0 (core, "sr PC;pd 1"); 2366 } 2367 break; 2368 case 'p': // print 2369 case 'x': // ここを変更.これを忘れると,入力なしの時に前回のコマンドを実行する機能が動かない 2370 case 'n': 2371 if (next) { 2372 r_core_seek (core, core->offset + core->blocksize, 1);
インストール
セーブしたら,
$ sys/install.sh
でインストールできる.
ローカルにインストールしたいときは
$ sys/user.sh
削除は
$ make uninstall && make purge
で行うことができる.
確認
無事インストールが終わったら,反映されているかを確認する.
$ r2 /bin/ls [0x00404840]> n? |Usage: nalias[=cmd] [args...]Alias commands | n list all defined aliases | n* same as above, but using r2 commands | ndis='af;pdf' create command - analyze to show function | ntest=#!pipe node /tmp/test.js create command - rlangpipe script | ndis= undefine alias | ndis execute the previously defined alias | ndis? show commands aliased by 'analyze' [0x00404840]> ndis='af;pdf' [0x00404840]> n* ndis=af;pdf [0x00404840]> ndis / (fcn) entry0 42 | 0x00404840 31ed xor ebp, ebp | 0x00404842 4989d1 mov r9, rdx | 0x00404845 5e pop rsi | 0x00404846 4889e2 mov rdx, rsp | 0x00404849 4883e4f0 and rsp, 0xfffffffffffffff0 ...(snip)...
これでエイリアス機能の識別文字がn
になっていることが確認できた.
しかし,エイリアスの定義では引数を渡す文字の@
を使うことができない.
[0x00404840]> ndis='pd 10@eip
とすると,
[0x00404840]> n* ndis='pd 10
と途切れてしまう.これはひと手間かけることで解決できる.
[0x00404840]> (test,"",pd 10@eip) [0x00404840]> ntest=.(test)`
マクロを定義して,そのマクロのエイリアスを設定している.これで,@
問題は解決できる.
デバッグ用エイリアス
最後に,デバッグでよく使いそうなマクロ・エイリアスを紹介する.一部はradare2book
に載っているものを活用した.これを$HOME/.radare2rc
に書いておくと起動時に毎回読み込んでくれる.
// .radare2rc for 32bit (peda32,"",drr,pd 10@eip,pxr 40@esp) (stepOut32,"",dso,drr,pd 10@eip,pxw 64@esp) (stepIn32,"",ds,drr,pd 10@eip,pxw 64@esp) (outputStack32,"",pxw 64@esp) nn=.(stepIn32) ; GDBでの'si' ni=.(stepOut32) ; GDBでの'ni' nw=.(outputStack32) ; GDBでの'x/20xw $esp' np=.(peda32) ; pedaによる出力に似た何か ns='do;db main;dc;db- main;np' ; GDBでの`start'.デバッグ情報が消されている場合は動作しない nr='do;dc;np' ; GDBでの'run' nc='dc;np' ; GDBでの'continue'
// .radare2rc for 64bit <- この行は書かない (peda64,"",drr,pd 10@rip,pxr 40@rsp) (stepOut64,"",dso,drr,pd 10@rip,pxq 64@rsp) (stepIn64,"",ds,drr,pd 10@rip,pxq 64@rsp) (outputStack64,"",pxq 64@rsp) nn=.(stepIn64) ni=.(stepOut64) nq=.(outputStack64) np=.(peda64) ns='do;db main;dc;db- main;np' nr='do;dc;np' nc='dc;np'
コマンド名は最初がn
であることが条件.それ以降は自由に変えてよい.
まとめ
とりあえず,これでエイリアス機能が指をあまり動かさずに呼び出せるようになったので楽になった.しばらくはこの設定で使ってみようと思う.
書き換える箇所があれだけで済んだこととソースが読みやすかったことには感動した.機能をひとつのファイル内で完結させる部分とかは今後プログラムを書く上で意識していきたい.
しかし,もっと良い方法がデフォルトでなにかあるんじゃないかなと思いもする.Bookを読んでなにか気づいたらまた書きたい.
参考文献
Radare2Book: https://www.gitbook.com/book/radare/radare2book/details