GDB の x(examine)は、指定したアドレスのメモリを、指定した個数・サイズ・フォーマットで表示するコマンド。gdb-peda のほかのコマンドは「gdb-peda 便利コマンド集」のノートを参照。
書式
x/[個数][サイズ][フォーマット] <ADDRESS> | $<REGISTER> | &<VAR_NAME>
| サイズ |
バイト数 |
b |
1(byte) |
h |
2(halfword) |
w |
4(word) |
g |
8(giant) |
| フォーマット |
表示形式 |
x |
16 進数 |
d |
10 進数(符号付き) |
c |
文字 |
a |
アドレス(近くのシンボル名 + オフセットも表示) |
s |
ヌル終端の文字列 |
i |
機械語命令(逆アセンブル) |
使用例
| コマンド |
表示されるもの |
x/20gx $rsp |
スタックの先頭($rsp が指すアドレス)から 8 バイト単位で 20 個、16 進数で |
x/32bx $rsp |
$rsp が指すアドレスから 1 バイト単位で 32 個、16 進数で(スタックの生バイト) |
x/gx $rbp+8 |
保存されたリターンアドレス |
x/10i $rip |
次に実行する命令から 10 命令分 |
x/s $rdi |
$rdi が指すヌル終端文字列 |
x/s 0x402004 |
指定したアドレスにある文字列 |
x/s &<VAR_NAME> |
文字配列の変数に入っている文字列(変数が char * のポインタなら & を付けずに x/s <VAR_NAME>) |
x $rbp-0x10 |
/ 以降を省略すると、前回の x のサイズとフォーマットを引き継ぐ |
補足
x の直後に Enter を押すと、続きのアドレスから同じ形式で表示される。
gx は 8 バイトをリトルエンディアンで数値に直して表示し、bx はメモリに並んでいる順のまま 1 バイトずつ表示する。同じ場所でも見え方が違うので、ペイロードがどう並んだかを確かめるときは bx、アドレスや値として読みたいときは gx を使う。
$rbp+8 がリターンアドレスになるのは、関数の先頭で push rbp; mov rbp, rsp を実行した後($rbp の位置に呼び出し元の rbp、その 8 バイト上にリターンアドレスがある)。関数の入口でまだ prologue を実行していないときや、フレームポインタを使わないビルドでは当てはまらない。
- x86-64 の Linux(System V ABI)では、関数の第 1 引数は
$rdi で渡される。puts や strcmp などの呼び出しで止めて x/s $rdi を実行すると、渡された文字列を確認できる。
- 64bit のバイナリではレジスタ名に
$rbp、$rsp、$rip を使う。$ebp などは 32bit のバイナリでの名前。
- アドレスは
x/s 0x402004 のように数値のまま渡す。* を付けると、そのアドレスに入っている値を読む式になる(break *0x401000 の * とは意味が違う)。
s と i は表示の単位が文字列・命令なので、通常はサイズを付けない。