Определение обратного адреса функции на серии ARM Cortex-M - PullRequest
1 голос
/ 26 февраля 2020

Я хочу определить адрес возврата функции в Keil. Я открыл раздел дизассемблирования в режиме отладки в Keil Uvision. Ниже показан некоторый код сборки:

enter image description here

Мое намерение состоит в том, чтобы ввести простой двоичный код в микроконтроллер с помощью переполнения буфера в микроконтроллере. см. Переполнение буфера Я хочу определить адрес возврата функции "test". Обязательно ли знать, как читать ассемблерный код, или есть хитрость, чтобы найти адрес возврата?

Я новичок ie в сборке.

Ответы [ 3 ]

3 голосов
/ 26 февраля 2020

R14 или под другим именем LR удерживайте обратный адрес. Слева вы можете увидеть это на картинке. Это 0x08000287.

1 голос
/ 26 февраля 2020

Когда вызывается функция, R14 будет перезаписан адресом после инструкции вызова («BL» или «BLX»). Если эта функция не вызывает никаких других функций, R14 будет часто оставаться с адресом возврата в течение его продолжительности. Кроме того, если функция tail вызывает другую функцию, хвостовой вызов может быть заменен ветвью ("B" или "BX"), где R14 содержит адрес возврата исходного вызывающего абонента. Если функция выполняет нехвостый вызов другой функции, необходимо будет сохранить R14 «где-то» (обычно в стеке, но, возможно, в другом ранее используемом регистре, сохраненном вызывающим абонентом) в некоторое время до этого и извлечь это значение из стека через некоторое время, но если оптимизация включена, то место, где сохраняется R14, обычно будет непредсказуемым.

У некоторых компиляторов может быть режим, который бы достаточно последовательно складывал вещи, чтобы их можно было использовать, но код будет очень зависит от компилятора. Скорее всего, техника будет успешной:

extern int getStackAddress(uint8_t **addr);  // Always returns zero
void myFunction(...whavever...)
{
  uint8_t *returnAddress;
  if (getStackAddress(&returnAddress)) return; // Put this first.
}

, где getStackAddress будет функцией машинного кода, которая сохраняет R14 по адресу в R0, загружает R0 с нуля и затем ветвится до R14. Существует относительно немного кодовых последовательностей, которые могли бы последовать этому, и если код проверяет инструкции по адресу, сохраненному в returnAddress, и распознает одну из этих кодовых последовательностей, он будет знать, что адрес возврата для myFunction хранится в место, подходящее для рассматриваемой последовательности. Например, если он видит:

    test r0,r0
    be ...
    pop {r0,pc}

Он будет знать, что адрес вызывающего абонента является вторым в стеке. Аналогично, если он увидит:

    cmp r0,#0
    bne somewhere:
somewhere: ; Compute address based on lower byte of bne
    pop {r0,r1,r2,r4,r5,pc}

, тогда он узнает, что адрес вызывающего является шестым.

Есть несколько компиляторов инструктонов, которые могут использовать для проверки регистра на ноль, и некоторые компиляторы могут используйте be, в то время как другие используют bne, но для вышеприведенного кода компиляторы, скорее всего, будут использовать вышеуказанный шаблон, и поэтому подсчет количества битов, установленных в инструкции pop, покажет местонахождение адреса возврата на стек. До времени выполнения никто не будет знать, будет ли этот тест действительно работать, но в тех случаях, когда он утверждает, что идентифицирует обратный адрес, он должен быть правильным.

0 голосов
/ 26 февраля 2020

Вы можете найти все ответы в документации Cortex-M

http://infocenter.arm.com/help/index.jsp?topic= / com.arm.do c .ddi0337h / Chdedegj. html

enter image description here

...