鬱猫のつぶやき

鬱猫が日々思っていることをつづります

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というオフセット値が変わってしまったのだと予想される。

github.com

まとめると、昨日hope-RIPEを実行してFAILと表示されたケースは、SSPなどが働いて脆弱性攻撃に失敗したというわけではなく、単純に攻撃コードのバグによって失敗しているということだった。

ということで、修正してプルリクを出しておくのが良さそうである。