Оригинал: megabeets.net
Пролог
Я очень много игрался с radare2 в прошлом году, с тех пор я начал участвовать в CTF, и стал глубоко погружаться в квесты по реверсу и эксплуатации уязвимостей. Я нашел radare2 очень полезным во многих СTF-тасках, мои решения благодаря нему стали намного короче. Иногда это мой незаменимый инструмент для решений тасков по исследованию зловредов таких как "сonfiguration retrieval". Печально, но я уверен, что лишь немного людей знакомы с radare2. Возможно, это вызвано тем, что они боятся выйти из зоны комфорта (IDA Pro, OllyDBG, gdb) или попросту не слышали про это. Так или иначе, я в правда верю, что вы добавите radare2 в свой инструментарий.
Потому что я реально очень очень верю в этот проект и хочу, чтобы все больше и больше исследователей были с ним знакомы, использовали его и, надеюсь, делали вклад в его развитие. Я решил сделать серию статей и примеров использования r2. Эти статьи нацелены научить вас основам radare2, его фишкам и возможностям, я объясню вам намного больше, чем вы должны знать для решения любого таска.
Добро пожаловать в IDA 10.0 (см. radare2/doc/fortunes.fun)
radare2
radare2 — опенсурсный фреймворк для реверсинга и анализа бинарников, реализованный в виде богатого консольного интерфейса для дизассемблирования, анализа данных, патчинга бинарников, сравнанения данных, поиска, перестановки, визуалиции и другое. У него есть возможность скриптинга, а также он работает на всех платформах (GNU/Linux, .Windows *BSD, iOS, OSX, Solaris…) и поддерживает тонну архитектур и форматов файлов. Но может быть важнее всех его фич идеология, на котором он стоит, radare2 абсолютно свободен.
Этот фреймворк состоит из набора утилит, который могут быть использованы или вместе из r2, или же отдельно. Мы познакомимся с такими утилитами как rahash2, rabin2, ragg2. Вместе они создают один из самых мощных инструментов в области статического и динамического анализа, редактирования hex и эксплуатации (я углублюсь в последующих статьях об этом).
Это важно отметить, что кривая обучения r2 попросту крутая, хотя r2 имеет оконный и веб-интерфейс, ни одного из них недостаточно, чтобы конкурировать с графическим интерфейсом или удобством IDA, имхо. Интерфейс командной строки, включая его визуальный режим, по-прежнему является ядром radare2, и местом где находится вся его мощь. Из-за его сложности я постараюсь объяснить все как можно яснее и проще.
Это более или менее как кривая обучения r2 работает
Перед тем, как мы начнем, вы можете ознакомиться с “Unfair comparison between r2, IDA Pro and Hopper” (Беспристрастное сравнение r2, IDA, Hopper), для того чтобы понимать с чем мы имеем дело.
Getting radare2
Установка
Разработка radare2 ведется достаточно быстро, проект улучшается каждый день, так что очень рекомендуется использовать текущую версию с гита вместо стабильной версии. Иногда стабильная версия менее стабильна, чем текущая версия в гите.
Если вы не хотите устанавливать гит версию или хотите бинарники для других систем (Windows, OS X, iOS, etc), зайдите на страницу загрузки с сайта radare2.Code:$ git clone https://github.com/radare/radare2.git $ cd radare2 $ ./sys/install.sh
Обновление
Как я говорил ранее, очень рекомендуется всегда использовать самую свежую версию r2 из репозитория. Все что вам нужно, чтобы обновить вашу версию r2 из гита, это просто выполнить следующую команду:
И у вас будет свежая версия из гита. Я обычно обновляю свою версию radare2 утром, в то время как смотрю видосики с котиками.Code:$ ./sys/install.sh
Деинсталляция
Я не могу придумать причину, зачем вам удалять radare2 так рано в этой статье, но если вы хотите это сделать, вам всего лишь надо выполнить следующее:
Getting StartedCode:$ make uninstall $ make purge
Вы можете загрузить свой первый челендж тут.
Теперь когда radare2 установлен на вашей системе, и вы загрузили бинарник, мы готовы начать исследовать основы использования radare2. Я буду работать на Remnux, но большинство команд и объяснений (если не все они) будут теми же самыми, что и для Windows и остальных систем.
Аргументы командной строки
Как и в большинстве консольных утилит лучший способ выяснить список доступных аргументов -- выполнить программу с флагом -h.
Я не буду тут постить полный выхлоп программы, вместо этого я лишь укажу те, которые я обычно использую в своей ежедневной работе:Code:$ r2 -h
Информация о бинарникеUsage: r2 [-ACdfLMnNqStuvwz] [-P patch] [-p prj] [-a arch] [-b bits] [-i file]
[-s addr] [-B baddr] [-M maddr] [-c cmd] [-e k=v] file|pid|-|--|=
-d: Debug the executable 'file' or running process 'pid'
-A: Analyze executable at load time (xrefs, etc)
-q: Quiet mode, exit after processing commands
-w: Write mode enabled
-L: List of supported IO plugins
-i [file]: Interprets a r2 script
-n: Bare load. Do not load executable info as the entrypoint
-c 'command; command; ...': Run r2 and execute commands (eg: r2 's main; px 60')
-p [prj]: Creates a project for the file being analyzed
-: Opens r2 with the malloc plugin that gives a 512 bytes memory area to play with
Каждый раз когда я встречаюсь с новым челленджем, я хочу, во-первых, получить информацию о бинарнике. Давайте извлечем ее, используя один из самых мощных инструментов в r2 фреймворке: rabin2.
Мы вызываем rabin2 с флагом -I, который выводит информацию о бинарнике такую как операционная система, язык, порядок байтов, архитектура, mitigations (canary, pic, nx) и другое.rabin2 позволяет извлекать информацию из бинарных файлов, влючая секции, заголовки, импорт, строки, энтрипоинты, и так далее. Он может извлечь эту информацию в нескольких форматах. rabin2 способен воспринимать множетсво форматов файлов такие как ELF, PE, Mach-O, Java CLASS.
Для подробной информации воспользуйтесь man rabin2
Code:rabin2 -I megabeets_0x1Как вы четко видите, наш бинарник - 32 битный ELF файл, с включенной дебаг информацией, динамически слинкован. У его нет никаких доступных техник митингации, полезная информация об этом будет в следующих статьях, когда мы научимся эксплоитить с помощью radare2.havecode true
pic false
canary false
nx false
crypto false
va true
intrp /lib/ld-linux.so.2
bintype elf
class ELF32
lang c
arch x86
bits 32
machine Intel 80386
os linux
minopsz 1
maxopsz 16
pcalign 0
subsys linux
endian little
stripped false
static false
linenum true
lsyms true
relocs true
rpath NONE
binsz 6220
Давайте теперь запустим программу и посмотрим, что она может.
Заметьте: Хотя я обещаю, что вы можете верить мне, запуская крекми, однако очень рекомендуется не верить мне. Всегда когда вы реверсите незнакомый бинарник, пожалуйста, делайте это внутри виртуального окружения, где ничего не может быть повреждено.
Но вы можете мне верить все-таки, даю вам свое dword!
Code:$ ./megabeets_0x1.:: Megabeets ::.
Think you can make it?
Nop, Wrong argument.Code:$ ./megabeets_0x1 abcdefВ первый раз как мы запускаем программу, мы получаем от нее сообщение, сообщающее "Не, неверный аргумент". Предположим, что нам необходимо воспользоваться аргументом "abcdef" для программы. Мы ошиблись снова. Очевидно нам нужен некоторый пароль, чтобы решить эту крекми..:: Megabeets ::.
Think you can make it?
Nop, Wrong argument.
Давайте исследуем эту программу, используя radare2:
Code:$ r2 ./megabeets_0x1Мы заспавнили radare2 консоль, и она автоматически нас приветствует с одним из ее приколов. Некоторые из них очень смешны, другие очень полезны, вы можете использнить команду fo, чтобы r2 напечатал вам еще одну. Теперь консоль r2 ждет ваших команд и показывает адрес, где вы сейчас находитесь (0x08048370). По-умолчанию вы автоматически будете на адресе точки входа. Давайте проверим так ли это:— Thank you for using radare2. Have a nice night!
[0x08048370]>
Code:[0x08048370]> ieМы использовали ie команду, которая печатает энтрипоинты бинарника. Команды r2 — последовательность значимых букв. В данном примере ie расшифровывается как info>>entrypoint. Таким образом команды очень легко запомнить, когда вы знакомы с возможностями radare2. Но вам не нужно запоминать все команды — достаточно просто добавить ? после (почти) всех буквы, чтобы получить информацию о команде и ее субкомандах.[Entrypoints]
vaddr=0x08048370 paddr=0x00000370 baddr=0x08048000 laddr=0x00000000 haddr=0x00000018 type=program1 entrypoints
Code:[0x08048370]> i?Команда i нацелена на получение информации из открытого файла, это тот же rabin2 (упомянутый ранее), реализованный в консоле radare2.|Usage: i Get info from opened file (see rabin2’s manpage)
| Output mode:
| ‘*’ Output in radare commands
| ‘j’ Output in json
| ‘q’ Simple quiet output
| Actions:
| i|ij Show info of current file (in JSON)
| iA List archs
| ia Show all info (imports, exports, sections..)
| ib Reload the current buffer for setting of the bin (use once only)
| ic List classes, methods and fields
| iC Show signature info (entitlements, …)
| id Debug information (source lines)
| iD lang sym demangle symbolname for given language
| ie Entrypoint
| iE Exports (global symbols)
| ih Headers (alias for iH)
| iHH Verbose Headers in raw text
| ii Imports
| iI Binary info
| ik [query] Key-value database from RBinObject
| il Libraries
| iL List all RBin plugins loaded
| im Show info about predefined memory allocation
| iM Show main address
| io [file] Load info from file (or last opened) use bin.baddr
| ir|iR Relocs
| is Symbols
| iS [entropy,sha1] Sections (choose which hash algorithm to use)
| iV Display file version info
| iz Strings in data sections
| izz Search for Strings in the whole binary
| iZ Guess size of binary program
Анализ
radare2 не анализирует файл по-умолчанию, потому что анализ — комплексный процесс, который требует длительного времени, особенно если вы имеете дело с большими файлами. Чтобы прочитать больше об анализе и причине выбора не выполнять анализ при запуске программы, вы можете прочесть этот пост в блоге radare2.
Очевидно анализ все еще можно выполнить и r2 имеет много типов функций анализа. Как я заметил раньше, мы можем исследовать функции анализа, добавляя ? к команде a.
Code:[0x08048370]> a?Я обычно начинаю работу, исполняя команду aa (analyse all). Имя данной команды может ввести в заблуждение, поскольку существует множество еще возможностей для анализа (проверьте команду aa?, но этого достаточно для большинства бинарников, которые я рассматривал. В этот раз мы начнем нашу работу прям с команды aaa, чтобы все сделать проще в связи с маленьким размером файла. Вы также можете запускать radare 2 с флагом -A, чтобы анализировать бинарник сразу же при запуске, используя aaa команду (например, r2 -A megabeets_0x1).|Usage: a[abdefFghoprxstc] […]
| ab [hexpairs] analyze bytes
| abb [len] analyze N basic blocks in [len] (section.size by default)
| aa[?] analyze all (fcns + bbs) (aa0 to avoid sub renaming)
| ac[?] [cycles] analyze which op could be executed in [cycles]
| ad[?] analyze data trampoline (wip)
| ad [from] [to] analyze data pointers to (from-to)
| ae[?] [expr] analyze opcode eval expression (see ao)
| af[?] analyze Functions
| aF same as above, but using anal.depth=1
| ag[?] [options] output Graphviz code
| ah[?] analysis hints (force opcode size, …)
| ai [addr] address information (show perms, stack, heap, …)
| ao[?] [len] analyze Opcodes (or emulate it)
| aO Analyze N instructions in M bytes
| ar[?] like ‘dr’ but for the esil vm. (registers)
| ap find prelude for current offset
| ax[?] manage refs/xrefs (see also afx?)
| as[?] [num] analyze syscall using dbg.reg
| at[?] [.] analyze execution traces
Examples:
f ts @ S*~text:0[3]; f t @ section..text
f ds @ S*~data:0[3]; f d @ section..data
.ad t t+ts @ d:ds
Code:[0x08048370]> aaaФлаги[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)[*] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
После завершения анализа radare2 ассоциирует имена с интересными смещениями в файле такими как секции, функции, символы, строки, etc. Такие имена называются флагами. Флаги могут быть сгруппированы в пространства флагов.Пространство флагов — пространство для флагов со схожими характеристиками или типами. Список пространств флагов можно вывести с помощью команды ‘fs’.
Code:[0x08048370]> fsМы можем выбрать пространство флагов, используя команду 'fs <flagspace>’ и далее вывести флаги, содержащиеся в пространстве, используя команду ‘f’. Чтобы выполнить несколько команд в одной строке, мы можем использовать точку с запятой (т.е. ‘cmd1; cmd2; cmd3;...)..0 4 . strings
1 35 . symbols
2 82 . sections
3 5 . relocs
4 5 . imports
5 1 . functions
Code:[0x08048370]> fs imports; fКак мы можем заметить, radare2 пометил импорты, используемые бинарником, мы можем видеть хорошо знакомые strcmp, strcpy, puts, etc вместе с их соответствующими адресами. Мы также можем посмотреть пространство строк:0x08048320 6 sym.imp.strcmp
0x08048330 6 sym.imp.strcpy
0x08048340 6 sym.imp.puts
0xffffffff 16 loc.imp.__gmon_start__
0x08048350 6 sym.imp.__libc_start_main
Code:[0x08048370]> fs strings; fСтроки0x08048700 21 str._n__.::_Megabeets_::.
0x08048715 23 str.Think_you_can_make_it_
0x0804872c 10 str.Success__n
0x08048736 22 str.Nop__Wrong_argument._n
Мы видим, что r2 пометил некоторые смещения как строки, задал некоторый тип названий переменных. Давайте теперь посмотрим на сами строки. Есть множество способов сделать это, и вы должны выбрать способ, который будет отвечать вашей цели наиболее всего.
iz - Посмотреть список строк в data секции.
izz - Найти строки во всем бинарнике
Code:[0x08048370]> izМы уже знаем большинство этих строк, мы их видели, когда запускали наш бинарник, помните? Мы не видели строки “Success”, хотя это наше ‘good boy’ сообщение. Теперь когда у нас есть строки, давайте посмотрим, где они используются в программе.vaddr=0x08048700 paddr=0x00000700 ordinal=000 sz=21 len=20 section=.rodata type=ascii string=\n .:: Megabeets ::.
vaddr=0x08048715 paddr=0x00000715 ordinal=001 sz=23 len=22 section=.rodata type=ascii string=Think you can make it?
vaddr=0x0804872c paddr=0x0000072c ordinal=002 sz=10 len=9 section=.rodata type=ascii string=Success!\n
vaddr=0x08048736 paddr=0x00000736 ordinal=003 sz=22 len=21 section=.rodata type=ascii string=Nop, Wrong argument.\n
Code:[0x08048370]> axt @@ str.*Эта команда раскрывает нам одну из фич radare2. Команда ‘axt’ используется, чтобы “найти данные\код, ссылающиеся на этот адрес” (см. ‘ax?’). А ‘@@’ это как символ форич итератора, используемый чтобы повторять команду над списком смещений (см. ‘@@?’), и ‘str.*’ - это регулярное выражение, означающее для всех флагов, начинающихся со ‘str’. Эта комбинация помогает мне не только получить список флагов типа string, но и также получить список имен функций, где это используются и саму указанную инструкцию. Не забудьте выбрать пространство флагов типа string (по-умолчанию используется ‘fs *’) перед этим.data 0x8048609 push str._n__.::_Megabeets_::. in main
data 0x8048619 push str.Think_you_can_make_it_ in main
data 0x8048646 push str._n_tSuccess__n in main
data 0x8048658 push str._n_tNop__Wrong_argument._n in main
Поиск
Как я упоминал ранее, все это время мы находились на этрипоинте программы, сейчас пора двигаться далее. Строки, которые мы нашли, все ссылаются на ‘main’. Для того, чтобы перейти из смещения в смещение, мы должны воспользоваться командой ‘seek’, представляемой ‘s’ в r2 консоли. Как вы уже знаете, добавляя знаков вопрос к (большинству) всем командам -- ответ на все ваши проблемы.
Code:[0x08048370]> s?По-простому команда ‘seek’ позволяет использовать адрес или математическое выражение в качестве аргумента для поиска. Выражение может быть математической операцией, флагом или же операциями доступа к памяти. Мы хотим найти функцию ‘main’, мы можем сделать это, выполнив команду ‘s main’, но давайте посмотрим сначала, какие другие функции radare2 выделил для нас, используя команду afl (Analyze Functions List).|Usage: s # Seek commands
| s Print current address
| s addr Seek to address
| s- Undo seek
| s- n Seek n bytes backward
| s– Seek blocksize bytes backward
| s+ Redo seek
| s+ n Seek n bytes forward
| s++ Seek blocksize bytes forward
| s[j*=] List undo seek history (JSON, =list, *r2)
| s/ DATA Search for next occurrence of ‘DATA’
| s/x 9091 Search for next occurrence of \x90\x91
| s.hexoff Seek honoring a base from core->offset
| sa [[+-]a] [asz] Seek asz (or bsize) aligned to addr
| sb Seek aligned to bb start
| sC[?] string Seek to comment matching given string
| sf Seek to next function (f->addr+f->size)
| sf function Seek to address of specified function
| sg/sG Seek begin (sg) or end (sG) of section or file
| sl[?] [+-]line Seek to line
| sn/sp Seek next/prev scr.nkey
| so [N] Seek to N next opcode(s)
| sr pc Seek to register
Code:[0x08048370]> aflПрелестно! Здесь импорты, которые мы были раньше, некоторые .ctors, энтропоинты, libc, main и две интересные функции, названные ‘sym.beet’ and ‘sym.rot13;’.0x080482ec 3 35 sym._init
0x08048320 1 6 sym.imp.strcmp
0x08048330 1 6 sym.imp.strcpy
0x08048340 1 6 sym.imp.puts
0x08048350 1 6 sym.imp.__libc_start_main
0x08048360 1 6 sub.__gmon_start___252_360
0x08048370 1 33 entry0
0x080483a0 1 4 sym.__x86.get_pc_thunk.bx
0x080483b0 4 43 sym.deregister_tm_clones
0x080483e0 4 53 sym.register_tm_clones
0x08048420 3 30 sym.__do_global_dtors_aux
0x08048440 4 43 -> 40 sym.frame_dummy
0x0804846b 19 282 sym.rot13
0x08048585 1 112 sym.beet
0x080485f5 5 127 main
0x08048680 4 93 sym.__libc_csu_init
0x080486e0 1 2 sym.__libc_csu_fini
0x080486e4 1 20 sym._fini
Дизассемблирование
main функция
Пришла пора посмотреть немного дизассемблированного кода (ура!). Мы должны для начала найти функцию, используя ‘s main’ и затем дизассемблировать ее, используя ‘pdf’ (Print Disassemble Function). Обратите внимание, как адрес в консоли поменяется на адрес main.
Заметьте: как я сказал ранее, цель нашего туториала научить radare2 и представить часть его возможностей, но не учить дизасму. Таким образом, я не буду проходить глубоко, и объяснять как это работает. Честно, бинарный код -- очень просто, вы нам нужно просто познакомиться с простейшим пониманием реверса.Code:[0x08048370]> s main [0x080485f5]> pdfИз дизассемблированного листинга, мы можем быстро сгенерировать псевдокод:;– main:
/ (fcn) main 127
| main ();
| ; var int local_8h @ ebp-0x8
| ; var int local_4h @ esp+0x4
| ; DATA XREF from 0x08048387 (entry0)
| 0x080485f5 8d4c2404 lea ecx, [esp + local_4h] ; 0x4
| 0x080485f9 83e4f0 and esp, 0xfffffff0
| 0x080485fc ff71fc push dword [ecx – 4]
| 0x080485ff 55 push ebp
| 0x08048600 89e5 mov ebp, esp
| 0x08048602 53 push ebx
| 0x08048603 51 push ecx
| 0x08048604 89cb mov ebx, ecx
| 0x08048606 83ec0c sub esp, 0xc
| 0x08048609 6800870408 push str._n__.::_Megabeets_::. ; str._n__.::_Megabeets_::.
| 0x0804860e e82dfdffff call sym.imp.puts ; int puts(const char *s)
| 0x08048613 83c410 add esp, 0x10
| 0x08048616 83ec0c sub esp, 0xc
| 0x08048619 6815870408 push str.Think_you_can_make_it_ ; “Think you can make it?” @ 0x8048715
| 0x0804861e e81dfdffff call sym.imp.puts ; int puts(const char *s)
| 0x08048623 83c410 add esp, 0x10
| 0x08048626 833b01 cmp dword [ebx], 1 ; [0x1:4]=0x1464c45
| ,=< 0x08048629 7e2a jle 0x8048655
| | 0x0804862b 8b4304 mov eax, dword [ebx + 4] ; [0x4:4]=0x10101
| | 0x0804862e 83c004 add eax, 4
| | 0x08048631 8b00 mov eax, dword [eax]
| | 0x08048633 83ec0c sub esp, 0xc
| | 0x08048636 50 push eax
| | 0x08048637 e849ffffff call sym.beet
| | 0x0804863c 83c410 add esp, 0x10
| | 0x0804863f 85c0 test eax, eax
| ,==< 0x08048641 7412 je 0x8048655
| || 0x08048643 83ec0c sub esp, 0xc
| || 0x08048646 682c870408 push str.Success__n ; “Success!.” @ 0x804872c
| || 0x0804864b e8f0fcffff call sym.imp.puts ; int puts(const char *s)
| || 0x08048650 83c410 add esp, 0x10
| ,===< 0x08048653 eb10 jmp 0x8048665
| ||| ; JMP XREF from 0x08048629 (main)
| ||| ; JMP XREF from 0x08048641 (main)
| |-> 0x08048655 83ec0c sub esp, 0xc
| | 0x08048658 6836870408 push str.Nop__Wrong_argument._n ; “Nop, Wrong argument..” @ 0x8048736
| | 0x0804865d e8defcffff call sym.imp.puts ; int puts(const char *s)
| | 0x08048662 83c410 add esp, 0x10
| | ; JMP XREF from 0x08048653 (main)
| `—> 0x08048665 b800000000 mov eax, 0
| 0x0804866a 8d65f8 lea esp, [ebp – local_8h]
| 0x0804866d 59 pop ecx
| 0x0804866e 5b pop ebx
| 0x0804866f 5d pop ebp
| 0x08048670 8d61fc lea esp, [ecx – 4]
\ 0x08048673 c3 ret
Псевдографический и режим графаCode:if (argc > 1 && beet(argv[1]) == true) # i.e - if any argument passed to the program AND the result of beet, given the passed argument, is true # argc is the number of arguments passed to the program # argc will be at least 1 becuase the first argument is the program name # argv is the array of parameters passed to the program { print "success" } else { print "fail" } exit
radare2 экипирован очень мощным и эффективным набором псевдографических режимов. Псевдографический режим более дружелюбный и позволяет использовать реверсинг в r2 на абсолютно другом уровне. Команда ‘V’ откроет вам окно псевдографического режима. Используйте ‘p/P’ команды для переключения между псевдографическими режимами. На самом верху экрана вы можете увидеть команду, которая сейчас используется для отображения.
Простейшие команды псевдографического интерфейса
Передвижение
Вы можете передвигаться вверх и вниз, используя кнопки ‘k’ и ‘j’ соответственно. Нажимая Enter, где бы ни было на джампе или при вызове функции, вы можете прыгнуть на адрес назначения. Рядом с каждым прыжком или вызовом функции есть число в квадратных скобках, нажимая цифру на своей клавиатуре, вы попадете на нужную адрес/функцию.
Помощь
Как и всегда в radare, нажимая ? вы переместитесь на экран помощи, где вы можете исследовать команды псевдографического режима.
Перекрестные ссылки
Используйте x/X, чтобы отобразить ссылки на/из функции соответственно. Используйте номера, чтобы прыгнуть на адрес ссылки.
radare2 команды
Используйте :command для того, чтобы выполнить r2 внутри псевдографического режима.
Комментирование
Вы можете добавить или удалить коммент, используя команду ‘;comment’ для добавления, ‘;-’ для удаления комментария.
Пометки
m<key> может быть использована для маркировки определенных смещений с ключом на ваш выбор. Нажмите на клавиатуре кнопку ключа, чтобы перейти на смещение.
Выход
Нажмите q для того, чтобы вернуться в r2 консоль.
Режим графов
Как и в простейших дизассемблерах, в radare2 есть свой режим графа. Вы можете получить доступ к ним через консоль, запустив команду VV, передвигаться по графу влево/вниз/вверх/вправо можно используя h/j/k/l, а чтобы прыгнуть на функцию используйте кнопку g и ключ показанный рядом с вызываемым адресом (т.е. gd).
Используйте ?, чтобы вывести все команды and будьте уверены не пропустить R команду (прим. переводчика: это самое важное, правда!).
Дизассемблируем ‘beet’
После короткого прекращения дизассемблирования, давайте вернемся к этому и исследуем функцию beet. Как мы видели ранее, наш бинарник проверяет результат функции beet, которая вызывается с аргументом, который мы передаем программе. Мы можем вывести beet, используя несколько способом, вот некоторые из них:
Вот как функция beet выглядит в псевдо графическом режиме:
- Искать beet в r2 консоли и выводить функцию, используя s sym.beet (sym.beet это флаг для beet функции. Вы можете вывести флаги sym, запустив команду f sym.<tab>) и далее выполнив pdf (print disassembled function).
- Вывести beet из r2 консоли без поиска, используя pdf @sym.beet. Знак @ используется как временный поиск, т.е. “вывести функцию со смещением sym.beet”.
- Прыгнуть в функцию beet из псевдографического интерфейса, используя кнопку 3 в main (номер рядом с вызываемой функцией)
- Прыгнуть в beet из Режима Графов, используя сочетание клавиш типа gd (где d - следующая буква рядом с вызываемой функцией из списка графов)
Мы можем видеть, что полученный аргумент копируется в буфер. Буфер расположен в регистре ebp -- local_88h. А ‘local_88h’ это 0x88, что есть 136 в десятичной системе исчисления. Мы можем увидеть это, запустив команду ? 0x88. Чтобы выполнить команду внутри псевдографического интерфейса, используйте ‘:’, а затем пишите свою команду.
Code::> ? 0x88Таким образом, 128 байт аллоцированы для буфера в стэке, следующие 4 байта будут использоваться для того, чтобы сохранить ссылку на ebp предыдущего стек фрейма, а еще следующие 4 байта будут адресом возврата, итого это суммируется до 136.136
0x88
0210
136
0000:0088
136
“\x88”
10001000
136.0
136.000000f
136.000000
После того как в буфер попадает наш аргумент, он будет сравнен с результатом функции, названной sym.rot13. Rot13 -- известный алгоритм шифротекста путем подстановки, используемый во многих CTF и крекми. Функций вызывается с девяти шестнадцати разрядным значениями, которые radare отказывается распознавать как строку (прим. переводчика: теперь распознает!). Мы можем сделать это вручную, используя команду ahi s прямо на эти адреса.
ahi s используется, чтобы выставить специфические смещения как строки (см. ahi?), @@ это итератор (см. @@?) и адреса используются прямо из функции sym.beet, которые radare2 не распознал как строки. После выполнения команды, интерфейс обновится (если не обновился, используйте кнопку r) и будет выглядеть так:Code::> ahi s @@=0x080485a3 0x080485ad 0x080485b7
Великолепно! Похоже за строкой пряталось слово “Megabeets” (запушенное в обратном порядке в связи с порядком байтов).
Бинарник осуществляет rot13 над строкой “Megabeets” и затем сравнивает результат с аргументом, который мы отправили в программу, используя для этого strcmp. К счастью, нам не нужно напрягаться, потому что r2 фреймворк уже включает rot13 шифр в его rahash2 утилите.
rahash2 считает контрольную сумму файлов, стров, используя различные алгоритмы.
Посмотрите мануал rahash2 для подробной информации.Code::> !rahash2 -E rot -S s:13 -s ‘Megabeets\n’rahash2 осуществила rot13(“Megabeets”) и в результате вывела “Zrtnorrgf”. Использов символ ‘!’, мы можем выполнять команды в консоли системы (прим. переводчика: можно и не писать !, чтобы исполнить команду в командной оболочке). Мы можем заметить, что строка “Zrtnorrgf” сравнивается с нашей вводимой строкой. Давайте откроем бинарник в режиме дебага со строкой “Zrtnorrgf” в качестве аргумента, использовав команду odd (см. ood?) и посмотрим, что будет.Zrtnorrgf
Code:[0xf7749be9]> ood?| ood [args] reopen in debugger mode (with args)Code:[0xf7749be9]> ood ZrtnorrgfWait event received by different pid 7415
Wait event received by different pid 7444
Process with PID 7575 started…
File dbg:///home/remnux/Desktop/tutorials/megabeets_0x1 Zrtnorrgf reopened in read-write mode
= attach 7575 7575
Assuming filepath /home/remnux/Desktop/tutorials/megabeets_0x1
[0xf7749be9]> dc
Selecting and continuing: 7575.:: Megabeets ::.
Think you can make it?
Success!PTRACE_EVENT_EXIT pid=7575, status=0x0
Вууху! Мы получил сообщение об успехе и решили крекми. После получения успешного сообщения мы можем наконец сказать, что наш бинарник делает: он берет первый аргумент, который мы вводим, и сравнивает его с rot13(“Megabeets”), что является “Zrtnorrgf”.
Вы можете увидеть полный исходный код крекми тут.
Эпилог
Первая часть нашего приключения с radare2 подходит к концу. Мы изучили лишь ореховую скорлупу radare2 и исследовали лишь основы основ. В следующих частях мы узнаем больше о возможностях radare2, включая скриптинг, исследование малвари и эксплуатации. Я боюсь, что сначала будет сложно понять всю мощь radare2 или почему вы должны оставить некоторые из своих старых привычек и начать пользоваться radare2, но я обещаю, что имея radare2 в своем инструментарии -- это очень умный шаг не важно являетесь ли вы реверс инженером, игроком CTF или просто энтузиастом в области безопасности.
Превыше всего я хотел бы поблагодарить Pancake, человека стоящего за radare2, создавшего эту впечатляющую тулзу свободной и открытой, и своих замечательных друзей в radare2 сообществе, которые посвятили свое время для помощи, улучшения и продвижения фреймворка.
Пожалуйста, оставляйте комментарии или сообщения приватно, если нечто неверно, неаккуратно, требует дополнительного разъяснения, или вы попросту этого не поняли. Не стесняйтесь делиться своими мыслями со мной.
Знакомство с Radare 2 -- часть вторая: эксплуатация (скоро).
© Translated by Cynically special for r0 Crew









Reply With Quote
Thanks
