C(x86_64)、11、30、34、または34 + 15 = 49バイト
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
ライブラリ関数を使用しSIGILL
てさまざまな手段でスローするいくつかのソリューションを提出しましたが、ライブラリ関数が問題を解決するという点で、おそらく不正行為です。ライブラリ関数を使用せず、オペレーティングシステムが非実行コードの実行を許可する場所についてさまざまな仮定を立てるさまざまなソリューションを以下に示します。(ここでの定数はx86_64用に選択されていますが、違法な命令を持っている他のほとんどのプロセッサー用の有効なソリューションを取得するために変更できます。)
06
x86_64プロセッサで定義された命令に対応しないマシンコードの最小番号のバイトです。実行するだけです。(または、2F
未定義であり、単一の印刷可能なASCII文字に対応します。)これらのどちらも常に未定義であることが保証されていませんが、今日では定義されていません。
最初のプログラムは2F
、読み取り専用のデータセグメントから実行されます。ほとんどのリンカは、正しくセグメント化されたプログラムで有用なものではない.text
ため、.rodata
(またはそれらのOSに相当する)からの機能的なジャンプを生成できません。これが動作するオペレーティングシステムはまだ見つかりません。また、多くのコンパイラが問題の文字列をワイド文字列にしたいという事実を考慮しなければなりません。L
; 私は、これが動作するオペレーティングシステムは物事についてかなり時代遅れの見方をしており、したがってデフォルトでC94以前の標準のために構築されていると想定しています。このプログラムが機能する場所は存在しない可能性がありますが、このプログラムが機能している場所も存在する可能性があります。そのため、このプログラムをより疑わしいものから疑わしいものへの潜在的な回答のコレクションにリストしています。(この回答を投稿した後、デニスmain[]={6}
はチャットの可能性についても言及しました。これは同じ長さであり、文字幅の問題に遭遇せず、潜在的な可能性を示唆さえしましたmain=6
;これらの答えを合理的に主張することはできません私自身は考えていなかったので)
ここの2番目のプログラムは06
、読み取り/書き込みデータセグメントから実行されます。ほとんどのオペレーティングシステムでは、書き込み可能なデータセグメントは悪用される可能性のある設計上の欠陥であると見なされるため、セグメンテーションエラーが発生します。ただし、これは常にそうとは限らないため、おそらく十分に古いバージョンのLinuxで動作しますが、簡単にテストすることはできません。
3番目のプログラムは06
スタックから実行されます。繰り返しになりますが、スタックは通常、セキュリティ上の理由で書き込み不可として分類されているため、これにより、最近ではセグメンテーション違反が発生します。私が見たリンカのドキュメントは、スタックから実行することが以前は合法だったことを暗示しています(前の2つのケースとは異なり、そうすることは時々有用です)ので、私はそれをテストすることはできませんが、いくつかがあると確信していますこれが機能するLinux(およびおそらく他のオペレーティングシステム)のバージョン。
最後に、-Wl,-z,execstack
(バックエンドの一部としてgcc
GNU ld
を使用する場合)に(15バイトのペナルティ)を与えると、実行可能スタック保護が明示的にオフになり、3番目のプログラムが動作し、予想どおりに違法な操作信号が与えられます。この49バイトバージョンが動作することをテストおよび検証しました。(Dennisはチャットでこのオプションmain=6
が6 + 15のスコアを与えると思われると述べています。6が露骨にスタック上にないことを考えると、これが機能することはかなり驚いています。リンクオプションは明らかにその名前が示唆している。)
raise(SIGILL)
か?