注:これは純粋に学術的な回答であり、悪意のある目的で使用することを意図したものではないことをお答えします。私はOPが行っている演習を認識しており、それらはオープンソースであり、承認されていない状況でこれらの手法を使用するようにユーザーを促すことを意図したものではありません。
以下でテクニックの詳細を説明しますが、私の概要は短いものになるので、参考のためにVudo mallocトリック(上記のリンクの1つで参照されています)を見てみましょう:http ://www.phrack.com /issues.html?issue=57&id=8
これは、mallocがメモリのブロックの作成、リストからのメモリのプルなどをどのように処理するかを詳しく説明しています。特に、この攻撃ではリンク解除攻撃が重要です(注:この特定の理由により、glibcがサイズの健全性チェックを実行するようになったのは正しいですが、この演習では古いlibcを使用する必要があります...レガシーブロ)。
論文から、割り当てられたブロックと解放されたブロックは同じデータ構造を使用しますが、データは異なる方法で処理されます。ここを参照してください:
chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| prev_size: size of the previous chunk, in bytes (used |
| by dlmalloc only if this previous chunk is free) |
+---------------------------------------------------------+
| size: size of the chunk (the number of bytes between |
| "chunk" and "nextchunk") and 2 bits status information |
mem -> +---------------------------------------------------------+
| fd: not used by dlmalloc because "chunk" is allocated |
| (user data therefore starts here) |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| bk: not used by dlmalloc because "chunk" is allocated |
| (there may be user data here) |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| |
| |
| user data (may be 0 bytes long) |
| |
| |
next -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| prev_size: not used by dlmalloc because "chunk" is |
| allocated (may hold user data, to decrease wastage) |
+---------------------------------------------------------+
割り当てられたブロックはfdまたはbkポインターを使用しませんが、解放されたブロックは使用します。これは後で重要になります。Doug Leaのmallocの「ブロック」が二重にリンクされたリストに編成されていることを理解するには、十分なプログラミングを知っている必要があります。空きブロック用のリストと割り当てられたブロック用のリストがあります(技術的には、サイズに応じて無料のリストがいくつかありますが、コードが同じサイズのブロックを割り当てるため、ここでは関係ありません)。したがって、特定のブロックを解放するときは、リストをそのまま維持するためにポインターを修正する必要があります。
たとえば、以下のリストからブロックyを解放するとします。
x <-> y <-> z
上の図では、bkとfdのスポットに、リストに沿って反復するために必要なポインターが含まれていることに注意してください。mallocがリストからブロックpを削除したい場合、特に、リストを修正するためのマクロを呼び出します。
#define unlink( y, BK, FD ) {
BK = P->bk;
FD = P->fd;
FD->bk = BK;
BK->fd = FD;
}
マクロ自体を理解するのは難しいことではありませんが、古いバージョンのlibcで注意すべき重要な点は、書き込まれるサイズやポインターに対して健全性チェックを実行しないことです。あなたの場合の意味は、アドレスのランダム化を一切行わなくても、ヒープのステータスを予測可能かつ確実に判断し、特定の方法でヒープをオーバーフローさせることで(ここではstrncopyを介して)任意のポインターを選択したアドレスにリダイレクトできることです。 。
攻撃を機能させるために必要なものがいくつかあります。
- ブロックのfdポインターは、上書きするアドレスからマイナス12バイトを指しています。オフセットは、mallocがリストを変更するときにアライメントをクリーンアップすることと関係があります
- ブロックのbkポインターがシェルコードを指しています
- サイズは-4である必要があります。これにより、いくつかのことが達成されます。つまり、ブロック内のステータスビットが設定されます。
したがって、特定の例ではオフセットを試してみる必要がありますが、ここでstrcpyを使用して渡そうとしている一般的な悪意のある形式は、次の形式です。
| 正当なバッファを埋めるためのがらくた| -4 | -4 | 上書きするアドレス-12(0x0C)| 代わりに呼び出したいaddr
負の数はprev_sizeフィールドを-4に設定することに注意してください。これにより、フリールーティングはprev_sizeチャンクが実際に制御/破損している現在のチャンクで開始すると信じます。
そして、はい、この攻撃が現在のバージョンのglibcで機能しないことを言及せずに、適切な説明を完了することはできません。サイズには健全性チェックが行われており、リンク解除メソッドは機能しません。これをアドレスのランダム化などの緩和策と組み合わせると、この攻撃はレガシーシステム以外では実行できなくなります。しかし、ここで説明する方法は、私がその挑戦をした方法です;)