[Информационная безопасность, Assembler, Реверс-инжиниринг, Хранение данных, CTF] Ломаем зашифрованный диск для собеседования от RedBalloonSecurity. Part 1

Автор Сообщение
news_bot ®

Стаж: 6 лет 4 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
29-Мар-2021 02:31

А что дальше?Хабровчане и хабровчушки, эта статья является долгожданным (ага, в пару дней) продолжением моей предыдущей статьи о взломе жесткого диска для собеседования в инфосек компанию RedBalloonSecurity. Любителей поковырять железяки я спешу разочаровать, поскольку все дальнейшие манипуляции с диском будут проводится только на уровне ассемблерного кода и логики. Поэтому, приготовьте чай/кофе или чего покрепче, ведь мы снова лезем в embeded дебри и опять пускаемся в неизвестность.LEVEL2Моему счастью не было предела когда я залил пропатченую прошивку на Winbond Flash чип и ядро моего Debian-неттопа распознало еще 1 раздел диска. Здесь будет немного больше информации, чем в предыдущем разделе. Ведь повышая уровень, сложность нашей с вами задачи только увеличивается.Содержимое раздела:
tkchk@ubuntu:/media/user/LEVEL2$ file *
0001-keystone-armv5.patch: unified diff output, ASCII text
level_2.html:              HTML document, ASCII text, with very long lines
level2_instructions.txt:   ASCII text
level_2.lod:               data
level_3.lod.7z.encrypted:  7-zip archive data, version 0.3
  • level_2.lod - это новый файл прошивки для диска. Прошиваемся так же, как и в предыдущей статье. Здесь ничего нового.
  • level_3.lod.7z.encrypted - это файл прошивки для следующего уровня. Судя по его разрешению, файл находится в запароленном 7z архиве. Нам нужно решить текущий уровень чтоб достать пароль от слудующего.
  • level2_instructions.txt - это, собственно, инструкции что и как делать. Подсказки тоже имеются.
  • 0001-leystone-armv5.patch - это патч для Keystone Assembler. Keystone это компилятор и набор С-шных библиотек для перевода ассемблерного кода в опкоды для процессора. Об этом чуть позже.
  • level_2.html - изюминка текущего уровня. Выглядит точ-в-точ как текст, который генерирует IDA Pro при загрузке бинарника.
Для тех, кто не в курсе, IDA Pro это программа для дизассемблирования. Дело в том, что когда мы пишем код на высокоуровневых языках (C, Python и тд) и подвергаем его компиляции, мы переводим наш +- human-readable текст в язык машинного кода. Тоесть, мы опускаем более понятную человеку логику в логику, которая больше понятна машине. Машина не понимает что такое функция, ведь функция, это скорее абстракция в голове у программиста. Процесс дизассемблирования позволяет сделать наоборот - поднять логику из машинного на человекопонятный уровень. Некоторые дизассемблеры позволяют поднять логику даже на C-шный уровень, хоть и не всегда делают это корректно (на самом деле очень даже корректно, но читать такой код порой бывает сложнее чем ассемблер). Если работаем с чем-то мелким, и надо кабанчиком понять что там происходит - этого хватит, но для более высокоточных вещей нужен уровень ассемблера. Это мы и получили в виде level_2.html файла.
tkchk@ubuntu:/media/user/LEVEL2$ cat level2_instructions.txt
Congratulations... you have made it to the other side
Back when I was an intern, I designed this key generation function. My boss hated it.
I hate my boss.
1. Invoke the function with command R<User_Input>
2. Find the key you must!!!!!
level2.html provides disassembly of a memory snapshot of the key generator function.
To help... guide... you in this adventure, you'll find a patchfile for the keystone
assembler to force the correct architecture.
Also, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASCII
0001-keystone-armv5.patch
tkchk@ubuntu-mac:/media/tkchk/LEVEL2$ cat 0001-keystone-armv5.patch
From 5532e7ccbc6c794545530eb725bed548cbc1ac3e Mon Sep 17 00:00:00 2001
From: mysteriousmysteries <mysteriousmysteries@redballoonsecurity.com>
Date: Wed, 15 Feb 2017 09:23:31 -0800
Subject: [PATCH] armv5 support
---
llvm/keystone/ks.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp
index d1819f0..8c66f19 100644
--- a/llvm/keystone/ks.cpp
+++ b/llvm/keystone/ks.cpp
@@ -250,7 +250,7 @@ ks_err ks_open(ks_arch arch, int mode, ks_engine **result)
     if (arch < KS_ARCH_MAX) {
         ks = new (std::nothrow) ks_struct(arch, mode, KS_ERR_OK, KS_OPT_SYNTAX_INTEL);
-
+
         if (!ks) {
             // memory insufficient
             return KS_ERR_NOMEM;
@@ -294,7 +294,7 @@ ks_err ks_open(ks_arch arch, int mode, ks_engine **result)
                         TripleName = "armv7";
                         break;
                     case KS_MODE_LITTLE_ENDIAN | KS_MODE_THUMB:
-                        TripleName = "thumbv7";
+                        TripleName = "armv5te";
                         break;
                 }
@@ -566,7 +566,7 @@ int ks_asm(ks_engine *ks,
     Streamer = ks->TheTarget->createMCObjectStreamer(
             Triple(ks->TripleName), Ctx, *ks->MAB, OS, CE, *ks->STI, ks->MCOptions.MCRelaxAll,
             /*DWARFMustBeAtTheEnd*/ false);
-
+
     if (!Streamer) {
         // memory insufficient
         delete CE;
@@ -594,7 +594,7 @@ int ks_asm(ks_engine *ks,
         return KS_ERR_NOMEM;
     }
     MCTargetAsmParser *TAP = ks->TheTarget->createMCAsmParser(*ks->STI, *Parser, *ks->MCII, ks->MCOptions);
-    if (!TAP) {
+    if (!TAP) {
         // memory insufficient
         delete Parser;
         delete Streamer;
--
1.9.1
level_2.html
ROM:00332D00
ROM:00332D00 ; Segment type: Pure code
ROM:00332D00                 AREA ROM, CODE, READWRITE, ALIGN=0
ROM:00332D00                 ; ORG 0x332D00
ROM:00332D00                 CODE16
ROM:00332D00
ROM:00332D00 ; =============== S U B R O U T I N E =======================================
ROM:00332D00
ROM:00332D00 ; prototype: generate_key(key_part_num, integrity_validate_table, key_table)
ROM:00332D00 ; Function called when serial console input is 'R'. Generates key parts in R0-R3.
ROM:00332D00 ; The next level to reach, the key parts to print you must!
ROM:00332D00
ROM:00332D00 generate_key
ROM:00332D00
ROM:00332D00 var_28          = -0x28
ROM:00332D00
ROM:00332D00                 PUSH            {R4-R7,LR}
ROM:00332D02                 SUB             SP, SP, #0x10
ROM:00332D04                 MOVS            R7, R1
ROM:00332D06                 MOVS            R4, R2
ROM:00332D08                 MOVS            R5, R0
ROM:00332D0A                 LDR             R1, =0x6213600 ; "R"...
ROM:00332D0C                 LDRB            R0, [R1,#1]
ROM:00332D0E                 CMP             R0, #0x31
ROM:00332D10                 BNE             loc_332D1A
ROM:00332D12                 ADDS            R0, R1, #2
ROM:00332D14                 BLX             ahex2byte
ROM:00332D18                 LDR             R1, =0x6213600
ROM:00332D1A
ROM:00332D1A loc_332D1A                              ; CODE XREF: generate_key+10j
ROM:00332D1A                 MOV             R2, SP
ROM:00332D1C
ROM:00332D1C loc_332D1C                              ; CODE XREF: generate_key+28j
ROM:00332D1C                 LDRB            R6, [R1]
ROM:00332D1E                 ADDS            R1, R1, #1
ROM:00332D20                 CMP             R6, #0xD
ROM:00332D22                 BEQ             loc_332D2A
ROM:00332D24                 STRB            R6, [R2]
ROM:00332D26                 ADDS            R2, R2, #1
ROM:00332D28                 B               loc_332D1C
ROM:00332D2A ; ---------------------------------------------------------------------------
ROM:00332D2A
ROM:00332D2A loc_332D2A                              ; CODE XREF: generate_key+22j
ROM:00332D2A                 SUBS            R5, #0x49
ROM:00332D2C                 CMP             R5, #9
ROM:00332D2E                 BGT             loc_332DD8
ROM:00332D30                 LSLS            R5, R5, #1
ROM:00332D32                 ADDS            R5, R5, #6
ROM:00332D34                 MOV             R0, PC
ROM:00332D36                 ADDS            R5, R0, R5
ROM:00332D38                 LDRH            R0, [R5]
ROM:00332D3A                 ADDS            R0, R0, R5
ROM:00332D3C                 BX              R0
ROM:00332D3C ; ---------------------------------------------------------------------------
ROM:00332D3E                 DCW 0x15
ROM:00332D40                 DCW 0xA6
ROM:00332D42                 DCW 0xA4
ROM:00332D44                 DCW 0xA2
ROM:00332D46                 DCW 0xA0
ROM:00332D48                 DCW 0x9E
ROM:00332D4A                 DCW 0x2E
ROM:00332D4C                 DCW 0x50
ROM:00332D4E                 DCW 0x98
ROM:00332D50                 DCW 0xC
ROM:00332D52 ; ---------------------------------------------------------------------------
ROM:00332D52
ROM:00332D52 key_part1
ROM:00332D52                 LDR             R0, [R4]
ROM:00332D54                 MOVS            R6, #1
ROM:00332D56                 STR             R6, [R7]
ROM:00332D58                 BLX             loc_332DEC
ROM:00332D5C                 CODE32
ROM:00332D5C
ROM:00332D5C key_part2
ROM:00332D5C                 LDR             R6, [R7]
ROM:00332D60                 CMP             R6, #1
ROM:00332D64                 LDREQ           R1, [R4,#4]
ROM:00332D68                 EOREQ           R1, R1, R0
ROM:00332D6C                 MOVEQ           R6, #1
ROM:00332D70                 STREQ           R6, [R7,#4]
ROM:00332D74                 B               loc_332DEC
ROM:00332D78 ; ---------------------------------------------------------------------------
ROM:00332D78
ROM:00332D78 key_part3
ROM:00332D78                 LDR             R6, [R7]
ROM:00332D7C                 CMP             R6, #1
ROM:00332D80                 LDREQ           R6, [R7,#4]
ROM:00332D84                 CMPEQ           R6, #1
ROM:00332D88                 LDREQ           R2, [R4,#8]
ROM:00332D8C                 EOREQ           R2, R2, R1
ROM:00332D90                 MOVEQ           R6, #1
ROM:00332D94                 STREQ           R6, [R7,#8]
ROM:00332D98                 B               loc_332DEC
ROM:00332D9C ; ---------------------------------------------------------------------------
ROM:00332D9C
ROM:00332D9C key_part4
ROM:00332D9C                 LDR             R6, [R7]
ROM:00332DA0                 CMP             R6, #1
ROM:00332DA4                 LDREQ           R6, [R7,#4]
ROM:00332DA8                 CMPEQ           R6, #1
ROM:00332DAC                 LDREQ           R6, [R7,#8]
ROM:00332DB0                 CMPEQ           R6, #1
ROM:00332DB4                 LDREQ           R3, [R4,#0xC]
ROM:00332DB8                 EOREQ           R3, R3, R2
ROM:00332DBC                 MOVEQ           R6, #1
ROM:00332DC0                 STREQ           R6, [R7,#8]
ROM:00332DC4                 LDR             R4, =0x35A036 ; "Key Generated: %s%s%s%s"
ROM:00332DC8                 BLX             loc_332DDC
ROM:00332DCC                 MOV             R1, SP
ROM:00332DD0                 LDR             R4, =0x35A05C ; "SP: %x"
ROM:00332DD4                 BLX             loc_332DDC
ROM:00332DD8                 CODE16
ROM:00332DD8
ROM:00332DD8 loc_332DD8                              ; CODE XREF: generate_key+2Ej
ROM:00332DD8                 LDR             R4, =0x35A020 ; "key not generated"
ROM:00332DDA                 NOP
ROM:00332DDC
ROM:00332DDC loc_332DDC                              ; CODE XREF: generate_key+C8p
ROM:00332DDC                                         ; generate_key+D4p
ROM:00332DDC                 SUB             SP, SP, #4
ROM:00332DDE                 STR             R0, [SP,#0x28+var_28]
ROM:00332DE0                 MOVS            R0, R4
ROM:00332DE2                 LDR             R4, =0x68B08D
ROM:00332DE4                 BLX             R4
ROM:00332DE6                 ADD             SP, SP, #4
ROM:00332DE8                 BLX             loc_332DEC
ROM:00332DE8 ; End of function generate_key
ROM:00332DE8
ROM:00332DEC                 CODE32
ROM:00332DEC
ROM:00332DEC loc_332DEC                              ; CODE XREF: generate_key+58p
ROM:00332DEC                                         ; generate_key+74j ...
ROM:00332DEC                 ADD             SP, SP, #0x20
ROM:00332DF0                 LDR             LR, [SP],#4
ROM:00332DF4                 BX              LR
ROM:00332DF8
ROM:00332DF8 ; =============== S U B R O U T I N E =======================================
ROM:00332DF8
ROM:00332DF8
ROM:00332DF8 ahex2byte                               ; CODE XREF: generate_key+14p
ROM:00332DF8                 STMFD           SP!, {R4-R6,LR}
ROM:00332DFC                 MOV             R4, R0
ROM:00332E00                 MOV             R6, R0
ROM:00332E04
ROM:00332E04 loc_332E04                              ; CODE XREF: ahex2byte+6Cj
ROM:00332E04                 LDRB            R0, [R4]
ROM:00332E08                 CMP             R0, #0xD
ROM:00332E0C                 BEQ             loc_332E68
ROM:00332E10                 BL              sub_332E70
ROM:00332E14                 CMN             R0, #1
ROM:00332E18                 BNE             loc_332E2C
ROM:00332E1C                 LDRB            R0, [R4]
ROM:00332E20                 BL              sub_332E98
ROM:00332E24                 CMN             R0, #1
ROM:00332E28                 BEQ             locret_332E6C
ROM:00332E2C
ROM:00332E2C loc_332E2C                              ; CODE XREF: ahex2byte+20j
ROM:00332E2C                 MOV             R5, R0
ROM:00332E30                 LDRB            R0, [R4,#1]
ROM:00332E34                 BL              sub_332E70
ROM:00332E38                 CMN             R0, #1
ROM:00332E3C                 BNE             loc_332E50
ROM:00332E40                 LDRB            R0, [R4,#1]
ROM:00332E44                 BL              sub_332E98
ROM:00332E48                 CMN             R0, #1
ROM:00332E4C                 BEQ             locret_332E6C
ROM:00332E50
ROM:00332E50 loc_332E50                              ; CODE XREF: ahex2byte+44j
ROM:00332E50                 MOV             R5, R5,LSL#4
ROM:00332E54                 ADD             R0, R5, R0
ROM:00332E58                 STRB            R0, [R6]
ROM:00332E5C                 ADD             R4, R4, #2
ROM:00332E60                 ADD             R6, R6, #1
ROM:00332E64                 B               loc_332E04
ROM:00332E68 ; ---------------------------------------------------------------------------
ROM:00332E68
ROM:00332E68 loc_332E68                              ; CODE XREF: ahex2byte+14j
ROM:00332E68                 STRB            R0, [R6]
ROM:00332E6C
ROM:00332E6C locret_332E6C                           ; CODE XREF: ahex2byte+30j
ROM:00332E6C                                         ; ahex2byte+54j
ROM:00332E6C                 LDMFD           SP!, {R4-R6,PC}
ROM:00332E6C ; End of function ahex2byte
ROM:00332E6C
ROM:00332E70
ROM:00332E70 ; =============== S U B R O U T I N E =======================================
ROM:00332E70
ROM:00332E70
ROM:00332E70 sub_332E70                              ; CODE XREF: ahex2byte+18p
ROM:00332E70                                         ; ahex2byte+3Cp
ROM:00332E70                 CMP             R0, #0xD
ROM:00332E74                 BEQ             loc_332E90
ROM:00332E78                 CMP             R0, #0x30
ROM:00332E7C                 BLT             loc_332E90
ROM:00332E80                 CMP             R0, #0x39
ROM:00332E84                 BGT             loc_332E90
ROM:00332E88                 SUB             R0, R0, #0x30
ROM:00332E8C                 B               locret_332E94
ROM:00332E90 ; ---------------------------------------------------------------------------
ROM:00332E90
ROM:00332E90 loc_332E90                              ; CODE XREF: sub_332E70+4j
ROM:00332E90                                         ; sub_332E70+Cj ...
ROM:00332E90                 MVN             R0, #0
ROM:00332E94
ROM:00332E94 locret_332E94                           ; CODE XREF: sub_332E70+1Cj
ROM:00332E94                 BX              LR
ROM:00332E94 ; End of function sub_332E70
ROM:00332E94
ROM:00332E98
ROM:00332E98 ; =============== S U B R O U T I N E =======================================
ROM:00332E98
ROM:00332E98
ROM:00332E98 sub_332E98                              ; CODE XREF: ahex2byte+28p
ROM:00332E98                                         ; ahex2byte+4Cp
ROM:00332E98                 CMP             R0, #0x41
ROM:00332E9C                 BLT             loc_332EB4
ROM:00332EA0                 CMP             R0, #0x46
ROM:00332EA4                 BGT             loc_332EB4
ROM:00332EA8                 SUB             R0, R0, #0x41
ROM:00332EAC                 ADD             R0, R0, #0xA
ROM:00332EB0                 B               locret_332EB8
ROM:00332EB4 ; ---------------------------------------------------------------------------
ROM:00332EB4
ROM:00332EB4 loc_332EB4                              ; CODE XREF: sub_332E98+4j
ROM:00332EB4                                         ; sub_332E98+Cj
ROM:00332EB4                 MVN             R0, #0
ROM:00332EB8
ROM:00332EB8 locret_332EB8                           ; CODE XREF: sub_332E98+18j
ROM:00332EB8                 BX              LR
ROM:00332EB8 ; End of function sub_332E98
ROM:00332EB8
ROM:00332EB8 ; ---------------------------------------------------------------------------
ROM:00332EBC dword_332EBC    DCD 0x6213600           ; DATA XREF: generate_key+Ar
ROM:00332EC0 dword_332EC0    DCD 0x6213600           ; DATA XREF: generate_key+18r
ROM:00332EC4 dword_332EC4    DCD 0x35A036            ; DATA XREF: generate_key+C4r
ROM:00332EC8 dword_332EC8    DCD 0x35A05C            ; DATA XREF: generate_key+D0r
ROM:00332ECC dword_332ECC    DCD 0x35A020            ; DATA XREF: generate_key:loc_332DD8r
ROM:00332ED0 off_332ED0      DCD 0x68B08D            ; DATA XREF: generate_key+E2r
ROM:00332ED4                 DCB 0, 0, 0, 0
ROM:00332ED4 ; ROM           ends
ROM:00332ED4
ROM:00332ED4                 END
Серьезно? ASM?Дабы сделать эту статью более понятной широкому кругу лиц, наверное стоит дать понять что же это за дамп из IDA Pro. Опишем все до мелочей :)В этом code-box приведены первые 20 строк из level_2.html файла:
01. ROM:00332D00
02. ROM:00332D00 ; Segment type: Pure code
03. ROM:00332D00                 AREA ROM, CODE, READWRITE, ALIGN=0
04. ROM:00332D00                 ; ORG 0x332D00
05. ROM:00332D00                 CODE16
06. ROM:00332D00
07. ROM:00332D00 ; =============== S U B R O U T I N E =======================================
08. ROM:00332D00
09. ROM:00332D00 ; prototype: generate_key(key_part_num, integrity_validate_table, key_table)
10. ROM:00332D00 ; Function called when serial console input is 'R'. Generates key parts in R0-R3.
11. ROM:00332D00 ; The next level to reach, the key parts to print you must!
12. ROM:00332D00
13. ROM:00332D00 generate_key
14. ROM:00332D00
15. ROM:00332D00 var_28          = -0x28
16. ROM:00332D00
17. ROM:00332D00                 PUSH            {R4-R7,LR}
18. ROM:00332D02                 SUB             SP, SP, #0x10
19. ROM:00332D04                 MOVS            R7, R1
20. ROM:00332D06                 MOVS            R4, R2
...
Колонка слева с ROM:XXXXXXXX - это адреса памяти. При загрузке бинарника в IDA Pro, мы должны препроверить, правильно ли IDA Pro поняла для какой архитектуры (ARM, x86, MIPS и тд. Их, ну прям очень большое количество) собран наш бинарник (в большинстве случаев, автоопределение работает очень хорошо, но если мы вгружаем не бинарник, а целый дамп памяти - некоторые вещи могут распознатся некорректно), считываем файл байт за байтом, и эта левая колонка автоинкрементируется каждый раз когда IDA Pro понимает что это за кусок данных. Данные в бинарнике могут быть поняты одним из следующих образов:
  • Данные. Самый низкий уровень понимания логики. Это когда кусок данных не представляет собой ничего конкретного. В дампе отображается как DCD, DCW, DCB - doubleword, word, byte соответственно (эти типы данных могут быть разных размеров на разных системах. Здесь советую погуглить и почитать. Сам это не сильно шарю). На такие штуки обычно есть ссылки из других участков кода. Назначение может быть самое разное. Далее будет понятно.
  • Код. Это когда кусок данных представляет собой 1 атомарную единицу операции (записать данные из регистра в память, сравнить числа и тд).
  • Строка. Это когда IDA Pro натыкается на массив данных которые лежат в ASCII диапазоне. От 0x20 до 0x7E (ASCII стандарт также описывает числа ниже 0x20, но они не имеют "текстового" смысла). Вполне возможно, что диапазон расширяется и на другие кодировки, но это вне контекста данной статьи.
  • Подпроцедура (Subroutine). Это самый высокий уровень понимания ассемблерной логики - когда IDA Pro видит функцию. Дальше мы видим то же самое, как если бы видели код. Но понимание того, что это не просто код, а функция дает невероятный скачок в осознании происходящего.
На 5й строке мы видим надпись CODE16. Это очень важно, поскольку этот дамп снят с кода для ARM процессоров (IC от LSI, который есть на плате от жесткого диска построен именно на этой архитектуре). У ARM процессоров есть 2 режима работы - ARM и Thumb.
  • В режиме ARM у нас есть доступ, наверное, ко всем ассемблерным операциям, но такие инструкции занимают 4 байта
  • В режиме Thumb мы немножко ограничены, но такие инструкции занимают 2 байта.
Причины по которым были созданы эти 2 режима мне неизвестны (знатоки в комментариях очень даже приветствуются), но могу сказать следующее.
  • В режиме ARM мы, скорее всего, будем исполнять желаемую логику быстрее. Как минимум потому что у нас есть доступ к инструкциям типа CMPEQ, которая выполнит операцию сравнения чисел только в том случае, когда результат предыдущго сравнения был успешным. Получается, что в этом режиме мы можем отдать логику if-else на железо. И сделать 2 операции (проверка предыдущего результата и выполнение новой операции) за 1 цикл процессора. Но и размер инструкций будет больше, а значит нужно использовать больше памяти.
  • В режиме Thumb мы не можем использовать подобное, но размер инструкций будет в 2 раза меньше, а значит затраты памяти будут ниже.
  • Еще стоит сказать, что архитектура ARM (не путать с режимом) прекрасна тем, что размер инструкций у них фиксирован (2 или 4 байта), чего нельзя сказать об x86
В общем, вот это CODE16 значит что в этом моменте процессор находится в Thumb режиме. И, как мы видим дальше, адреса памяти инкрементируются по 2 (конечно, там, где есть инструкция).На строках 9-11 мы видим нарошно оставленные комментарии. Они говорят нам, что этот код исполняется тогда, когда мы вводим в серийник диска букву R и что-то после нее. Также, мы видим, что суть задачи - зарулить исполнение код таким образом, чтоб диск отдал нам части ключей. Совмещая эти ключи, мы получаем пароль от level_3.lod.7z.encrypted.Строка 13 являет собой адрес, на который есть отсылки в коде. Дело в том, что программы на ассемблере не исполняются линейно. Инструкции типа B, BL, BX, BLX переводят исполнение кода по новому адресу. И когда IDA Pro видит такие инструкции, она автоматически дает имя этому адресу. В нашем случае, ребята из RedBalloonSecurity переименовали этот адрес в generate_key. Переименовывать позиции в коде, на который есть ссылки является прекрасным способом оставить для себя заметку о том, что делает определенный кусок кода.На строке 15 мы видим переменную. Надеюсь, все помнят об области видимости в С? Реализация этого механизма на уровне ассемблера очень хитрая. Здесь используется структура данных типа стек.Ëмае, вот к чему stack в stackoverflowУ каждого процессора, помимо кэша, есть встроенное хранилище временных данных - регистры. Это самая быстрая память компьютера, как такового. Все операции с регистрами выполняются невероятно быстро. А поэтому, программу нужно строить таким образом чтоб минимизировать обращения к памяти, и почаще использовать регистры.У ARM процессоров 15 регистров. Для большинства, можно писать код и использовать их как хочешь (хотя внутри компилятора все же есть определенные правила о том, какой регистр для чего использовать). Они имеют имена вида R0, R1 ... R15. Последние имеют специальное назначение:
  • SP (R13) - Stack Pointer. В этом регистре хранится адрес вершины стека
  • BP (R7 в Thumb, R11 в ARM) - Base Pointer. Здесь находится адрес начала стека
  • LR (R14) - Link Register. Если у бренч (B) инструкции есть приставка L, это значит, что адрес в PC нужно записать в LR (там есть определенная специфика, которую я не совсем понимаю. К этому адресу в LR должно добавлятся +2 байта для Thumb, или +4 байта для ARM. Но, это не точно). Потом это используется для возврата на предыдущее место в коде, например через BX LR. По сути, это аналог подхода, когда мы сохраняем адрес возврата на стек, но здесь используем регистр. Из преисуществ - он быстрее и часть програмной логики падает на CPU без хождения по памяти. Недостаток - регистр всего один, и предыдущие адреса возврата все же прийдется складывать на стек.
  • PC (R15) - Program Counter. Здесь находится адрес инструкции, которую процессор выполняет в данный момент. Писать сюда напрямую, кажись, нельзя. Но этот регистр полезен если мы хотим сделать прыжок на другой адрес. Даже если мы работаем с 16-битной архитектурой, мы, ну никак не можем сказать процессору прыгнуть на 16-битный адрес имея 2 байта на 1 инструкцию. Большинство инструкций для прыжка используют именно сдвиг от того, что находится в PC.
  • CSPR - Current State Process Register. Это специфический регистр. К нему нельзя обратится целиком, как и записать сюда что-то. Данные внутри этого регистра формируются автоматически на основе того, какие инструкции выполняет процессор. Он разбит на сегменты, и хранит в себе информацию о текущем состоянии процессора. К примеру, если мы делаем инструкцию CMP (сравнить числа), результат сравнения (0 или 1) пишется в один из битов этого регистра. А в дальнейшем это используется для условных операций.
Стек это определенное место в памяти, где хранятся значения локальных переменных, аргументы функций, адреса возвратов, а также предыдущее значение BP. Стек логически разбит на сегменты (stack frames). Каждый сегмент принадлежит какой-то определенной функции. И, когда мы вызываем из одной функции другую, мы по сути, сдвигаем адреса BP & SP чуть ниже(!) в памяти. Но перед тем как создавать новый сегмент на стеке, мы должны знать адрес, куда должен вернутся PC после завершения функции - он сохраняется на стеке (Return Address) перед вызовом функции. Также, чтоб при возврате, сегмент стека стал того же размера что и был, мы сохраняем предыдущее значение BP (Saved %ebp) на этот же стек. Выглядит все это дело примерно так (%ebp = BP, %esp = SP):
В предыдущем абзаце я сказал, что при создании нового сегмента стека, адреса BP & SP смещаются ниже. Дело в том, что "так сложилось исторически". Стек это FIFO конструкция, которая меняется в процессе исполнения программы. И компилятор не знает какого размера он может быть. То же самое касается кучи (heap) - памяти, которую мы запрашиваем у системы через семейство вызовов malloc (glibc). При выделении памяти в куче, ее адреса растут вверх, а вот когда растет стек, его адреса растут вниз. Стоит оговорится, что мы работаем с embeded устройством. Понятия кучи здесь, может и не быть (опять же, прошу экспертов меня поправить).
У ARM процессоров есть специальные семейство инструкций, которые работают со стеком: PUSH, POP, STMFD, LDMFD (уверен, есть еще, но для наших делишек этого хватит).
  • PUSH кладет то, что в аргументе на стек, и увеличивает стек (на самом деле уменьшает адрес)
  • POP снимает со стека данные и кладет в то, что в аргументе (зачастую регистр, но может быть и адрес памяти) и уменьшает стек (на самом деле увеличивает адрес)
  • STMFD, LDMFD делают то же самое, но туда можно запихнуть несколько регистров, и снять со стека несколько значений в рамках одной инструкции. И, кажись, указать, стоит ли подстраивать SP в зависимости от количества впихнутых регистров. Опять же, прелести ARM архитектуры!
Готовы? Ныряем!Для того, чтоб что-то правильно сломать, нужно это правильно понять. Начнем с первого куска.
...
13. ROM:00332D00 generate_key
14. ROM:00332D00
15. ROM:00332D00 var_28          = -0x28
16. ROM:00332D00
17. ROM:00332D00                 PUSH            {R4-R7,LR}
18. ROM:00332D02                 SUB             SP, SP, #0x10
19. ROM:00332D04                 MOVS            R7, R1
20. ROM:00332D06                 MOVS            R4, R2
21. ROM:00332D08                 MOVS            R5, R0
22. ROM:00332D0A                 LDR             R1, =0x6213600 ; "R"...
23. ROM:00332D0C                 LDRB            R0, [R1,#1]
24. ROM:00332D0E                 CMP             R0, #0x31
25. ROM:00332D10                 BNE             loc_332D1A
26. ROM:00332D12                 ADDS            R0, R1, #2
27. ROM:00332D14                 BLX             ahex2byte
...
Строка 17-21. Первая инструкция, это PUSH. Она сохраняет на стек переменные из регистров R4-R7 и LR на стек, тоесть сохраняет предыдущий stack frame. Потом, отнимаем 16 байт от SP (увеличиваем стек). Копируем из регистров R0-R2 аргументы, которые были переданы в функцию generate_key в их "рабочие" места. Как видим, в прототипе было 3 аргумента. Регистров столко же. В предыдущем разделе я говорил, что аргументы падают на стек - это правда только в том случае, когда аргументов больше, чем 3 (или 4, уже не помню).Процедура в предыдущем абзаце называется Function Prologue. Тоесть, не происходит ничего, что касается программной логики, но выполняется подготовка стека и регистров. Мне кажется, именно по подобным шаблонам IDA Pro отличает код от подпроцедур.Строка 22-23. Грузим адрес, который будет указывать на то, что мы вводим в консольник диска в R1. Инструкция LDRB R0, [R1,#1]берет то, что лежит в R1, добавляет единицу, лезет в память по этому адресу (если значение в квадратных скобках, сначала надо интерпретировать эти данные как адрес), берет 1 байт и сохраняет его в R0.Строка 24-25. Идет сравнение 2го вводимого символа с 0x31. В ASCII 0x31 это "1". Если мы ввели после буквы R единичку, выполнение кода не пойдет на loc_332D1A. Позже разберем что это за место.Строка 26-27. Добавляем к адресу наших вводимых данных двойку и сохраняем в R0. По сути, мы смещаем адрес на 2 байта вперед. Тоесть, теперь он указывает на первый символ после R1 - "R1_" (на underscore). Далее, нас ждет безусловный прыжок на функцию ahex2byte. Но, это не просто прыжок. BLX, кроме прыжка, делает еще 2 замечательные вещи - сохраняет текущий адрес PC в LR, и переключает нас в ARM режим! внутри функции ahex2byte у нас теперь 4 байта на инструкцию. Помним, что R0 является первым аргументом при вызове функции.Дабы подитожить, вот то, как пердыдущий кусок выглядел бы в С-шном виде. Этот код не правильный. Он чисто для наглядности:
void main () {
  char *input = "R10000";
  if (input[1] == "1") {
    &input = &input + 2;
    ahex2byte(&input);
  }
  else {
    goto: loc_332D1A;
  }
}
ахекс2байт
138. ROM:00332DF8 ; =============== S U B R O U T I N E =======================================
139. ROM:00332DF8
140. ROM:00332DF8
141. ROM:00332DF8 ahex2byte                               ; CODE XREF: generate_key+14p
142. ROM:00332DF8                 STMFD           SP!, {R4-R6,LR}
143. ROM:00332DFC                 MOV             R4, R0
144. ROM:00332E00                 MOV             R6, R0
145. ROM:00332E04
146. ROM:00332E04 loc_332E04                              ; CODE XREF: ahex2byte+6Cj
147. ROM:00332E04                 LDRB            R0, [R4]
148. ROM:00332E08                 CMP             R0, #0xD
149. ROM:00332E0C                 BEQ             loc_332E68
150. ROM:00332E10                 BL              sub_332E70
151. ROM:00332E14                 CMN             R0, #1
152. ROM:00332E18                 BNE             loc_332E2C
153. ROM:00332E1C                 LDRB            R0, [R4]
154. ROM:00332E20                 BL              sub_332E98
155. ROM:00332E24                 CMN             R0, #1
156. ROM:00332E28                 BEQ             locret_332E6C
157. ROM:00332E2C
158. ROM:00332E2C loc_332E2C                              ; CODE XREF: ahex2byte+20j
159. ROM:00332E2C                 MOV             R5, R0
160. ROM:00332E30                 LDRB            R0, [R4,#1]
161. ROM:00332E34                 BL              sub_332E70
162. ROM:00332E38                 CMN             R0, #1
163. ROM:00332E3C                 BNE             loc_332E50
164. ROM:00332E40                 LDRB            R0, [R4,#1]
165. ROM:00332E44                 BL              sub_332E98
166. ROM:00332E48                 CMN             R0, #1
167. ROM:00332E4C                 BEQ             locret_332E6C
168. ROM:00332E50
169. ROM:00332E50 loc_332E50                              ; CODE XREF: ahex2byte+44j
170. ROM:00332E50                 MOV             R5, R5,LSL#4
171. ROM:00332E54                 ADD             R0, R5, R0
172. ROM:00332E58                 STRB            R0, [R6]
173. ROM:00332E5C                 ADD             R4, R4, #2
174. ROM:00332E60                 ADD             R6, R6, #1
175. ROM:00332E64                 B               loc_332E04
176. ROM:00332E68 ; ---------------------------------------------------------------------------
177. ROM:00332E68
178. ROM:00332E68 loc_332E68                              ; CODE XREF: ahex2byte+14j
179. ROM:00332E68                 STRB            R0, [R6]
180. ROM:00332E6C
181. ROM:00332E6C locret_332E6C                           ; CODE XREF: ahex2byte+30j
182. ROM:00332E6C                                         ; ahex2byte+54j
183. ROM:00332E6C                 LDMFD           SP!, {R4-R6,PC}
184. ROM:00332E6C ; End of function ahex2byte
185. ROM:00332E6C
186. ROM:00332E70
187. ROM:00332E70 ; =============== S U B R O U T I N E =======================================
188. ROM:00332E70
189. ROM:00332E70
190. ROM:00332E70 sub_332E70                              ; CODE XREF: ahex2byte+18p
191. ROM:00332E70                                         ; ahex2byte+3Cp
192. ROM:00332E70                 CMP             R0, #0xD
193. ROM:00332E74                 BEQ             loc_332E90
194. ROM:00332E78                 CMP             R0, #0x30
195. ROM:00332E7C                 BLT             loc_332E90
196. ROM:00332E80                 CMP             R0, #0x39
197. ROM:00332E84                 BGT             loc_332E90
198. ROM:00332E88                 SUB             R0, R0, #0x30
199. ROM:00332E8C                 B               locret_332E94
200. ROM:00332E90 ; ---------------------------------------------------------------------------
201. ROM:00332E90
202. ROM:00332E90 loc_332E90                              ; CODE XREF: sub_332E70+4j
203. ROM:00332E90                                         ; sub_332E70+Cj ...
204. ROM:00332E90                 MVN             R0, #0
205. ROM:00332E94
206. ROM:00332E94 locret_332E94                           ; CODE XREF: sub_332E70+1Cj
207. ROM:00332E94                 BX              LR
208. ROM:00332E94 ; End of function sub_332E70
209. ROM:00332E94
210. ROM:00332E98
211. ROM:00332E98 ; =============== S U B R O U T I N E =======================================
212. ROM:00332E98
213. ROM:00332E98
214. ROM:00332E98 sub_332E98                              ; CODE XREF: ahex2byte+28p
215. ROM:00332E98                                         ; ahex2byte+4Cp
216. ROM:00332E98                 CMP             R0, #0x41
217. ROM:00332E9C                 BLT             loc_332EB4
218. ROM:00332EA0                 CMP             R0, #0x46
219. ROM:00332EA4                 BGT             loc_332EB4
220. ROM:00332EA8                 SUB             R0, R0, #0x41
221. ROM:00332EAC                 ADD             R0, R0, #0xA
222. ROM:00332EB0                 B               locret_332EB8
223. ROM:00332EB4 ; ---------------------------------------------------------------------------
224. ROM:00332EB4
225. ROM:00332EB4 loc_332EB4                              ; CODE XREF: sub_332E98+4j
226. ROM:00332EB4                                         ; sub_332E98+Cj
227. ROM:00332EB4                 MVN             R0, #0
228. ROM:00332EB8
229. ROM:00332EB8 locret_332EB8                           ; CODE XREF: sub_332E98+18j
230. ROM:00332EB8                 BX              LR
231. ROM:00332EB8 ; End of function sub_332E98
Строка
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_assembler, #_reversinzhiniring (Реверс-инжиниринг), #_hranenie_dannyh (Хранение данных), #_ctf, #_red_balloon_security, #_soiskatel (соискатель), #_rabota (работа), #_shifr (шифр), #_informatsionnaja_bezopasnost (
Информационная безопасность
)
, #_assembler, #_reversinzhiniring (
Реверс-инжиниринг
)
, #_hranenie_dannyh (
Хранение данных
)
, #_ctf
Профиль  ЛС 
Показать сообщения:     

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

Текущее время: 30-Июн 12:24
Часовой пояс: UTC + 5