Переполнение стека eip x86 vs x86_64 easy C code - PullRequest
10 голосов
/ 08 декабря 2011

Позвольте мне пропустить вступление и перейти к хорошей части.Я читаю «Руководство по этическим хакерам» и пробую пример кода (около p175).

-----------------------------------------------------------------------------------------

Цель: переполнение EIP в стеке

Пример кода:

##> cat overflow.c
main(){
    char str1[10];   // declare a 10byte string
    // next, copy 35 bytes of 'A' to 'str1'
    strcpy(str1,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}

-----------------------------------------------------------------------------------------

Если я скомпилирую и запусту его на своем ноутбуке x86, тогда результат будет ожидаемым.

результат на X86 с openSuse 12.1

##> uname -a
Linux linux-tzxm.site 3.1.0-1.2-desktop #1 SMP PREEMPT 
Thu Nov 3 14:45:45 UTC 2011 (187dde0) i686 i686 i386 GNU/Linux

##> cat /proc/sys/kernel/randomize_va_space 
1

##> gcc version 4.6.2 (SUSE Linux)
##> GNU gdb (GDB) SUSE (7.3-41.1.2)

##> gdb -q overflow

Reading symbols from /home/administrator/Programming/C/testProgs/overflow...done.

(gdb) run

Starting program: /home/administrator/Programming/C/testProgs/overflow 

Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

(gdb) info reg eip

eip            0x41414141       0x41414141

-----------------------------------------------------------------------------------------

Однако, если я сделаю то же самое на своем ноутбуке x86_64, то результат будет другим и не таким, как ожидалось (насколько я знаюточка зрения)

результат на x86_64 с openSuse 11.3

##> uname -a
Linux linux-2mna.site 2.6.34.10-0.4-desktop #1 SMP PREEMPT 2011-10-19 22:16:41 +0200 x86_64 x86_64 x86_64 GNU/Linux

##> cat /proc/sys/kernel/randomize_va_space 
1

##> gcc version 4.5.0 20100604
##> GNU gdb (GDB) SUSE (7.1-3.12)

##> gdb -q overflow2

Reading symbols from /home/jojojorn/Documents/Personal/HACKING/C_Prog/Tests/testProgs/overflow2...done.

(gdb) run

Starting program: /home/jojojorn/Documents/Personal/HACKING/C_Prog/Tests/testProgs/overflow2 

Program received signal SIGSEGV, Segmentation fault.

0x0000000000400553 in main () at overflow.c:11
11      }

(gdb) info reg eip

Invalid register `eip'

(gdb) 

-----------------------------------------------------------------------------------------

Итак, вот мои вопросы:

1) почему я не могу переполнить EIPв моем стеке на моем x86_64?Есть ли разница в поведении стека между x86_64 и x86?

2), когда я запускаю скомпилированный двоичный файл x86 на своем x86_64 и проверяю его с помощью gdb, тогда результат снова, как и ожидалось.Итак, я полагаю, что разница сделана с использованием 32-битных gcc и 64-битных gcc?Для этого простого кода, в чем и в чем разница?

3) Если я хочу, чтобы мой код на x86_64 вел себя так, как он был скомпилирован на x86, есть ли параметр gcc для установки во время компиляции?

4) Я задаю этот вопрос, а это значит, что у меня еще нет достаточных знаний, чтобы задавать лучшие вопросы.Есть ли что-то еще, что приходит в твои гениальные умы, что я должен спросить (и на что ты бы ответил)?

С уважением

Ответы [ 2 ]

16 голосов
/ 08 декабря 2011

На x86_64 указатель инструкции RIP, а не EIP ... таким образом, если вы запросите регистр EIP в gdb с 64-битным исполняемым файлом, вы не получите никаких значений поскольку это не правильный 64-битный регистр. Если вы хотите сохранить свой исполняемый файл 32-битным на собственной 64-битной платформе, то передайте gcc флаг -m32 во время компиляции.

Если вы хотите посмотреть, как ведет себя стек Unix x86_64 по сравнению со стеком Unix x86, то я предлагаю прочитать ABI Unix x86_64 , разделы 3.2 и 3.4.

1 голос
/ 08 декабря 2011
  1. Дело не в том, что на x86_64 нет переполнения, это просто другой способ представления исключения.Вместо того, чтобы фактически сказать вам, что он не смог выполнить код 0x4141414141414141 после он фактически обновил rip, он сообщает вам, что адрес назначения недействителен до обновления.Это архитектурное различие между кодом x86 и кодом x86_64, и всякий раз, когда вы выполняете 64-битный код, именно так он обрабатывается.

  2. Опять же, вы бы по-разному получали другое сообщениеТолько 64-битный код.

  3. Вы должны скомпилировать его как 32-битный код.Невозможно получить такое же сообщение, если вы скомпилируете его как код x86_64.

  4. На самом деле не трудно заметить эту разницу, если вы правильно отладите код и посмотрите, где rip указывает на значения других регистров.

...