ARM обратный инжиниринг дампа ROM - PullRequest
0 голосов
/ 07 февраля 2019

У меня старая встроенная система с процессором ARM, я выгружал ПЗУ, извлекал с помощью binwalk и загружал в IDA pro.Я обнаружил в некоторой подпрограмме BX не с LR, а с регистром общего назначения (R2, R3 и т. Д.) В псевдокоде, что-то вроде этого «memory [0xCC1232] (a3, v4)», это пример.Я думал, что это похоже на функцию указателя C компилятора ARM.это может быть?Во всяком случае, мой главный вопрос заключается в следующем: как я могу найти эту подпрограмму (memoryx ..) только с rom dump? Потому что адрес - это адрес оперативной памяти, поэтому без ram dump я не могу найти ссылку на эту подпрограмму? Я подумал найти подпрограммучто записать значение в этот конкретный адрес, но это почти невозможно, спасибо

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

в зависимости от настроек компилятора и от того, какое ядро ​​предназначается, bx без lr очень распространено, если не требуется, поскольку pop старых ядер (обычно ldmia) lr не работает для переключения между режимами arm и thumb, поэтому компиляторы будутсгенерируйте pop как r3, а затем bx r3.

extern unsigned int more_fun ( void );
unsigned int fun ( void )
{
    return(more_fun()+1);
}

00000000 <fun>:
   0:   b510        push    {r4, lr}
   2:   f7ff fffe   bl  0 <more_fun>
   6:   3001        adds    r0, #1
   8:   bc10        pop {r4}
   a:   bc02        pop {r1}
   c:   4708        bx  r1
   e:   46c0        nop         ; (mov r8, r8)

vs

00000000 <fun>:
   0:   b508        push    {r3, lr}
   2:   f7ff fffe   bl  0 <more_fun>
   6:   3001        adds    r0, #1
   8:   bd08        pop {r3, pc}
   a:   bf00        nop

r4 против r3, поскольку фиктивный регистр здесь не имеет значения, интересно, что это делает компилятор, но они просто используются для выравнивания стека,не сохранять регистр.

это, конечно, режим большого пальца, режим охраны

00000000 <fun>:
   0:   e92d4010    push    {r4, lr}
   4:   ebfffffe    bl  0 <more_fun>
   8:   e8bd4010    pop {r4, lr}
   c:   e2800001    add r0, r0, #1
  10:   e12fff1e    bx  lr

, вы ожидаете увидеть, что lr используется с bx lr

или это дляновее, но gcc, по крайней мере, по умолчанию работает в режиме большого пальца, и вы должны заставить его генерировать код руки, подобный следующемувозможный.если это встроенная система, и все находится в энергонезависимой памяти (flash / rom / etc), то в какой-то момент, если код находится в оперативной памяти, он копируется или распаковывается или иным образом в оперативную память перед переходом на ветвь.С другой стороны, вы, возможно, разбирали некоторый код, который может вызывать код в ram, но этот код в ram может поступать из загрузки, в основном это какой-то внешний источник, который в конечном итоге отсутствует на плате / чипе.Подобно загрузчику, в котором есть код для загрузки программы через uart и последующего перехода к ней, это не означает, что код используется нормально, и, безусловно, означает, что вы не можете предсказать или знать, каким будет этот код, тем более найти его и разобрать.

bx из not lr можно использовать вручную для запуска в такой код, если я загружаю в 0x20000000 и каким-то образом знаю, что это код большого пальца, а не рука, тогда мне нужно каким-то образом направить адрес с 1, затем bxк тому же, иногда вы делаете это с помощью регистра, иногда нет.

вы также увидите bx, используемый компоновщиком для исправления чего-то далеко или для изменения режимов:

unsigned int more_fun ( void )
{
    return(3);
}

компоновщик добавляет батут для вас:

00000000 <fun>:
   0:   e92d4010    push    {r4, lr}
   4:   eb000003    bl  18 <__more_fun_from_arm>
   8:   e8bd4010    pop {r4, lr}
   c:   e2800001    add r0, r0, #1
  10:   e12fff1e    bx  lr

00000014 <more_fun>:
  14:   2003        movs    r0, #3
  16:   4770        bx  lr

00000018 <__more_fun_from_arm>:
  18:   e59fc000    ldr r12, [pc]   ; 20 <__more_fun_from_arm+0x8>
  1c:   e12fff1c    bx  r12
  20:   00000015    andeq   r0, r0, r5, lsl r0
  24:   00000000    andeq   r0, r0, r0

и в этом случае используется r12.

0 голосов
/ 07 февраля 2019

В общем случае невозможно определить фактический адрес перехода без разборки и анализа кода.Однако возможны несколько советов и приемов.

  1. Очень часто часть ПЗУ копируется в ОЗУ при очень раннем запуске.Попробуйте найти эту процедуру копирования в инициализации.Если вам повезет, вы сможете получить начальное содержимое интересующего вас места в ОЗУ. А если вам очень повезет, это место не будет перезаписано во время выполнения, и это будут фактические данные.(См. Ниже)
  2. Попробуйте разобрать часть кода раньше.В большинстве случаев адрес извлекается из некоторой таблицы в ПЗУ, затем сохраняется в локальной переменной, и адрес этой таблицы там.
  3. В большинстве случаев тела кода подпрограммы располагаются при запуске ПЗУ вплотную, начиная с точки входаи закончился BX LR.Вы можете найти все или большинство точек входа в подпрограмму, просто просканировав ПЗУ, подозревая, что точка входа в следующую подпрограмму находится рядом с «BX LR» предыдущей.Чтобы определить, вызывается ли определенная подпрограмма косвенно, попробуйте найти, существует ли ее простой адрес где-то в ПЗУ, или она загружена парой 'MOVW' + 'MOVT'.Это дает вам представление о том, где его можно использовать.
  4. В некоторых случаях адрес подпрограммы передается в качестве параметра для вызова подпрограммы.Поэтому попробуйте найти, ссылается ли какой-либо вызывающий абонент на какой-либо адрес в коде.
  5. Могут быть таблицы процедур, похожие на длинные последовательности слов, указывающие на область кода ПЗУ (возможно, чередующиеся с нулями).Попробуйте найти их и определить, какой из них можно использовать в вашем случае.

Пример кода инициализации ОЗУ, взятого из среды выполнения GNAT:

        movw    r0,#:lower16:__data_start ; __data_start points to RAM
        movt    r0,#:upper16:__data_start ; (often it is start of RAM)
        movw    r1,#:lower16:__data_words
        movw    r2,#:lower16:__data_load  ; __data_load points to ROM
        movt    r2,#:upper16:__data_load  ; right after code and readonly data
        cbz     r1,1f
0:      ldr     r4,[r2],#4
        str     r4,[r0],#4
        subs    r1,r1,#1
        bne     0b
1:
...