Что такое% gs в сборке - PullRequest
       2

Что такое% gs в сборке

15 голосов
/ 12 февраля 2012
void return_input (void)
{ 
   char array[30]; 

   gets (array); 
   printf("%s\n", array); 
}

После компиляции в gcc эта функция преобразуется в следующий код сборки:

push   %ebp
mov    %esp,%ebp
sub    $0x28,%esp
mov    %gs:0x14,%eax
mov    %eax,-0x4(%ebp)
xor    %eax,%eax
lea    -0x22(%ebp),%eax
mov    %eax,(%esp)
call   0x8048374 
lea    -0x22(%ebp),%eax
mov    %eax,(%esp)
call   0x80483a4 
mov    -0x4(%ebp),%eax
xor    %gs:0x14,%eax
je     0x80484ac 
call   0x8048394 
leave  
ret  

Я не понимаю две строки:

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

Что такое% gs и что именно делают эти две строки?

Это команда компиляции:

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

Ответы [ 3 ]

20 голосов
/ 12 февраля 2012

GS - это сегментный регистр, его использование в linux можно прочитать на здесь (в основном используется для данных процесса).

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

этот код используется для проверкичто стек не взорвался или не был испорчен, используя канарейку, хранящуюся в GS + 0x14, см. this .

3 голосов
/ 12 февраля 2012

ES, FS, GS: дополнительные сегментные регистры. Могут использоваться в качестве дополнительных сегментных регистров;также используется в специальных инструкциях, которые охватывают сегменты (например, строковые копии).взято отсюда

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


надеюсь, что это поможет

2 голосов
/ 02 апреля 2018

На языках ассемблера в стиле AT & T символ процента обычно указывает регистр.В процессорах семейства x86 с 386 года GS является одним из так называемых сегментных регистров .Однако в защищенном режиме регистры сегментов работают как регистры селектора .

. Селектор виртуальной памяти представляет свое собственное отображение виртуального адресного пространства вместе со своим собственным режимом доступа.С практической точки зрения, %gs:0x14 можно рассматривать как ссылку на массив, источник которого хранится в% gs (хотя ЦП и немного разыменовывает).В современных системах GNU / Linux %gs обычно используется для указания на область локального хранилища потока.Однако в коде, о котором вы спрашиваете, важен только один элемент TLS - канарейка стека.

Идея состоит в том, чтобы попытаться обнаружить ошибку переполнения буфера, поместив случайное, но постоянное значение - оно называетсяканарейка стека в памяти канареек, которые шахтеры использовали, чтобы сигнализировать об увеличении уровней ядовитых газов, умирая - в стек до вызова gets() над его рамкой стека и проверяя, является ли онвсе еще там после gets() вернется.gets() не имеет смысла перезаписывать эту часть стека - она ​​находится за пределами своего собственного стекового фрейма, и ей не дается указатель на нее - поэтому, если канарейка стека умерла, что-то пошло не так опасным образом.(C как среда программирования оказывается особенно склонной к такого рода ошибкам, и исследователи безопасности научились использовать многие из них за последние двадцать лет или около того. Кроме того, gets() оказывается функцией, которая по своей природерискует переполнить целевой буфер.) Вы не предлагали адреса с вашим кодом, но 0x80484ac, вероятно, является адресом leave, а call 0x8048394, который выполняется в случае несовпадения (то есть перепрыгивается на je 0x80484ac в случае совпадения), вероятно, является вызовом __stack_chk_fail(), предоставленным libc для обработки повреждения стека, спасаясь от метафорической ядовитой шахты.

Причина, по которой каноническое значение канарейки стека сохраняется вЛокальное хранилище потоков таково, что каждый поток может иметь свой собственный канареечный стек.Сами стеки обычно не разделяются между потоками, поэтому естественно также не использовать канареечное значение.

...