Секция «Методы и средства зашиты информации»
УДК 004:056
ОБФУСКАЦИЯ ПАМЯТИ ANDROID ПРИЛОЖЕНИЙ С ПОМОЩЬЮ РАНДОМИЗАЦИИ СТЕКА
Д. С. Доронина
Сибирский федеральный университет Российская Федерация, 660041, г. Красноярск, просп. Свободный, 79 E-mail: [email protected]
Статья рассматривает механизм обфускации памяти с помощью рандомизации стека для нативных функций Android приложений. Этот механизм может применяться при разработке программного обеспечения наземных систем управления.
Ключевые слова: обфускация памяти, рандомизация стека, ARM, безопасность Android. ANDROID APPS MEMORY OBFUSCATION BY STACK RANDOMIZATION
D. S. Doronina
Siberian Federal University 79, Svobodny Av., Krasnoyarsk, 660041, Russian Federation E-mail: [email protected]
The article considers the mechanism of memory obfuscation through stack layout randomization in native Android applications. This mechanism can be applicable for software development of terrestrial control system.
Keywords: memory obfuscation, stack layout randomization, ARM, Android security.
Введение. В данной работе рассматривается реализация механизма рандомизации стека функций, работающих под ARM-архитектурой, описанного в статье [1]. Механизм актуален для защиты памяти от таких атак, как переполнение буфера [2]. В отличие от механизма ASLR данный механизм гораздо меньше влияет на производительность программ, а также не имеет известных методов обхода [3]. Этот механизм может применяться в том числе и при разработке программного обеспечения наземных систем управления, а также в задачах фаззинга методом «серого ящика» (например, см. [4; 5]).
Принцип рандомизации стека. Рассмотрим состояние стека при вызове функции. В начале стека находятся параметры функции, затем занесенные в стек регистры в обратном порядке, далее находится место для локальных переменных функции (см. рис. 1). В последней строчке происходит сдвиг регистра sp на начало места, где помещаются локальные переменные. Состояние стека при добавлении дополнительных регистров в стек показано на рис. 2 (k - количество регистров, добавленных в начало; m - количество регистров, добавленных в конец; c - количество изначальных регистров).
Видно, что регистры могут быть добавлены в начало, так и в середину (до регистра lr - адреса возврата).
При добавлении регистров данные в стеке смещаются, следовательно необходимо обеспечить доступ к ним. Рассмотрим ситуации, при которых необходимо менять код:
1. Обращение к данным, находящимся по адресу [sp, #b], где b - любое число
Данный вид обращение используется в большинстве случаев для доступа к локальным переменным.
2. Передача значения sp в другой регистр (rx) и обращение к данным по адресу [rx, #b].
Такой вид обращения может использоваться для доступа как к локальным переменным, так
и к параметрам функции.
Актуальные проблемы авиации и космонавтики - 2017. Том 2
3. Передача значения гх в другой регистр (гу) и обращение по [гу, #Ь] (и т. д.) Данный вид обращения достаточно редок, однако его также нужно отслеживать.
ао
а
local variable n „ sp *
Локальные
пеоемеиг+ые
iota vansti e i 1
r2 / i
rS Регмстрь
a
it \
argS A Параметры
arqti функции V
push {г2. гЗ. г4. 1г} SUt) Sp #3
--
Рис. 1. Состояние стека при переходе в функцию
Рис. 2. Состояние стека после добавления дополнительных регистров
Таким образом, для обеспечения работоспособности функции после добавления дополнительных регистров необходимо сделать следующее:
1. Найти все обращения вида [sp, #b]. Для каждого обращения проверить значение b-a, где a - значение, которое было вычтено из sp в начале функции.
Если b-a < 0, значит [sp, #b] указывает на область локальных переменных. После выполнения push всех регистров указатель стека sp указывает на регистр lr (как было бы и без дополнения дополнительных регистров), следовательно, локальные переменные не изменили своего местоположения относительно sp, следовательно, делать сдвиг не нужно.
Если 0 <= b-a < 4c, то b = b + 4к. Если b-a >= 4c, то b = b + 4(к + m). (Умножение на 4 необходимо, так как каждый регистр занимает в стеке 4 байта).
2. Найти все инструкции вида mov rx, sp / add rx, sp, #z (z - любое число) (1), т. е. инструкции, в которых происходит перемещение значения sp (возможно, со смещением) в регистр rx.
Дла каждой инструкции найти инструкцию вида (mov rx, ...) / (ldr rx, ...) (2), в которой затирается значение sp в регистре rx. Затем произвести действия из пункта 1 относительно [rx, #b] для инструкций между (1) и (2), заменив b-a на b + z, если инструкция (1) стоит до инструкции sub sp, #a, и на b+ z-a, если после.
Секция «Методы и средства зашиты информации»
3. Аналогичные действия произвести для инструкций вида mov ry, rx/ add ry, rx, #z (rx - регистр из шага 2).
Вывод. На данном этапе разработана программа, которая производит рандомизацию стека для относительно небольших функций с различным количеством входных параметров. Программа реализована путем дизассемблирования библиотек, парсинга получившихся файлов и перезаписи библиотеки по вышеописанному алгоритму. На вход программе подается apk-файл, на выходе имеем пересобранный переподписанный apk-файл с рандомизацией стека для нативных библиотек.
Библиографические ссылки
1. Liang Y. et el. Stack Layout Randomization with Minimal Rewriting of Android Binaries // 18th annual International Conference on Information Security and Cryptology (ICISC 2015).
2. Bright P. How security flaws work: The buffer overflow [Электронный ресурс]. URL : https://arstechnica.com/security/2015/08/how-security-flaws-work-the-buffer-overflow/ (дата обращения: 10.04.2017).
3. Anti-malware [Электронный ресурс]. URL: https://www.anti-malware.ru/news/2016-10-20/21252 (дата обращения: 10.04.2017).
4. Shudrak M., Zolotarev V. Improving fuzzing using software complexity metrics // Lecture Notes in Computer Science. 2016. Vol. 9558. Рp. 246-261.
5. Shudrak M., Zolotarev V. The technique of dynamic binary analysis and its application in the information security sphere // In Proceedings of IEEE EuroCon - 2013, Zagreb, Croatia. 2013. Рp. 112-118.
© Доронина Д. С., 2017