Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / практический хакинг.pdf
Скачиваний:
24
Добавлен:
19.04.2024
Размер:
31.35 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Наэтомэтапеоткройтеконсольмониторапоследовательногопор-

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

та, нажав Tools > Serial Monitor (Инструменты > Монитор последо-

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

вательного порта). Serial Monitor – это всплывающее окно, которое может отправлять и получать данные UART в модуль Black Pill и из него.По функциям оно аналогично инструменту screen,который ис- пользовался ранее,но встроено в IDE Arduino для удобства.Нажмите Tools > Port (Инструменты > Порт), чтобы убедиться, что вы выбра- ли порт USB, к которому подключен ваш последовательный адаптер USB.Убедитесь,что скорость передачи в настройках окна Serial Mon- itor составляет 9600, как мы указали в коде. После этого вы должны увидеть приглашение Login: нашей программы Arduino. Введите образец текста для тестирования программы. На рис. 7.17 показан пример сеанса.

Если вы введете какой-либо другой текст, кроме sock-raw.org, вы должны получить сообщение Access Denied (доступ отклонен). В про- тивном случае – сообщение ACCESS GRANTED (доступ разрешен).

Рис.7.17.Всплывающее окно Serial Monitor в среде Arduino IDE

Отладка целевого устройства

Теперь пришло время для основного упражнения: отладки и взлома Black Pill. Если вы выполнили все предыдущие шаги, у вас должна быть полностью рабочая среда отладки, а Black Pill должен содержать написанную нами программу Arduino.

Мы будем использовать OpenOCD для связи с Black Pill с помощью SWD через программатор ST-Link. Сделаем это, чтобы открыть сеанс удаленной отладки с GDB. Затем, используя GDB, пройдемся по ин- струкциям программы и обойдем ее проверку аутентификации.

Запуск сервера OpenOCD

Запустим OpenOCD как сервер. Он нужен нам для связи с Black Pill через SWD.Чтобы запустить его с ядром STM32F103 Black Pill с помо- щью ST-Link,мы должны указатьдва соответствующих файла конфи- гурации с помощью переключателя -f:

218  Глава 7

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

 

o

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

$m

 

 

 

 

 

 

 

 

 

 

 

m

 

 

 

 

 

 

 

sudo openocd -f /usr/local/share/openocd/scripts/interface/stlink.cfg -f /usr/local/share/w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

 

 

 

p

 

 

 

 

 

 

 

 

 

 

df

-xcha

 

e

openocd/scripts/targets/stm32f1x.cfg

 

 

 

df

-x cha

 

e

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

 

 

n

 

 

 

 

[sudo] password for ithilgore:

Open On-Chip Debugger 0.10.0+dev-00936-g0a13ca1a (2019-10-06-12:35) Licensed under GNU GPL v2

For bug reports, read http://openocd.org/doc/doxygen/bugs.html

Info : auto-selecting first available session transport "hla_swd". To override use 'transport

select <transport>'.

Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD

Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : clock speed 1000 kHz

Info : STLINK V2J31S7 (API v2) VID:PID 0483:3748 Info : Target voltage: 3.218073

Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints Info : Listening on port 3333 for gdb connections

Эти файлы конфигурации помогают OpenOCD понять, как взаи- модействовать с устройствами, использующими JTAG и SWD. Если вы установили OpenOCD из источника, как было показано выше, эти файлы конфигурации должны находиться в каталоге /usr/local/share/ openocd.ПослезапускакомандыOpenOCDначнетприниматьлокаль- ные подключения Telnet на TCP-порт 4444 и GDB-подключения на

TCP-порт 3333.

На этом этапе мы откроем сеанс OpenOCD через Telnet и начнем отправлять команды Black Pill через SWD. В другом терминале вве- дите:

$ telnet localhost 4444

Trying 127.0.0.1...

Connected to localhost. Escape character is '^]'. Open On-Chip Debugger

> reset init

target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000538 msp: 0x20005000

>halt

>flash banks

#0 : stm32f1x.flash (stm32f1x) at 0x08000000, size 0x00000000, buswidth 0, chipwidth 0 > mdw 0x08000000 0x20

0x08000000: 20005000 08000539 080009b1 080009b5 080009b9 080009bd 080009c1 08000e15 0x08000020: 08000e15 08000e15 08000e15 08000e15 08000e15 08000e15 08000e15 08000e35 0x08000040: 08000e15 08000e15 08000e15 08000e15 08000e15 08000e15 08000a11 08000a35 0x08000060: 08000a59 08000a7d 08000aa1 080008f1 08000909 08000921 0800093d 08000959 > dump_image firmware-serial.bin 0x08000000 17812

dumped 17812 bytes in 0.283650s (61.971 KiB/s)

Уязвимости портов UART,JTAG и SWD  219

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Команда reset init останавливает целевое устройство и вы-

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

полняет полный сброс, выполняя скрипт reset-init. Этот скрипт

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

представляет собой обработчик событий, который выполняет та- кие задачи, как натройка тактовых импульсов и тактовой частоты JTAG. Вы можете найти примеры этих обработчиков, если посмо-

трите файлы .cfg каталога openocd/scripts/target/. Команда halt

отправляет запрос на останов, чтобы устройство остановилось и перешло в режим отладки. Команда flash banks выводит од- нострочную сводку каждой области флеш-памяти, которая была указана в файле OpenOCD .cfg (в данном случае stm32f1x.cfg). Она выводитна печатьосновную флеш-памятьBlack Pill,которая начи- нается с адреса 0x08000000. Этот шаг важен, поскольку он поможет вам определить, из какого сегмента памяти нужно сделать дамп микропрограммы. Обратите внимание, что иногда значение раз- мера указывается неправильно. Лучшим ресурсом для этого шага остается просмотр таблиц данных. Затем мы отправляем 32-бит- ную команду доступа к памяти mdw , начиная с найденного ранее адреса, чтобы прочитать и отобразить первые 32 байта флеш-па- мяти. Наконец выгружаем целевую память с этого адреса (всего 17 812 байт) и сохраняем ее в файле firmware-serial.bin в локаль- ном каталоге нашего компьютера . Мы получили число 17 812, запросив размер программного файла Arduino, загруженного во флеш-память. Для этого введите следующую команду из времен- ного каталога компилятора Arduino:

/tmp/arduino_build_336697 $ stat -c '%s' serial-simple.ino.bin

17812

Затем вы можете использовать такие инструменты сравнения, как colordiff и xxd, чтобы узнать, есть ли какие-либо различия между файлом firmware-serial.bin, который мы выгружали из флеш-памя- ти, и файлом serial-simple.ino.bin, который мы загрузили через IDE Arduino. Если вы сохранили ровно столько байтов, сколько содержит программа Arduino, в выводе colordiff не должно быть различий:

$ sudo apt install colordiff xxd

$ colordiff -y <(xxd serial-simple.ino.bin) <(xxd firmware-serial.bin) | less

Рекомендуем вам поэкспериментировать с другими командами OpenOCD; все они задокументированы на веб-сайте инструмента. Вот полезная команда, которую стоит попробовать:

> flash write_image erase custom_firmware.bin 0x08000000

Вы можете использовать ее для записи новой прошивки.

220  Глава 7

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

t

 

 

P

D

 

 

 

 

 

 

 

 

o

 

 

 

 

 

NOW!

r

 

 

 

 

 

 

BUY

 

 

Отладка с помощью GDB

 

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

 

.c

 

 

 

 

p

df

 

 

 

 

e

 

 

 

 

 

 

 

g

 

 

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

 

-x cha

 

 

 

 

 

Давайте отладим и изменим поток выполнения программы Arduino

 

 

 

 

 

 

 

с помощью GDB. С уже запущенным сервером OpenOCD мы можем начатьудаленный сеанс GDB.Чтобы облегчитьсвою задачу,мы будем использовать файл в формате исполняемых и связываемых файлов (ELF), созданный во время компиляции программы Arduino. ELF – стандартный формат файла для исполняемых файлов, объектного кода, разделяемых библиотек и дампов ядра в Unix-подобных систе- мах. В этом случае он действует как промежуточный файл во время компиляции.

Перейдите во временный каталог, созданный во время компиля- ции. Убедитесь, что вы изменили случайную часть имени каталога на значение, полученное в результате вашей собственной компиля- ции Arduino. Затем, предполагая, что ваша программа Arduino была названа serial-simple, запустите удаленный сеанс GDB, используя команду­ gdb-multiarch с аргументами, приведенными ниже:

$ cd /tmp/arduino_build_336697/

$ gdb-multiarch -q --eval-command="target remote localhost:3333" serial-simple.ino.elf

Reading symbols from serial-simple.ino.elf...done. Remote debugging using localhost:3333

0x08000232 in loop () at /home/ithilgore/Arduino/serial-simple/serial-simple.ino:15 15 if (start == true) {

(gdb)

Эта команда откроет сеанс GDB и используетлокальный двоичный файл ELF (называемый serial-simple.ino.elf), созданный Arduino во время компиляции для отладочных символов. Отладочные симво- лы–это примитивные типы данных,которые позволяют отладчикам получатьдоступктакойинформации,какпеременныеиименафунк- ций, из исходного кода двоичного файла.

Теперь вы можете использовать этот терминал, чтобы отправлять команды GDB. Начните с ввода команды info functions, чтобы убе- диться, что символы действительно были загружены:

(gdb) info functions

All defined functions:

File /home/ithilgore/Arduino/hardware/Arduino_STM32-master/STM32F1/cores/maple/HardwareSerial. cpp:

HardwareSerial *HardwareSerial::HardwareSerial(usart_dev*, unsigned char, unsigned char); int HardwareSerial::available();

File /home/ithilgore/Arduino/serial-simple/serial-simple.ino: void loop();

void recv_data(); void setup(); void validate();

Уязвимости портов UART,JTAG и SWD  221

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Теперь поместим точку останова на функцию validate(), потому

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

что имя подразумевает, что она выполняет какую-то проверку, кото-

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

рая может быть связана с аутентификацией.

(gdb) break validate

Breakpoint 1 at 0x800015c: file /home/ithilgore/Arduino/serial-simple/serial-simple.ino, line 55.

Поскольку отладочная информация,записанная в двоичном файле ELF, сообщает GDB о том, какие исходные файлы использовались для его сборки, мы можем использовать команду list для печати частей исходного кода программы. Такая удобная возможность редко пре- доставляется в реальных сценариях обратного проектирования, где вам придется полагаться на команду дизассемблирования, которая вместо исходного кода показывает код ассемблера. Вот результат вы- полнения обеих команд:

(gdb) list validate,

55void validate() {

56Serial1.println(buf);

57new_data = false;

58

59if (strcmp(buf, "sock-raw.org") == 0)

60Serial1.println("ACCESS GRANTED");

61else {

62Serial1.println("Access Denied.");

63Serial1.print("Login: ");

64}

(gdb) disassemble validate

Dump of assembler code for function validate():

0x0800015c <+0>: push

{r3,

lr}

0x0800015e <+2>: ldr

r1, [pc, #56] ; (0x8000198 <validate()+60>)

0x08000160

<+4>: ldr

r0, [pc, #56] ; (0x800019c <validate()+64>)

0x08000162

<+6>: bl

0x80006e4 <Print::println(char const*)>

0x08000166

<+10>: ldr

r3, [pc, #56] ; (0x80001a0 <validate()+68>)

0x08000168

<+12>: movs

r2, #0

0x0800016a <+14>: ldr

r0, [pc, #44] ; (0x8000198 <validate()+60>)

0x0800016c <+16>: ldr

r1, [pc, #52] ; (0x80001a4 <validate()+72>)

0x0800016e <+18>: strb

r2, [r3, #0]

0x08000170

<+20>: bl

0x8002de8 <strcmp>

0x08000174

<+24>: cbnz

r0, 0x8000182 <validate()+38>

0x08000176

<+26>: ldr

r0, [pc, #36] ; (0x800019c <validate()+64>)

ПРИМЕЧАНИЕ    Вы можете использовать более короткие версии мно- гих команд GDB, такие как l вместо list, disas вместо disassemble и b вместо break.Если вы долго пользуетесь GDB,такие сокращения за- метно облегчают работу

222  Глава 7

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Если у вас есть только ассемблерный код, импортируйте файл

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

(в данном случае serialsimple.ino.elf) в декомпилятор наподобие техdf,-x chan

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

e

 

что предоставляет Ghidra или IDA Pro. Это очень поможет вам, пото- му что он переведет ассемблерный код в C, который намного легче читать (рис. 7.18).

Рис.7.18.Использование декомпилятора в Ghidra для быстрого чтения кода C вместо кода сборки

Если у вас есть только шестнадцатеричный файл (например, firm- ware-serial.bin) как результат сброса микропрограммы из флеш-па- мяти, вам сначала придется дизассемблировать его, используя ин- струментарий ARM следующим образом:

$ arm-none-eabi-objdump -D -b binary -marm -Mforce-thumb firmware-serial.bin > output.s

Файл output.s будет содержать ассемблерный код.

Теперьдавайте посмотрим,как мы можем обойти процесс простой аутентификации нашей цели.Чтобы продолжить нормальное выпол- нение программы, введите команду continue (или,для краткости, c):

(gdb) continue

Continuing.

Теперь программа ожидает последовательного ввода. Откройте монитор последовательного порта в средеArduino IDE,как мы этоде- лали раньше, введите образец пароля, например test123, и нажмите Enter. На терминале GDB вы должны увидеть, что срабатывает точка останова для функции проверки. С этого момента мы заставим GDB автоматически отображать следующую инструкцию, которая будет

Уязвимости портов UART,JTAG и SWD  223

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

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

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

выполнениякомандыdisplay / i $ pc.Затеммыпостепенноперейдем

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

к одной машинной инструкции, используя команду stepi, пока не дойдем до вызова strcmp. Дойдя до вызова Print :: println, обойдем его, потому что это не касается нас в данном контексте (листинг 7.2):

Листинг 7.2. Пошаговое выполнение функции проверки нашей программы в GDB

Breakpoint 1, validate () at /home/ithilgore/Arduino/serial-simple/serial-simple.ino:55

55

void validate() {

 

 

 

 

(gdb) display/i $pc

 

 

 

 

1: x/i $pc

 

 

 

 

 

=> 0x800015c <validate()>: push

{r3, lr}

 

(gdb) stepi

 

 

 

 

 

halted: PC: 0x0800015e

 

 

 

 

56

 

Serial1.println(buf);

 

 

 

3: x/i $pc

 

 

 

 

 

=> 0x800015e <validate()+2>:

ldr

r1, [pc, #56]

; (0x8000198 <validate()+60>)

(gdb) stepi

 

 

 

 

 

halted: PC: 0x08000160

 

 

 

 

0x08000160

56

Serial1.println(buf);

 

1: x/i $pc

 

 

 

 

 

=> 0x8000160 <validate()+4>:

ldr

r0, [pc, #56]

; (0x800019c <validate()+64>)

(gdb) stepi

 

 

 

 

 

halted: PC: 0x08000162

 

 

 

 

0x08000162

56

Serial1.println(buf);

 

1: x/i $pc

 

 

 

 

 

=> 0x8000162 <validate()+6>:

bl

0x80006e4 <Print::println(char const*)>

(gdb) next

 

 

 

 

 

halted: PC: 0x080006e4

 

 

 

 

57

 

new_data = false;

 

 

 

1: x/i $pc

 

 

 

 

 

=> 0x8000166 <validate()+10>:

ldr

r3, [pc, #56]

; (0x80001a0 <validate()+68>)

(gdb) stepi

 

 

 

 

 

halted: PC: 0x08000168

 

 

 

 

0x08000168

57

new_data = false;

 

1: x/i $pc

 

 

 

 

 

=> 0x8000168 <validate()+12>:

movs r2, #0

 

(gdb) stepi

 

 

 

 

 

halted: PC: 0x0800016a

 

 

 

 

59

 

if (strcmp(buf, "sock-raw.org") == 0)

 

1: x/i $pc

 

 

 

 

 

=> 0x800016a <validate()+14>:ldr

r0, [pc, #44] ; (0x8000198 <validate()+60>)

(gdb) stepi

 

 

 

 

 

halted: PC: 0x0800016c

 

 

 

 

0x0800016c

59

if (strcmp(buf, "sock-raw.org") == 0)

1: x/i $pc

 

 

 

 

 

=> 0x800016c <validate()+16>:

ldr

r1, [pc, #52]

; (0x80001a4 <validate()+72>)

(gdb) stepi

 

 

 

 

 

halted: PC: 0x0800016e

 

 

 

 

57

 

new_data = false;

 

 

 

1: x/i $pc

 

 

 

 

 

=> 0x800016e <validate()+18>:

strb

r2, [r3, #0]

 

224

Глава 7

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

t

 

 

 

 

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

 

 

 

 

to

 

 

 

 

 

(gdb) stepi

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

o

m

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

e halted: PC: 0x08000170

 

 

 

 

p

df

 

 

 

g

.c

 

 

 

 

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

-xcha

 

 

 

 

59

if (strcmp(buf, "sock-raw.org") == 0)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1: x/i $pc

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

=> 0x8000170 <validate()+20>:

bl

0x8002de8 <strcmp>

 

 

 

 

 

 

 

 

 

 

 

(gdb) x/s $r0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x200008ae <buf>:

"test123"

 

 

 

 

 

 

 

 

 

 

 

 

 

(gdb) x/s $r1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x8003a48:

"sock-raw.org"

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Последниедве команды GDB (x/s $r0 иx/s $r1 ) отображаютсо- держимоерегистровr0 иr1 ввидестрок.Этирегистрыдолжнысодер- жать два аргумента, переданных функции strcmp() Arduino, потому что, согласно стандарту вызова процедур ARM (APCS), первые четы- ре аргумента любой функции передаются в первые четыре регистра ARM r0, r1, r2, r3. Это означает, что регистры r0 и r1 содержат адреса строки test123 (которую мы указали как пароль) и строку действи- тельного пароля sock-raw.org, для которой выполняется сравнение. Вы можете отобразить все регистры в GDB в любое время, выполнив команду info registers (или,для краткости, i r).

Теперь мы можем обойти аутентификацию несколькими способа- ми. Самый простой способ – установить значение r0 для sock-raw.org прямо перед тем, как выполнение достигнет вызова strcmp(). Вы мо- жете легко сделать это, введя следующую команду GDB:

set $r0="sock-raw.org"

В качестве альтернативы, если бы нам не было известно правиль- ное строковое значение ключевой фразы,мы могли бы обойти аутен- тификацию, обманув программу – заставив ее думать, что strcmp() завершилась успешно. Для этого мы изменим возвращаемое значе- ние strcmp() сразу после его возврата. Обратите внимание, что strcmp() возвращает 0 в случае успеха.

Мы можем изменить возвращаемое значение с помощью команды cbnz, которая предназначена для сравнения и перехода на ненулевое значение. Она проверяет регистр в левом операнде и, если он не ра- вен нулю, выполняет переход (ветвление) к месту назначения, ука- занномувправомоперанде.Вэтомслучаерегистр–r0,ионсодержит возвращаемое значение strcmp():

0x08000170

<+20>:

bl

0x8002de8 <strcmp>

0x08000174

<+24>:

cbnz

r0, 0x8000182 <validate()+38>

 

 

 

 

Теперь мы перейдем к функции strcmp(), выполнив еще одну команду­ stepi, когда достигнем ее. Затем мы можем выйти из нее, выполнив команду завершения. Непосредственно перед выполнени- ем команды cbnz изменим значение r0 на 0, что указывает на успеш- ное выполнение strcmp():

Уязвимости портов UART,JTAG и SWD  225