47

私はCコードを書き、それを分解し、レジスターを読んで、プログラムがアセンブリーでどのように機能するかを理解しました。

int test(char *this){
    char sum_buf[6];
    strncpy(sum_buf,this,32);
    return 0;
}

私が調べてきたコードの一部は、テスト関数です。出力を分解すると、テスト関数が得られます...

   0x00000000004005c0 <+12>:        mov    %fs:0x28,%rax
=> 0x00000000004005c9 <+21>:        mov    %rax,-0x8(%rbp)
... stuff ..
   0x00000000004005f0 <+60>:        xor    %fs:0x28,%rdx
   0x00000000004005f9 <+69>:        je     0x400600 <test+76>
   0x00000000004005fb <+71>:        callq  0x4004a0 <__stack_chk_fail@plt>
   0x0000000000400600 <+76>:        leaveq 
   0x0000000000400601 <+77>:        retq 

私が知りたいのは、mov %fs:0x28,%rax実際に何をしているのかということです。

4

3 に答える 3

78

FSとレジスタの両方を、GS特別なオペレーティングシステムのデータ構造にアクセスするためのベースポインタアドレスとして使用できます。したがって、表示されているのは、レジスタに保持されている値からのオフセットでロードされた値であり、レジスタFSの内容のビット操作ではありませんFS

具体的には、FS:0x28Linuxでは特別なセンチネルスタックガード値が格納されており、コードはスタックガードチェックを実行しています。たとえば、コードをさらに調べると、の値FS:0x28がスタックに格納されていることがわかります。次に、スタックの内容が呼び出されXOR、の元の値を使用してが実行されFS:0x28ます。2つの値が等しい場合、つまりXOR、同じ値の2つがゼロ値になるためにゼロビットが設定されている場合は、testルーチンにジャンプします。それ以外の場合は、スタックが何らかの理由で破損し、スタックに格納されている番兵の値が変更されました。

GCCを使用している場合、これは次のコマンドで無効にできます

-fno-stack-protector
于 2012-04-26T01:03:02.440 に答える
0
glibc:
  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARD
  THREAD_SET_STACK_GUARD (stack_chk_guard); 

the _dl_random from kernel.
于 2019-07-08T04:56:15.550 に答える
-3

http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htmを見ると、%fs:28実際にはのアドレスから28バイトのオフセットだと思います%fs%fs + 28したがって、場所から%raxに完全なレジスタサイズをロードしていると思います。

于 2012-04-26T00:43:17.170 に答える