Трассировка стека в коде сборки x86 - PullRequest
3 голосов
/ 13 декабря 2011

Я смотрю на практический экзамен для одного из моих классов, и я просто не понимаю несколько аспектов проблемы, так что, возможно, вы мне поможете (возможно, действительно легко, если вы знаете x86).

Итак, проблема 8 здесь: http://www.coe.utah.edu/~cs4400/schedule/exam3.F10.pdf

И решение для этого здесь: http://www.coe.utah.edu/~cs4400/schedule/exam3_solns.F10.pdf\

Я просто не понимаю, как значения получены в решении. Позвольте мне рассказать о том, как я интерпретирую стек:

08048510 <callfoo>:
08048510: 55       pushl %ebp               # old frame pointer is pushed to the stack  
08048511: 89 e5    movl %esp,%ebp           # frame pointer = stack pointer
08048513: 83 ec 08 subl $0x8,%esp           # allocates 8 bytes for stack
08048516: 83 c4 f4 addl $0xfffffff4,%esp    # this I believe allocates 4 bytes to the stack??
08048519: 68 9c 85 04 08 pushl $0x804859c   # push string address
0804851e: e8 d1 ff ff ff call 80484f4 <foo> # call foo, which takes the string address as param1
08048523: 89 ec    movl %ebp,%esp           # (after foo) does similar to return out of function
08048525: 5d       popl %ebp
08048526: c3       ret

080484f4 <foo>:
080484f4: 55       pushl %ebp                  # push old frame pointer
080484f5: 89 e5    movl %esp,%ebp              # frame pointer = stack pointer
080484f7: 83 ec 18 subl $0x18,%esp             # allocate 24 bytes 
080484fa: 8b 45 08 movl 0x8(%ebp),%eax         # moves the param1 (string pointer) into eax
080484fd: 83 c4 f8 addl $0xfffffff8,%esp       # allocates 8 more bytes (?)
08048500: 50       pushl %eax                  # push x # pushes param1 to stack
08048501: 8d 45 fc leal 0xfffffffc(%ebp),%eax  # adds 12 to the frame pointer, puts it in eax(?)  
08048504: 50       pushl %eax                  # push buf (which apparently is located in eax and 0xc(%ebp)
08048505: e8 ba fe ff ff call 80483c4 <strcpy> # copies the string from param1 into buf
0804850a: 89 ec    movl %ebp,%esp              # puts stack pointer into ebp
0804850c: 5d       popl %ebp                   # pops ebp (returns back to other function)
0804850d: c3       ret

(а) Итак, после этого, я думаю, я вижу, как buf [0] = 0x64636261. Символьный символ - это один байт, и, будучи байтом с прямым порядком байтов, он также может читаться так: buf [0] = 0x61626364 (хотя я не знаю, примет ли мой проф. Этот ответ). Однако , я не понимаю, как buf [2] равно 0x08040069 или 0x69000408. У него есть последний символ, затем нулевой, но что это за 04 и 08?

(б) Я не уверен, как получить (б) или (в). Где я могу получить значение esp, чтобы узнать, что входит в ebp в начале foo? В общем, я просто запутался в этих последних двух ... помощь? (

1 Ответ

3 голосов
/ 24 мая 2013

Кажется, что в этом коде происходит много ненужных манипуляций с указателем стека, но все, что действительно важно, это то, что переменная buf имеет значение ebp-4.Вы можете видеть это из последовательности:

leal 0xfffffffc(%ebp),%eax 
pushl %eax
call 80483c4 <strcpy>

0xfffffffc равно -4, поэтому leal 0xfffffffc(%ebp),%eax устанавливает eax в адрес ячейки памяти ebp-4.Это значение затем помещается в стек в качестве первого аргумента strcpy.Поскольку первый аргумент, переданный strcpy, равен buf, мы знаем, что адрес buf находится в ebp-4.

Теперь рассмотрим, как вызывается стек, как foo.

Сначала в строку адреса вставляется инструкция pushl $0x804859c.

0804859c   # string pointer

Затем, когда вызывается функция foo, адрес инструкции после вызова (08048523) помещается в стек как адрес возврата.

08048523   # return address

Затем внутри foo ebp сохраняется в стеке.В этот момент это может быть что угодно.

????????   # saved ebp

Тогда ebp устанавливается на esp, поэтому теперь он указывает на место, где был сохранен предыдущий ebp.

Теперь, когда мы знаем, что buf находится на уровне ebp-4, это означает, что следующий элемент в стеке будет buf.В стеке выделено намного больше места, чем необходимо для инструкций subl и addl, но все, что нас волнует, это то, что buf находится на ebp-4.Итак, часть стека, о которой мы заботимся, выглядит следующим образом:

0804859c   # string pointer
08048523   # return address
????????   # saved ebp      <- ebp points here
????????   # buff[0]        <- ebp-4 points here

Итак, что теперь происходит, когда вы копируете "abcdefghi" в buff?Поскольку машина не имеет порядка байтов, эти мечи будут заполняться справа налево.У вас есть 9 символов плюс нулевой терминатор в этой строке, поэтому вы собираетесь перезаписать все четыре байта buff[0], все четыре байта сохраненного ebp, а затем два байта адреса возврата.

Итак, ваш стек теперь выглядит следующим образом:

0804859c   # string pointer
08040069   # return address
68676665   # saved ebp      <- ebp points here
64636261   # buff[0]        <- ebp-4 points here

Исходя из этого, должно быть совершенно очевидно, каковы ответы на различные вопросы.

Поскольку стек строится в памяти вниз, buff[1] и buff[2] расположены непосредственно над buff[0] в представлении стека, как я это показал.Таким образом, вы можете видеть, что различные значения баффов просто:

buff[0] = 0x64636261
buff[1] = 0x68676665
buff[2] = 0x08040069

Затем, непосредственно перед инструкцией ret, у нас есть следующие две инструкции:

movl %ebp,%esp
popl ebp

Первая устанавливает esp втекущее значение ebp, поэтому оно будет указывать на позицию в стеке, где был сохранен предыдущий ebp.Однако, глядя на представление стека, вы можете видеть, что это значение теперь перезаписано с 68676665.Поэтому, когда вы вставляете ebp, это значение, которое вы получите.

%ebp = 0x68676665

Аналогично, когда функция вернется, она попытается вытолкнуть адрес возврата из стека, но снова вы можете увидетьиз представления стека, что исходный адрес возврата был частично перезаписан.Так что сразу после того, как ret инструкция eip появится, 08040069.

$eip = 0x08040069

И это, я думаю, ответит на все ваши вопросы.

Я понимаю, что этот вопрос уже несколько летстарый, но он не был закрыт и нет принятого ответа, поэтому, возможно, это объяснение все еще может быть кому-то полезно.

...