
Сканер уязвимостей приложений iOS/Android без декомпиляции (DC25 demo lab, CB17)
# README




trueseeing — это быстрый, точный и устойчивый сканер уязвимостей для iOS/Android-приложений. Мы работаем на уровне Dalvik VM для Android — то есть нам неважно, обфусцировано целевое приложение или нет.
## Возможности
В настоящее время мы можем:
* Автоматически сканировать приложение на уязвимости, формируя отчёт в формате HTML/JSON/текст (см. ниже)
* Модифицировать приложение для упрощения анализа: например, включать отладочный бит, разрешать полное резервное копирование, отключать TLS pinning, изменять целевой API level, внедрять frida-gadget и т. д.
* Изучать общую информацию о приложении
* Копировать данные в/из приложения через отладочный интерфейс
* Искать определённые вызовы/константы/sput/iput
* Восстанавливать константы/наборы типов для аргументов операций
* Сканировать вызовы API/приватных методов для нативного кода (примечание: требуется [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
* Сканировать iOS-приложения на базовые уязвимости (примечание: требуется [ts2-disasm-ghidra](https://github.com/alterakey/ts2-disasm-ghidra))
* Подключать frida-скрипты
* Запускать интерактивную сессию frida
* Трассировать вызовы
* и т. д.
## Установка
### Контейнеры
ПРИМЕЧАНИЕ:
* Начиная с версии 2.1.9 мы размещаемся на ghcr.io (Docker Hub несколько устарел).
* Требуется adbd на хосте для управления устройствами.
Мы предоставляем контейнеры, которые можно использовать сразу, как показано ниже; сейчас это также рекомендуемый способ и единственный для Windows:
$ docker run --rm -v $(pwd):/out -v ts2:/cache ghcr.io/alterakey/trueseeing
Если вы хотите запускать без сохранения состояния, можно не монтировать том в /cache (не рекомендуется для повседневного использования; см. также [#254](https://github.com/alterakey/trueseeing/issues/254)):
$ docker run --rm -v $(pwd):/out ghcr.io/alterakey/trueseeing
### Установка с помощью [uv](https://github.com/astral-sh/uv)
Кроме того, вы можете установить наш пакет с помощью [uv](https://github.com/astral-sh/uv) следующим образом. Особенно форма `uv tool install` может быть полезна для расширений (см. ниже), так как она предоставляет им наибольшую свободу. Просто помните, что вам понадобятся JRE и Android SDK (опционально; для работы с устройствами):
$ uvx trueseeing
$ uv tool install trueseeing
$ trueseeing
### Установка с помощью pip (устаревший способ)
Конечно, вы всегда можете использовать старый добрый pip, если это необходимо:
$ pip install trueseeing
## Использование
### Интерактивный режим
Вы можете интерактивно сканировать/анализировать/модифицировать приложения — это идеальный выбор для ручного анализа:
$ trueseeing target.apk
[+] trueseeing x.y.z
ts[target.apk]> ?
...
ts[target.apk]> i # показать общую информацию
...
ts[target.apk]> pf AndroidManifest.xml # показать манифест
...
ts[target.apk]> a # также анализировать ресурсы
...
ts[target.apk]> /s something # поиск текста
...
ts[target.apk]> as # сканирование
...
[+] done, found 6403 issues (174.94 sec.)
ts[target.apk]> gh report.html
### Пакетный режим
Мы принимаем встроенную команду (`-c`) или файл скрипта (`-i`) для выполнения перед выводом приглашения, а также возможность сразу завершить работу без приглашения (`-q`; в этом режиме tty не требуется!).
Вы можете использовать эти возможности для проведения пакетного сканирования, например, для вывода результатов сразу в stderr:
$ trueseeing -eqc 'as' target.apk
Для создания файла отчёта в формате HTML:
$ trueseeing -eqc 'as;gh report.html' target.apk
Для создания файла отчёта в формате JSON:
$ trueseeing -eqc 'as;gj report.json' target.apk
Чтобы вывести отчёт в stdout, опустите имя файла в последней команде `g*`:
$ trueseeing -eqc 'as;gh' target.apk > report.html
$ trueseeing -eqc 'as;gj' target.apk > report.json
### Неинтерактивный режим сканирования (устаревший способ)
Традиционно вы можете сканировать приложения с помощью следующей командной строки, чтобы получить список находок в stderr:
$ trueseeing --scan target.apk
Чтобы создать отчёт в формате HTML:
$ trueseeing --scan --scan-output report.html target.apk
$ trueseeing --scan --scan-report=html --scan-output report.html target.apk
Чтобы создать отчёт в формате JSON:
$ trueseeing --scan --scan-report=json --scan-output report.json target.apk
Чтобы вывести отчёт в stdout, укажите '-' в качестве имени файла:
$ trueseeing --scan --scan-output - target.apk > report.html
$ trueseeing --scan --scan-report=html --scan-output - target.apk > report.html
$ trueseeing --scan --scan-report=json --scan-output - target.apk > report.json
## Расширенное использование
### Расширения
Вы можете создавать свои собственные команды и сигнатуры в виде расширений. Расширения размещаются в каталоге `/ext` (контейнеры) или `~/.trueseeing2/extensions/` (uv/pip). Кроме того, вы можете распространять расширения в виде wheel-пакетов. Мы предоставляем информацию о типах, так что вы сможете не только проверять типы ваших расширений с помощью [zuban](https://github.com/zubanls/zuban), но и получать хорошую поддержку от IDE. Подробнее см. в разделе «Детали».
## Сборка
Сборка выполняется следующим образом:
$ docker build -t trueseeing https://github.com/alterakey/trueseeing.git#main
Для сборки wheel-пакетов можно воспользоваться [flit](https://flit.pypa.io/en/stable/):
$ flit build
Для взлома (разработки) необходимо создать подходящее окружение. С помощью [uv](https://github.com/astral-sh/uv) можно просто сделать:
$ git clone https://github.com/alterakey/trueseeing.git wc
$ uv sync --locked --dev
$ (... hack ...)
$ uv run trueseeing ... # запуск
$ uv run zuban check trueseeing && uv run ruff trueseeing # проверка
Success: no issues found in XX source files
$ uv run flit build # сборка (wheel)
$ docker build -t trueseeing . # сборка (контейнер)
С помощью pip: сначала создайте venv, установите [flit](https://flit.pypa.io/en/stable/) и инструменты проверки ([zuban](https://github.com/zubanls/zuban) и [ruff](https://github.com/astral-sh/ruff)), затем позвольте flit подтянуть зависимости. Вкратце:
$ git clone https://github.com/alterakey/trueseeing.git wc
$ python3 -m venv wc/.venv
$ source wc/.venv/bin/activate
(.venv) $ pip install flit zuban ruff
(.venv) $ flit install --deps=develop -s
(.venv) $ (... hack ...)
(.venv) $ trueseeing ... # запуск
(.venv) $ zuban check trueseeing && ruff check trueseeing # проверка
Success: no issues found in XX source files
(.venv) $ flit build # сборка (wheel)
(.venv) $ docker build -t trueseeing . # сборка (контейнер)
## Детали
### Классы уязвимостей
В настоящее время мы можем обнаружить следующие классы уязвимостей, в основном описанные в OWASP Mobile Top 10 - 2016:
* Неправильное использование платформы (M1)
* Debuggable
* Непреднамеренная публикация Activity, Service, ContentProvider, BroadcastReceiver
* Небезопасные данные (M2)
* Backupable (т.е. подвержено атаке через резервное копирование)
* Небезопасные права доступа к файлам
* Логирование
* Незащищённые коммуникации (M3)
* Отсутствие pinning'а (т.е. подвержено атаке перехвата TLS)
* Использование открытого HTTP
* WebView, допускающие модификацию
* Недостаточная криптография (M5)
* Жёстко заданные пароли/секретные ключи
* Шифры Вернама со статическими ключами
* Использование режима ECB
* Проблемы качества клиентского кода (M7)
* WebView с возможностью отражения (т.е. XSS в таких представлениях могут быть повышены до удалённого выполнения кода через JS-отражение)
* Использование небезопасной политики в отношении смешанного контента
* Модификация кода (M8)
* Жёстко заданные сертификаты
* Обратная разработка (M9)
* Отсутствие обфускации
### API расширений
API расширений находится в пакете `trueseeing.api`. Поскольку мы предоставляем информацию о типах, ваша IDE будет помогать вам при написании расширений. Просто убедитесь, что PYTHONPATH вашей IDE (или её языкового сервера) покрывает venv, в котором установлен наш пакет; см. `uv tool list --show-paths`, если вы установили его с помощью `uv tool install`. Если вы установили с помощью `uvx`, рассмотрите возможность переустановки с помощью `uvx install`. Если вы установили через pip, вы уже знаете, где он находится.
#### Команды
Для определения новых команд реализуйте `trueseeing.api.Command` и зарегистрируйте их.
Следующий класс предоставит пример команды `t`, например:
```python
from typing import TYPE_CHECKING
from trueseeing.api import Command
from trueseeing.core.ui import ui
if TYPE_CHECKING:
from trueseeing.api import CommandMap, CommandPatternMap, ModifierMap, OptionMap, ConfigMap
class MyCommand(Command):
@staticmethod
def create() -> Command:
return MyCommand()
def get_commands(self) -> CommandMap:
return {'t':dict(e=self._test, n='t', d='sample command')}
def get_command_patterns(self) -> CommandPatternMap:
return dict()
def get_modifiers(self) -> ModifierMap:
return dict()
def get_options(self) -> OptionMap:
return dict()
def get_configs(self) -> ConfigMap:
return dict()
async def _test(self) -> None:
ui.info('hello world')
```
#### Сигнатуры
Для определения новых сигнатур реализуйте `trueseeing.api.Signature` и зарегистрируйте их.
Следующий класс предоставит пример детектора `my-sig`, например:
```python
from typing import TYPE_CHECKING
from trueseeing.api import Signature
if TYPE_CHECKING:
from trueseeing.api import SignatureMap, ConfigMap
class MySignature(Signature):
@staticmethod
def create() -> Signature:
return MySignature()
def get_sigs(self) -> SignatureMap:
return {'my-sig':dict(e=self._detect, d='sample signature')}
def get_configs(self) -> ConfigMap:
return dict()
async def _detect(self) -> None:
self._helper.raise_issue(
self._helper.build_issue(
sigid='my-sig',
title='hello world',
cvss='CVSS:3.0/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N/',
)
)
```
#### Форматы файлов
Для определения новых форматов файлов сначала реализуйте `Context` (ABC) для ваших форматов, затем реализуйте `trueseeing.api.FileFormatHandler` для создания и возврата их экземпляров, и зарегистрируйте их.
Следующий класс предоставит поддержку APK-файлов под типом `apk2`, например:
```python
from typing import TYPE_CHECKING
from trueseeing.api import FileFormatHandler
from trueseeing.core.android.context import APKContext
if TYPE_CHECKING:
from typing import Optional, Set
from trueseeing.api import FormatMap, ConfigMap
from trueseeing.core.context import Context, ContextType
class MyAPKContext(APKContext):
# Используем другой тип контекста
def _get_type(self) -> Set[ContextType]:
return {'apk2'}
class APKFileFormatHandler(FileFormatHandler):
@staticmethod
def create() -> FileFormatHandler:
return APKFileFormatHandler()
def get_formats(self) -> FormatMap:
return {'apk2':dict(e=self._handle, r=r'\.apk$', d='sample file format', t=None)} # если этот обработчик может предлагать тип контекста устройства, укажите его в t
def get_configs(self) -> ConfigMap:
return dict()
def _handle(self, path: str) -> Optional[Context]:
return MyAPKContext(path)
```
Затем убедитесь, что в ваших сигнатурах проверяется тип контекста, чтобы они игнорировались на неподдерживаемых контекстах:
```python
context = self._helper.get_context().require_type('apk2')
```
При успешной проверке `require_type(...)` попытается понизить тип для вашего удобства.
Но по дизайну это работает только для известных типов (в настоящее время — `apk`). Поэтому, если вы определяете какие-то подробные интерфейсы в своих новых классах контекста, как мы это делаем для типа `apk`, вам нужно выполнить понижение здесь, т.е.:
```python
context: MyAPKContext = self._helper.get_context().require_type('apk2') # type:ignore[assignment]
```
Можно определить несколько форматов, соответствующих одному и тому же шаблону. Мы оцениваем шаблоны в порядке от наиболее строгого (т.е. длинного) к наименее строгому. Используйте ключ `-F`, чтобы принудительно использовать определённый формат для целевого файла, например:
```
$ trueseeing -F apk2 target.apk
```
#### Требования к пакетам
Расширения могут быть: a) любым пакетом, помещённым в `/ext` (контейнер) или `~/.trueseeing2/extensions` (pip), либо b) любым установленным модулем с именем, начинающимся с префикса `trueseeing_ext0_`.
### Происхождение названия проекта?
Заклинание из D&D, [True Seeing](https://www.dandwiki.com/wiki/SRD:True_Seeing).