http://natashenka.ca/wp-content/uploads/2014/01/strcpy8x11.png
strcpy は、あなたが示しているような理由で危険であると考えられています。作成した 2 つのバッファーは、関数のスタック フレームに格納されたローカル変数です。スタック フレームの大まかな外観は次のとおりです
。
参考までに、スタックの一番上に配置されます。つまり、メモリを逆方向に拡張します (これは、メモリ内の変数が逆方向に読み取られるという意味ではなく、新しい変数が古い変数の「後ろ」に配置されるという意味です)。つまり、関数のスタック フレームの locals セクションに十分に書き込むと、コピー先の変数の後に他のすべてのスタック変数に順方向に書き込み、他のセクションに割り込んで、最終的にリターン ポインターを上書きします。その結果、賢ければ、関数が返す場所を完全に制御できます。あなたはそれを本当に何でもさせることができますが、心配しているのはあなたではありません.
5 文字の文字列に対して最初のバッファを 6 文字にすることでわかるように、C 文字列は null バイト \x00 で終わります。strcpy 関数は、コピー元のバイトが 0 になるまでバイトをコピーしますが、コピー先がその長さであることを確認しません。これが、配列の境界を越えてコピーできる理由です。これは、印刷がそのサイズを超えてバッファを読み取っている理由でもあり、\x00 まで読み取ります。興味深いことに、コンパイラがスタックに与えた順序に応じて、strcpy が s のデータに書き込んだ可能性があるため、a を出力して、「snsadsdas」のような結果が得られるかどうかを確認するのも楽しい練習になるかもしれませんが、できませんs を汚染している場合でも、さまざまな理由でスタックエントリ間にバイトが存在することがあるため、どのように見えるかを確認してください)。
このバッファに、ハッシュ関数を使用してコードをチェックインするためのパスワードが保持されていて、それを取得した場所 (サーバーの場合はネットワーク パケット、テキスト ボックスなど) からスタック内のバッファにコピーすると、非常にうまくいきます。宛先バッファが保持できるよりも多くのデータをソースからコピーし、パケットを送信したりパスワードを試行したりできたユーザーにプログラムの制御を返す可能性があります。正しい文字数を入力してから、RAM のどこかにジャンプするアドレスを表す正しい文字を入力するだけです。
境界をチェックしてソース文字列をトリミングする場合は strcpy を使用できますが、これは悪い習慣と見なされます。http://www.cplusplus.com/reference/cstring/strncpy/のように最大長を取る最新の関数があります。
最後に、これはすべてバッファ オーバーフローと呼ばれます。一部のコンパイラは、OS によってランダムに選択されたバイトの素敵な小さな塊を、すべてのスタック エントリの前後に追加します。コピーのたびに、OS はこれらのバイトをそのコピーと照合してチェックし、異なる場合はプログラムを終了します。これにより、多くのセキュリティ問題が解決されますが、バイトが変更されたときに何が起こるかを処理する関数へのポインターを上書きするのに十分な距離までバイトをスタックにコピーして、同じことを行うことができます。正しく行うのが非常に難しくなります。