私はCTFを初めて使い、これを解決するように求められました。
#include <cstdio>
// g++ pwn2.cpp -o pwn2 -static
void ilocamp() {
char flaga[1024] = {0};
FILE *f = fopen("flag2.txt", "r");
fread(flaga, 1, 1024, f);
fclose(f);
printf("flaga: ILOCAMP{%s}\n", flaga);
}
int main() {
int tab[100] = {0};
int dwa = 2;
int n,i,min,x;
scanf("%d",&n);
for (i=0;i<n;i++) {
scanf("%d", &x);
scanf("%d", &tab[x]);
}
min = 1000000000;
for (i=0;i<n;i++) {
if (tab[i] && tab[i] < min) {
min = tab[i];
}
}
printf("najmniejsza liczba: %d a dwa wynosi: %d\n", min, dwa);
}
ポイントは、メイン関数の戻りアドレスをilocamp()エントリアドレスで上書きすることであり、これを行うには、ループ内でその単純な脆弱性を使用することになっていますが、これを行う方法がわかりません。私はバイナリも持っていますが、gdbで何かをしようとしましたが、どうすればよいかわかりません。ヒントをください。バイナリがあります: http://www48.zippyshare.com/v/b7OaWQeW/file.html (ファイル "flag2.txt"はローカルサーバーにあります)
時間がないので、今のところ大まかな説明です。 一般的な考え方は、ターゲット関数のアドレスと、スタック上の戻りアドレスの正確な位置を決定することです。
差出人住所を上書きする場合は、最初に正しい位置を見つける必要があります。これを行うには、おそらくプログラムをデバッグし、ブレークポイントをメイン関数の可能な最後のステップに設定し、そこから単一の命令をステップ実行することによってレジスターが変化するのを観察します。簡単なヒント:プログラムを開いた後、起動するたびに1バイト長い文字列をプログラムに挿入すると、ある時点でプログラムがクラッシュするのを確認できます。スタックカナリアまたはシャドウスタックがないか、ターゲットアドレスが見つかったと仮定します。あなたは(デバッグしながら)例えばたくさんの 'A'を供給し、デバッガーで0x41を監視します。
次に、ターゲット関数のアドレスを決定します。かなり簡単です。たとえば、次のことができます。 info symbol
とinfo address
。その後、RIP(Return Instruction Pointer)のアドレスに到達するまで、スタックにゴミ(例:「A」)を書き込んでから、必要な新しいアドレスを書き込みます。
また、EIP/RIPやウィキペディアなどのスタックオーバーフローについても少し読んでください。