Search
Write a publication
Pull to refresh
67
2.4

User

Send message

Нужно было быстренько перехватить вызов нативной функции и посмотреть значение переменной в Android приложении. Как то давно использовал для этого замечательную утилиту Frida. Установил на планшет frida-server (root уже был) и клиент на PC, написал классический JS хук, но он не работал:

defineHandler({
  onEnter(log, args, state) {
    conslole.log('decoder_CRC_check()');
  },

  onLeave(log, retval, state) {
    const libc = Module.findBaseAddress('libc.so');
    console.log(hexdump(libc, {
      /* address: ptr('0x1000'), -- to override the base address */
      offset: 0,
      length: 64,
      header: true,
      ansi: true
    }));
  }
});

В консоли лишь получал TypeError: not a function at onEnter (D:\Distrib\Android TV\frida\hook.js:7)

Убил полдня в поисках "чего я делаю не так", при том что и официальная дока и нейронки твердят, что именно так и нужно получать базовый адрес модуля и, при необходимости, функций. Оказалось, во Frida 17 автор полностью удалил некоторые функции (а дока и нейронки еще не обновились):

  • Module.ensureInitialized()

  • Module.findBaseAddress()

  • Module.getBaseAddress()

  • Module.findExportByName()

  • Module.getExportByName()

  • Module.findSymbolByName()

  • Module.getSymbolByName()

  • Туда же статические функции Memory

И теперь надо писать цепочку вызовов:

const lib = Process.findModuleByName("libc.so");
console.log("[*] libc.so loaded at base: " + lib.base);
const funcAddr = lib.findExportByName("decoder_CRC_t_init");

Итог получился такой универсальный скрипт:

Java.perform(function () {
	const System = Java.use("java.lang.System");
    const Runtime = Java.use('java.lang.Runtime');
    const SystemLoadLibrary = System.loadLibrary.overload('java.lang.String');
    const VMStack = Java.use('dalvik.system.VMStack');
    // "ожидание"\перехват динамической загрузки нативных библиотек
    SystemLoadLibrary.implementation = function(library) {
		console.log("Loading dynamic library => " + library);
        const loaded = Runtime.getRuntime().loadLibrary0(
            VMStack.getCallingClassLoader(), library
        );
        if (library.includes("mylibname")) {
            console.log("\n[+] Hooked mylibname");
            // перехватываем только нужную нам
            hookNativeFunc();
        }
        return loaded;
    }	
});

function hookNativeFunc() {
    //тут имя полностью как называется сам файл в ресурсах
	const lib = Process.findModuleByName("libmylibname.so");
    console.log("[*] mylibname.so loaded at base: " + lib.base);
    const funcAddr = lib.findExportByName("decoder_CRC_t_init");
    if (!funcAddr) {
        console.log("[-] Function not found!");
		return;
    }
    console.log("[+] Found decoder_CRC_t_init at: " + funcAddr);
    Interceptor.attach(funcAddr, {
        onEnter: function (args) {
            var result = args[0];
            var inputPtr = args[1];
            var len = args[2].toInt32();
            console.log("\n[+] decoder_CRC_t_init called");
            console.log("    result:    " + result);
            console.log("    inputPtr:  " + inputPtr);
            console.log("    len:       " + len);
        },
        onLeave: function (retval) {
            //нужный адрес массива, например из IDA PRO
            const wordArrayOffset = 0x5B2C04;
            const wordArray = lib.base.add(wordArrayOffset);
			var ptr = new NativePointer(wordArray); // современный вариант чтения
            console.log("[*] 5B2C04 contents:");
            try {
                console.log(hexdump(ptr, {
				  offset: 0,
				  length: 512,
				  header: true,
				  ansi: true
				}));
            } catch (e) {
                console.log("[!] Error reading 5B2C04:", e);
            }
            console.log("Return value:", retval);
        }
    });
}

Запускается так frida -U -f com.android.app -l hook.js

Tags:
Total votes 5: ↑5 and ↓0+6
Comments5

А вы знали, что можно фильтровать стек Журнала событий Home Assitant, например, убрать оттуда тонну сообщений о последнем обновлении датчиков и видеть там только важные сообщения.

Для этого в конфигурацию configuration.yaml нужно внести следующие строчки и перезагрузить HA

logbook:
  exclude:
    entity_globs:
      - sensor.*_last_seen
Tags:
Total votes 1: ↑1 and ↓0+2
Comments0

Универсальная автоматизация для Home Assistant, которая закрывает все краны в комнате, где произошла утечка

alias: Сработал датчик протечки
description: Закрыть все стояки в комнате, где сработал любой из датчиков
triggers:
  - value_template: >
      {{ states.binary_sensor | selectattr('attributes.device_class', 'eq',
      'moisture')| selectattr('state', 'eq', 'on') | list | count > 0 }}
    trigger: template
    for:
      hours: 0
      minutes: 0
      seconds: 5
actions:
  - variables:
      data: |
        {% set leak_sensor = states.binary_sensor
          | selectattr('attributes.device_class', 'eq', 'moisture')
          | selectattr('state', 'eq', 'on')
          | first %}
        {% if leak_sensor %}
          {% set area = area_id(leak_sensor.entity_id) %}
          {{ {'leak_sensor': leak_sensor.entity_id, 'area': area, 'area_name': area_name(area)} }}
        {% else %}
          {{ {'leak_sensor': None, 'area': None, 'area_name': 'Unknown'} }}
        {% endif %}
  - parallel:
      - data:
          entity_id: >
            {{ expand(area_entities(data.area)) | selectattr('domain', 'eq',
            'valve') | map(attribute='entity_id') | list }}
        action: valve.close_valve
      - action: script.play_text
        data:
          message: Обнаружена протечка в {{ data.area_name  }}, закрыла стояки
      - action: notify.persistent_notification
        metadata: {}
        data:
          message: Протечка в {{ data.area_name  }}
      - action: input_text.set_value
        metadata: {}
        data:
          value: Обнаружена протечка в {{ data.area_name  }}
        target:
          entity_id: input_text.protechka

Алгоритм простой, в течении 5 секунд должны появится устройства с типом moisture со статусом ON, по нему вычисляется комната и название (для вывода на экран и озвучивание), потом в найденной комнате все краны закрываются, плюс проигрывается звук на колонках, плюс выводится сообщение. Главное условие - датчики протечки и краны должны иметь свойство комната.

Tags:
Total votes 2: ↑2 and ↓0+3
Comments0
{% set special_device_timeouts  = {
  'sensor.0x1c34f1fffed6742a_last_seen':15, 
  'sensor.0x000d6f00132ac72f_last_seen':11,
} %}

{% set low_battery_devices = states.sensor 
 | selectattr('attributes.state_class', 'equalto', 'measurement') 
 | selectattr('attributes.battery_last_reported_level', 'defined') 
 | selectattr('attributes.battery_last_reported_level', 'is_number') 
 | selectattr('attributes.battery_last_reported_level', 'le', 10) 
 | list %}

{% set default_timeout = 4 %} 
{% set offline_devices = namespace(devices=[]) %}

{% for sensor in states.sensor 
  | selectattr('entity_id', 'search', '_last_seen$') 
  | selectattr('attributes.device_class', 'equalto', 'timestamp') 
  | selectattr('state', 'defined') 
  | rejectattr('state', 'in', ['unavailable', 'unknown', '']) %}
  {% set timeout = special_device_timeouts.get(sensor.entity_id, default_timeout) %}
  
  {% set last_seen_time = as_timestamp(sensor.state) %}
  {% set current_time = as_timestamp(now()) %}
  {% set hours_diff = ((current_time - last_seen_time) / 3600) | float %}
  {% set is_offline = hours_diff > timeout %}

  {% if is_offline %}    
    {% set offline_devices.devices = offline_devices.devices + [sensor] %}
  {% endif %}  
{% endfor %}

{% set all_devices = (offline_devices.devices + low_battery_devices)
  | map(attribute='attributes.friendly_name') 
  | map('replace', 'Last seen', '') 
  | map('replace', 'Батарея+', '') 
  | map('trim') 
  | join(', ')%}

{{ all_devices if all_devices else none}}

Написал шаблон вспомогательного устройства, аккумулирующий названия устройств на батарейках, которые не отвечают более 11 часов (нужно устройствам включить свойство last_seen) или заряд меньше 10. Можно использовать для вывода в виджет или предупреждать Алисой.

ЗЫspecial_device_timeouts - это список устройств с таймаутами, которые могут долго спать

Tags:
Rating0
Comments0

Будьте внимательны при продлении домена в TimeWeb - по умолчанию подключается "Премиум" тариф (+~500 руб). А чтобы его убрать нужно кликнуть по сумме.

PS В истории транзакций вывод на экран этого списания не реализован.

Tags:
Total votes 1: ↑1 and ↓0+2
Comments0

На днях приснилось(!) — «а что если сделать тестовый файл с Dolby Atmos, в котором динамически включалась\отключалась бы мета об объектах». Готовых роликов нет. Хотелось понять Atmos это все таки маркетинг или реальная технология улучшающая звуковое восприятие сцены. Подумалось, сделалось.

Основная фишка при воспроизведения дорожки с Атмосом это рендеринг звука в реальном времени в зависимости от оборудования пользователя, а в идеале и с учетом местоположения слушателя(!), будь то наушники (получится бинауральный звук), полноценная 7.1.4 аудио система или саундбар 7.1.4 (оборудование конечно же должно поддерживать Atmos, иначе, по обратной совместимости, будет получен классический многоканальный звук). То есть оборудование с поддержкой Atmos «знает» и о количестве доступных каналов, и об их расположении в пространстве, и о положении слушателя (для этого есть отдельная процедура калибровки с помощью микрофонов). Итого при классическом многоканале звук может воспроизводится спереди, слева где-то впереди, справа где-то впереди, где-то сзади слева, где-то сзади справа, а в случае Атмос, переходы звука из одного канала в другой будут плавнее (чем больше физ. каналов, тем точнее будет позиционироваться звук), звук может «подниматься» вверх и «приближаться» к пользователю.

Идея состояла в следующем: взять тестовый файл со звуком в Dolby Digital Plus with Atmos, выкинуть из него мету, сделать другой тестовый видео файл с дорожкой Dolby Digital Plus (без Atmos). Нарезать первый и второй файлы на равные отрезки и склеить их в третий, новый файл с чередованием кусков из первого и второго.

Получившиеся файлы можно скачать тут. Для удобства я вшил в видео текст с отображением Atmos. Бонусом записал вторую дорожку — стерео с верхних Top каналов в конфигурации 7.1.2

Наверняка такое "жесткое переключение" не предусмотрено стандартом Dolby, но это работает, в одном видео можно прослушать звук с Атмосом и без.

Мира!

Tags:
Total votes 2: ↑2 and ↓0+2
Comments1

Давно страдаю от того, что в HomeAssistant нет встроенных сенсоров по типу "Средняя температура в гостиной", "Средняя влажность в спальне" и достаточно долго для этого использовал инструмент "Объединение состояний сенсоров" (Настройки - Устройства - Вспомогательные - Создать вспомогательный объект - Объединение состояний сенсоров), тип "Медиана/Среднее арифметическое" и туда вручную добавлял датчики.

Недостатком было, что созданная сущность являлась просто числом и не относилась к домену "Температура", соответственно не было единицы измерения, не рисовались графики и нельзя было выбирать его в некоторых BluePrints, которые требовали температуру.

Сегодня открыл для себя Вспомогательные устройства на основе шаблонов, теперь все происходит автоматом.

Шаблон для нового устройства

{{ (states.sensor | selectattr('attributes.device_class', 'eq', 'temperature') 
  | selectattr('entity_id', 'in', area_entities('Гостиная')) 
  | map(attribute='state') | map('float', default=none) 
  | reject('==', none) | list | average(default=0)) }}

Бонус - шаблон для сенсора, который определяет (объединяет несколько сенсоров) человека в комнате

{{ states.binary_sensor | selectattr('attributes.device_class', 'in',['motion','occupancy','presence']) 
 | selectattr('state','eq','on') 
 | selectattr('entity_id', 'in', area_entities('Гостиная')+area_entities('Кухня')) 
 | list | count > 0 }}

Tags:
Total votes 4: ↑4 and ↓0+8
Comments0

Information

Rating
413-th
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

Backend Developer, Fullstack Developer
Lead
Git
Linux
OOP
Java
REST
Spring Boot
JDBC
Hibernate
Java Spring Framework
Apache Kafka