18
void return_input(void)
{{
   char配列[30];

   get(配列);
   printf( "%s \ n"、array);
}

gccでコンパイルした後、この関数は次のアセンブリコードに変換されます。

%ebpをプッシュ
mov%esp、%ebp
サブ$0x28、%esp
mov%gs:0x14、%eax
mov%eax、-0x4(%ebp)
xor%eax、%eax
lea -0x22(%ebp)、%eax
mov%eax、(%esp)
0x8048374に電話する
lea -0x22(%ebp)、%eax
mov%eax、(%esp)
0x80483a4に電話する
mov -0x4(%ebp)、%eax
xor%gs:0x14、%eax
je 0x80484ac
0x8048394に電話する
離れる  
ret  

私は2行を理解していません:

mov%gs:0x14、%eax
xor%gs:0x14、%eax

%gsとは何ですか、そしてこれらの2行は正確に何をしますか?

これはコンパイルコマンドです:

cc -c -mpreferred-stack-boundary = 2 -ggdb file.c
4

3 に答える 3

24

GSはセグメントレジスタであり、Linuxでの使用はここで読み取ることができます(基本的にスレッドごとのデータに使用されます)。

mov    %gs:0x14,%eax
xor    %gs:0x14,%eax

このコードは、GS + 0x14に格納されているカナリア値を使用して、スタックが展開または破損していないことを検証するために使用されます。これを参照してください。

gcc -fstack-protector=strong多くの最新のディストリビューションではデフォルトでオンになっています。gcc -fno-stack-protectorこれらのチェックを追加しないように使用できます。(x86では、スレッドローカルストレージは安価であるため、GCCはランダム化されたカナリア値をそこに保持し、リークをいくらか困難にします。)

于 2012-02-12T14:18:38.510 に答える
3

ES、FS、GS:追加セグメントレジスタ追加セグメントレジスタとして使用できます。セグメントにまたがる特別な命令(文字列コピーなど)でも使用されます。ここから取った

http://www.hep.wisc.edu/~pinghc/x86AssmTutorial.htm


それが役に立てば幸い

于 2012-02-12T14:02:30.200 に答える
3

AT&Tスタイルのアセンブリ言語では、パーセント記号は通常、レジスタを示します。386以降のx86ファミリプロセッサでは、GSはいわゆるセグメントレジスタの1つです。ただし、プロテクトモード環境では、セグメントレジスタはセレクタレジスタとして機能します。

仮想メモリセレクタは、独自のアクセスレジームとともに仮想アドレス空間の独自のマッピングを表します。実際に%gs:0x14は、原点が%gsで保持されている配列への参照と考えることができます(CPUは少し余分な逆参照を行いますが)。最新のGNU/Linuxシステムで%gsは、通常、スレッドローカルストレージ領域を指すために使用されます。ただし、質問しているコードでは、TLSの1つの項目(スタックカナリア)のみが重要です。

アイデアは、ランダムで一定の値をスタックに配置することによって、バッファオーバーフローエラーの検出を試みることです。これは、採炭業者が死ぬことによって有毒ガスのレベルの増加を通知するために使用したカナリアを記念して、スタックカナリアと呼ばれます。スタックフレームの上で呼び出され、戻ってきた gets()後もまだそこにあるかどうかを確認します。スタックのこの部分を上書きするビジネスはありません—それはそれ自身のスタックフレームの外側にあり、それへのポインタは与えられません—したがって、スタックカナリアが死んだ場合、何かが危険な方法で間違っています。(プログラミング環境としてのCは、この種の不正行為を特に起こしやすく、セキュリティ研究者は過去20年ほどでそれらの多くを悪用することを学びました。また、gets()gets()gets()たまたまそのターゲットバッファをオーバーフローするリスクがある関数です。)コードでアドレスを提供していませんが、0x80484acはのアドレスである可能性が高く、leave不一致call 0x8048394の場合(つまり、によってジャンプされた場合)に実行されます。je 0x80484ac一致する場合)は、おそらく__stack_chk_fail()、比喩的な有毒な鉱山から逃げることによってスタックの破損を処理するためにlibcによって提供されるへの呼び出しです。

スタックカナリアの正規値がスレッドローカルストレージに保持される理由は、このようにして、すべてのスレッドが独自のスタックカナリアを持つことができるためです。スタック自体は通常スレッド間で共有されないため、カナリア値も共有しないのは当然です。

于 2018-04-01T22:38:20.460 に答える