Подтвердить что ты не робот

Почему этот адрес памяти% fs: 0x28 (fs [0x28]) имеет случайное значение?

Я написал фрагмент кода на 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 <[email protected]>
   0x0000000000400600 <+76>:        leaveq 
   0x0000000000400601 <+77>:        retq 

Я хотел бы знать, что действительно делает mov %fs:0x28,%rax?

4b9b3361

Ответ 1

На x86_64 сегментированная адресация больше не используется, но регистры FS и GS могут использоваться в качестве адресов базовых указателей для доступа к специальным структурам данных операционной системы. Итак, вы видите значение, загруженное со смещением от значения, хранящегося в регистре FS, а не битовые манипуляции с содержимым регистра FS.

В частности, происходит то, что FS:0x28 в Linux хранит специальное значение сторожевого стража, а код выполняет проверку защитного стека. Например, если вы посмотрите дальше в своем коде, вы увидите, что значение в FS:0x28 сохраняется в стеке, а затем FS:0x28 содержимое стека и выполняется XOR с исходным значением в FS:0x28, Если эти два значения равны, что означает, что нулевой бит был установлен, потому что XOR, если два одинаковых значения приводят к нулевому значению, мы переходим к процедуре test, в противном случае мы переходим к специальной функции, которая указывает что стек был каким-то образом поврежден, и значение часового, хранящееся в стеке, было изменено.

При использовании GCC это можно отключить с помощью

-fno-stack-protector

Ответ 2

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.

Ответ 3

Глядя на http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm, я думаю, что %fs:28 на самом деле является смещением 28 байтов от адреса в %fs. Поэтому я думаю, что он загружает полный размер регистра из местоположения %fs + 28 в% rax.