hope-RIPEを使ってみる その2
昨日、hope-RIPEをSpikeシミュレーターで動かしてみたんだが、Stack Buffer Overflowを利用したROPが成功しないという不可解な現象に遭遇した。SSPが有効になっているからかと思ったけども、Makefileを見る限りではそうではないみたいだし、これは何だろうということで詳しく調べてみた。
失敗したケースのうち、以下のケースを取り上げる。
ripe_attack_generator -t direct -i rop -c ret -l stack -f memcpy
デバッガーで原因を探る
デバッガーで追ってみたところ、ropでjumpする先のアドレスを間違えていることが原因でセグフォしていることがわかった。
逆アセンブルの内容
0000000000010e00 <perform_attack>: ... 11b84: 78813083 ld ra,1928(sp) <-- ここで return address を書き換える 11b88: 78013403 ld s0,1920(sp) <-- ここに breakpoint を貼って、p $raしてみる 11b8c: 79010113 addi sp,sp,1936 11b90: 8082 ret 0000000000011ec8 <rop_target>: // <-- jump先ターゲット 11ec8: 1141 addi sp,sp,-16 11eca: e406 sd ra,8(sp) 11ecc: e022 sd s0,0(sp) 11ece: 0800 addi s0,sp,16 11ed0: 67cd lui a5,0x13 11ed2: 7d878513 addi a0,a5,2008 # 137d8 <.annobin_elf_init.c_end+0x73e> 11ed6: c3bfe0ef jal ra,10b10 <puts@plt> 11eda: 4501 li a0,0 11edc: c55fe0ef jal ra,10b30 <exit@plt>
デバッガーの出力
(gdb) b *0x11b88 Breakpoint 1 at 0x11b88 (gdb) r Starting program: /root/hope-RIPE/build/ripe_attack_generator -t direct -i rop -c ret -l stack -f memcpy Missing separate debuginfos, use: dnf debuginfo-install glibc-2.28.9000-24.fc30.riscv64 tech: 100 attack: 202 code ptr: 300 location: 400 function: 500 Breakpoint 1, 0x0000000000011b88 in perform_attack () (gdb) p $ra $1 = (void (*)()) 0x11ed8 <rop_target+16>
<rop_target+16>
がちゃんと命令の先頭アドレスとなっていれば良いが、そうなっていない。0x11ed8なので、jal ra,10b10
という命令の"ど真ん中に"ジャンプしてしまう。で、decodeができずIllegal Instructionで落ちていることがわかった。
以下の箇所がjump先を決めているところだが、コンパイラのバージョンが変わったことにより、この16というオフセット値が変わってしまったのだと予想される。
まとめると、昨日hope-RIPEを実行してFAILと表示されたケースは、SSPなどが働いて脆弱性攻撃に失敗したというわけではなく、単純に攻撃コードのバグによって失敗しているということだった。
ということで、修正してプルリクを出しておくのが良さそうである。