21 января 2013 в 02:59

История реверс-инжиниринга одного пушистого зверька



Тихим утром третьего января, когда Москва уже дремала после новогодних праздников, в нашей квартире раздался звонок в дверь. Почта наконец-то доставила посылку с новогодними подарками, заказанными на Амазоне. Среди прочего в ней находился и подарок для сына — электронный питомец Furby. Покупка его была, в общем-то импульсной. Игрушка значилась в бестселлерах новогоднего сезона и стоила относительно недорого. В сортах Furby я не разбирался, но когда-то давно что-то позитивное об игрушке слышал.

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

Надпись гласила, что для данной игрушки в AppStore можно скачать приложение, с помощью которого киберпитомца можно кормить, подавать ему всякие команды, а также переводить фразы, которые он произносил на своем языке — фурбише (Furbish), на английский. Приложение было скачано, питомец покормлен всякими съедобными и несъедобными объектами, которые он либо с аппетитом проглатывал, либо выплевывал, а переводчик с фурбиша на английский работал на удивление точно.

Неужели распознавание аудио работает в наше время так надежно и даже в довольно шумной обстановке? Что-то тут не так. И как приложение передает команды Furby? ИК отпадает (ранние версии Furby, как выяснилось, имели ИК-порт для общения между собой), Bluetooth тоже. Остается только аудио. Это интересно… Вот если бы удалось хакнуть протокол общения с этим созданием и уметь управлять им с компьютера… Найти какие-то «пасхальные яйца», скрытые или сервисные команды! Или…

В общем, как вы поняли, отец семейства сделал себе на Новый Год подарок.

***

Для начала синхронизировал iPhone с компьютером и заглянул внутрь файла приложения (.ipa). Среди прочей требухи там нашлось несколько десятков коротких WAV-файлов, пронумерованных особым образом. Все это очень смахивало на готовые аудиокоманды. Первый файл начинался с номера 350. После воспроизведения этого файла в Audacity Furby чего-то деловито пожевал и выдал радостное «Mmm, yum!». «Ага!» — подумал Штирлиц, — «Теперь-то ты у меня наешься!».

Команды в приложении начинались с 350-й и заканчивались 900-й, с большими пробелами в нумерации. Значит потенциально Furby умеет воспринимать гораздо большее число команд, чем есть на руках этих готовых WAV-файлов. Надо искать дальше.

Внешний вид сигнала в Audacity наводил на мысль, что используется какая-то частотная модуляция, причем шел один сигнал, дальше небольшая пауза, затем визуально такой же сигнал снова. Общая продолжительность — полторы секунды. Раз модуляция частотная, то неплохо бы взглянуть на спектр. Посмотрел график — на нем отчетливо выделялось пять пиков на одинаковых расстояниях друг от друга в районе 16-19КГц:



Башня из Мордора — это, конечно, красиво, но как это расшифровать? Покопался в Audacity еще немного и отрыл режим отображения аудио в виде спектрограммы. Вот эта картинка уже была гораздо красивее первой:



Здесь отчетливо видны две посылки с паузой посередине, отличающиеся друг от друга порядком следования «нот» (базовых частот). Причем средняя частота является несущей, постоянно чередуясь с другими четырьмя «нотами».

Для удобства декодирования последовательности сделал в графическом редакторе маску, которую наложил поверх скриншота спектрограммы, присвоил каждой ноте последовательно числа от 0 до 3 и начал анализировать последовательно идущие команды (как мы помним, разработчики iOS-приложения услужливо пронумеровали нам все WAV-файлы). Поначалу оказалось, что в соседних командах числа иногда «прыгают», т.е. идут не так, как хотелось бы при последовательном инкрементировании чисел. После некоторого анализа стало понятно, что «ноты» надо нумеровать так, как на рисунке ниже:



Здесь посылка расшифровывается как 3233 3012 1032 (для удобства восприятия я разбил последовательности на блоки по четыре цифры; в четверичной системе каждый такой блок — это один байт).

Дальнейший анализ команд, перевод их бинарную форму и побитовое сравнение выявило следующую структуру посылки и команды в целом:

  1. Первый байт (в примере это 3233), будучи записанным в бинарном виде, имеет следующую структуру: 11 1 01111, где старшие два бита всегда равны 11, следующий бит равен 0 для первой посылки в команде и 1 для второй, а 01111 — это сами данные (часть идентификатора команды);
  2. Второй байт (3012) — контрольная сумма, зависящая от 6 бит команды (где 1 бит — идентификатор посылки и 5 бит — сами данные);
  3. Третий и заключительный байт посылки всегда равен 1032.


Что это значит? Во-первых, команда разбивается на два пакета по 5 бит данных в каждом. В сумме мы получаем 10-битное число, т.е. потенциальное число команд, которые может посылать или принимать Furby — 1024. Однако метод вычисления контрольной суммы вычислить не удалось. Проанализировав номера команд получилось, что я могу на основе имеющихся WAV-файлов найти 7 из 32 контрольных сумм для первой посылки и 31 из 32 контрольных сумм для второй посылки. В сумме это давало 217 потенциальных команд вместо имеющихся 76 (в виде готовых WAV-файлов), что тоже неплохо.

Написал скрипт, который генерировал по нужному номеру команды WAV-файл, подобный готовому, и начал перебирать доступные мне диапазоны команд. Как оказалось, недокументированные команды действительно были — Furby реагировал на них разным образом, пел песенки, читал рэп, чихал, имитировал сон и делал прочие незамысловатые вещи.

Это подстегнуло исследовательский аппетит, однако алгоритм вычисления контрольной суммы реверс-инжинирингу упорно не поддавался, а значит большая часть команд оставалась для меня недоступной.

В очередной раз прочесывая Интернет на предмет каких-нибудь зацепок я вдруг обнаружил ссылку на официальное приложение Furby для Android (про которое на коробке с игрушкой не было ни слова). «Android → Java → байт-код → исходники → … → ПРОФИТ!». Никогда еще Штирлиц не был так близок к разгадке…

***

Найдя наконец на какой-то помойке нужный мне .apk-файл, я залез внутрь и не увидел ни одного WAV-файла с командами, хотя в целом набор ресурсов был похож на тот, что в приложении для iOS. Раз WAV-файлов нет, то приложение как-то генерит команды на лету? Это то, что мне нужно! Декомпиляция и просмотр Java-кода дал несколько интересных зацепок, но как оказалось, вся интересная начинка, а именно генерация и анализ аудио, находится внутри нативной .so-библиотеки, в которой есть один метод, который мне был нужен, а именно private static native byte[] GenerateComAirCommand(int paramInt);.

Как же достучаться до нативного метода? Пораскинув мозгами, Штирлиц решил качать Android SDK. В итоге был собран маленький проект, в который включена сама нативная библиотека и минимальная обвязка, предоставляющая доступ к одной только нужной мне функции. Само же приложение при старте просто создавало WAV-файлы для минимально необходимого мне набора WAV-файлов, где в командах были те самые недостающие старшие и младшие 5 бит, для которых мне были нужны контрольные суммы. После некоторого курения Stack Overflow (опыта написания приложений под Android у меня на тот момент не было) приложение запустилось и сгенерировало мне на виртуальной SD-карте эмулятора набор нужных мне WAV-файлов, которые я перетащил через adb pull в нормальную файловую систему. Анализ этих файлов дал мне полное покрытие — все 64 контрольных суммы, по которым можно воссоздать любую из 1024 команд.

В ходе анализа реакций Furby на команды был найден еще один диапазон команд, на который Furby так или иначе реагировал. Однако каких-то атомарных команд типа «открой глаза», «закрой глаза», «пошевели ушами» обнаружено не было. Равно как и не была найдено команд самоуничтожения или зачитывания EULA на фурбише (это не значит, что каких-то специализированы команд нет, просто они могут активироваться, например, особой последовательностью или вообще другим набором кодов — но это как-то выяснить вряд ли возможно).

***

Однако я решил пойти дальше и написать анализатор ответов Furby, так как некоторые команды, хотя и не дают видимого результата, могут вызывать реакцию Furby в виде ответных команд, что тоже интересно. В итоге был написан Perl-скрипт, анализирующий поток PCM-данных с микрофона, делающий на лету и расшифровывающий эти посылки. Писалось все это под Windows, где для Perl, к сожалению, нету нормальных способов записи данных с микрофона, поэтому пришлось сделать консольную программу на Delphi, которая читает с микрофона данные и выводит их непрерывно в STDOUT. Поток данных перенаправляется в скрипт, где уже происходит анализ. Такой вот Unix way для Windows.

«Стоп, стоп, стоп,» — скажет утомленный читатель, — «А для чего все это нужно?»

Мне было интересно посмотреть, «что у него внутри», не ломая игрушку физически (все-таки покупал не себе). Попутно получил знания о генерации и анализе звука в Perl, о FFT, оконных функциях, о работе с Android, что само по себе увлекательно.

Возможно кому-то данная статья пригодится при реализации собственного протокола, есть ведь всякие интересные примочки для iPhone, передающие данные как раз через аудиоразъем.

Ну и, наконец, возможность управлять Furby через компьютер потенциально открывает эмоциональный метод нотификации о каких-то событиях. Например, при приходе почты от определенного адресата можно попросить Furby что-то станцевать, по приходу коммита в Git от определенного человека — помурлыкать, а от другого — издать звук менее приличный (коих у Furby есть в запасе). Правда для этого все же нужно решить уже парочку задач хардверных. Во-первых, запретить Furby засыпать через 10 минут неактивности (а активностью считается физическое тормошение — для этого у него имеется датчик положения в пространстве) и питать его не от батареек, а от блока питания или USB. Может быть на Хабре есть знатоки железа, которые захотят окончательно укротить зверька?

Сам код после некоторого причесывания выложен на GitHub. Пожелания и находки всячески приветствуются. Разумеется, вся изложенная информация и программный код предоставлен исключительно в образовательных целях.

Oo-tah-toh-toh. Kah way-loh.
+309
106435
297
afan 138,7

Комментарии (82)

+40
Boleg2, #
Вот это да… А я думал — Хабра становится скучна )
К сожалению, помочь по сабжу ничем не смогу. Большое спасибо за статью, прочёл с удовольствием.
0
timsoid, #
Хорошая игрушка, говорят скоро в России появятся локализованные, но будут стоить не 50$, а 4500р…
+11
spmbt, #
Как уже писали на такую тему про цены на разные эпплы, Россия — очень богатая страна: ). А вот и идея для мелкого заработка через интернет с использованием наработок автора — делать локализацию самостоятельно и продавать не за 4500, а за 3000 и с полным набором команд. (А за доп. плату — менять прошивку на перевод от Гоблина: ) ).
+1
JagaJaga, #
Дарили мне такую в 2001 году, вроде… Еще с ик-портом :)
+7
JaLoveAst1k, #
Вот так взять и без опыта растормошить apk, а потом прикрутить к своему проекту вынутую библиотеку — респект :)
Таки сколько рабочих команд оказалось в зверке?
+4
afan, #
Все они перечислены здесь: github.com/iafan/Hacksby/blob/master/lib/Furby/Command.pm (некоторые уже описаны, некоторые еще нет).

Большинство кодов зарезервировано не за командами, а за ответами Furby (когда он произносит фразу, он посылает и код этой фразы). Эти коды описаны тут: github.com/iafan/Hacksby/blob/master/lib/Furby/Command/Dictionary.pm

Ну и наконец, существуют коды, которые можно посылать в виде команд (Furby на них как-то отреагирует), так и получить от Furby в виде события.

Попытка понять закономерности и точно описать команды — отдельная большая работа.
+1
spmbt, #
Возможно, там не датчик положения, а простейший «датчик тормошения», как в игрушках-мячиках, которые включают светодиоды, когда мячик подпрыгивает — это дешевле и энергоэффективнее, с ним вообще не надо тратить энергии во сне. И тогда задача его бодрствования будет решена, если сигнал просыпания подавать постоянно — просто перемкнуть механический выключатель. 10-минутный таймер никогда его не будет выводить в сон.

По питанию — посмотрите, от какого напряжения он питается, и если меньше 5 вольт, то цепочкой диодов можно сбросить напряжение до нужного (но при малом потреблении в режиме сна там всё равно будет близко к 5 В, поэтому проверку схемы должен, конечно, сделать знающий человек). А если более 5 — то есть микросхемы повышения напряжения (опять же, быстрее сделает специалист или любитель с опытом), если делать красиво и с высоким КПД. Или, самое простое, выбрать БП с нужным напряжением и током.
0
afan, #
Вот здесь пишут, что датчик положения. Вообще и с точки зрения железа и компоновки игрушка довольно интересная, но курочить ее жалко.

До некоторой степени ее можно аккуратно разобрать и частично посмотреть внутренности, но дальше уже требуется необратимое вмешательство.
0
roman01la, #
Как раз к нг купил одного такого малыша. Спасибо за упоминание приложения для Android, думал нет такого)
+4
shapa, #
Вообще-то для нотификаций и прочего есть не менее забавная игрушка Karotz, у меня она разговаривает и ушами машет например когда почту в ящик (физический ;)) ) кладут

www.karotz.com
0
afan, #
Это nazbatag который? Да, интересный девайс для нотификаций. Правда как подарок сыну данная покупка уже не прокатила бы, а покупать себе такие игрушки уже разрешения у внутренней жабы спрашивать надо.
+4
Dreddik, #
Круто, прочитал на одном дыхании!
Автору респектище!
+3
lohmat, #
Вот это я понимаю, провел новогодние праздники с интересом и пользой! :) Отличная статья.
+4
icoz, #
А жена что сказала? ;-)
+5
afan, #
Жена к такому «творческому запою» отнеслась с пониманием, за что ей большое спасибо. )
+5
BarsMonster, #
Хе-хе, а как насчет такой идеи: берем мозги Furby и засовываем в рыбу?

+9
Disasm, #
Как же достучаться до нативного метода? Пораскинув мозгами, Штирлиц решил качать Android SDK.

IDA Pro надо было качать, IDA Pro.
0
Vilko, #
Достучаться и распотрошить — разные вещи. Хотя согласен, реверс нативного метода тоже был бы уместен в изучении :)
0
afan, #
Мое общение с ассемблером закончилось лет двадцать назад, так что это уже было бы выше моей головы. Но если кто захочет посмотреть, каков алгоритм вычисления вот этих контрольных сумм, я буду признателен.
0
tyomitch, #
Первая тетрада контрольной суммы вычисляется очевидно: (cmd % 8) + (cmd / 8) (cmd берётся, включая бит номера пакета)
+1
tyomitch, #
Вот вторую тетраду не могу расколоть голыми руками.
Где взять эту вашу нативную библиотеку, чтоб заглянуть внутрь?
0
afan, #
Напишите в личку.
0
icoz, #
Результаты есть? Заинтригован.
Уже подумываю над покупкой сего девайса с целью потрошения. Только вот цена на него в 6 килорублей пока сдерживает…
0
afan, #
Заказывайте с Амазона с пересылкой (куча разных компаний есть, которые предоставляют виртуальный адрес в США). Если интересно, могу в личку написать, какой я пользовался.

А по результатам — есть перечень известных команд и их частичное описание (в исходниках проекта на Github).
+1
Vilko, #
Чексум берется как младший байт из таблички
табличка
DCW 0, 0x1E, 0x2D, 0x33, 0x4C, 0x52, 0x61, 0x7F, 0x8B, 0x95, 0xA6, 0xB8, 0xC7, 0xD9, 0xEA, 0xF4 DCW 0x10A, 0x114, 0x127, 0x139, 0x146, 0x158, 0x16B, 0x175, 0x181, 0x19F, 0x1AC, 0x1B2, 0x1CD, 0x1D3, 0x1E0, 0x1FE DCW 0x209, 0x217, 0x224, 0x23A, 0x245, 0x25B, 0x268, 0x276, 0x282, 0x29C, 0x2AF, 0x2B1, 0x2CE, 0x2D0, 0x2E3, 0x2FD DCW 0x303, 0x31D, 0x32E, 0x330, 0x34F, 0x351, 0x362, 0x37C, 0x388, 0x396, 0x3A5, 0x3BB, 0x3C4, 0x3DA, 0x3E9, 0x3F7 DCW 0x407, 0x419, 0x42A, 0x434, 0x44B, 0x455, 0x466, 0x478, 0x48C, 0x492, 0x4A1, 0x4BF, 0x4C0, 0x4DE, 0x4ED, 0x4F3 DCW 0x50D, 0x513, 0x520, 0x53E, 0x541, 0x55F, 0x56C, 0x572, 0x586, 0x598, 0x5AB, 0x5B5, 0x5CA, 0x5D4, 0x5E7, 0x5F9 DCW 0x60E, 0x610, 0x623, 0x63D, 0x642, 0x65C, 0x66F, 0x671, 0x685, 0x69B, 0x6A8, 0x6B6, 0x6C9, 0x6D7, 0x6E4, 0x6FA DCW 0x704, 0x71A, 0x729, 0x737, 0x748, 0x756, 0x765, 0x77B, 0x78F, 0x791, 0x7A2, 0x7BC, 0x7C3, 0x7DD, 0x7EE, 0x7F0 DCW 0x806, 0x818, 0x82B, 0x835, 0x84A, 0x854, 0x867, 0x879, 0x88D, 0x893, 0x8A0, 0x8BE, 0x8C1, 0x8DF, 0x8EC, 0x8F2 DCW 0x90C, 0x912, 0x921, 0x93F, 0x940, 0x95E, 0x96D, 0x973, 0x987, 0x999, 0x9AA, 0x9B4, 0x9CB, 0x9D5, 0x9E6, 0x9F8 DCW 0xA0F, 0xA11, 0xA22, 0xA3C, 0xA43, 0xA5D, 0xA6E, 0xA70, 0xA84, 0xA9A, 0xAA9, 0xAB7, 0xAC8, 0xAD6, 0xAE5, 0xAFB DCW 0xB05, 0xB1B, 0xB28, 0xB36, 0xB49, 0xB57, 0xB64, 0xB7A, 0xB8E, 0xB90, 0xBA3, 0xBBD, 0xBC2, 0xBDC, 0xBEF, 0xBF1 DCW 0xC01, 0xC1F, 0xC2C, 0xC32, 0xC4D, 0xC53, 0xC60, 0xC7E, 0xC8A, 0xC94, 0xCA7, 0xCB9, 0xCC6, 0xCD8, 0xCEB, 0xCF5 DCW 0xD0B, 0xD15, 0xD26, 0xD38, 0xD47, 0xD59, 0xD6A, 0xD74, 0xD80, 0xD9E, 0xDAD, 0xDB3, 0xDCC, 0xDD2, 0xDE1, 0xDFF DCW 0xE08, 0xE16, 0xE25, 0xE3B, 0xE44, 0xE5A, 0xE69, 0xE77, 0xE83, 0xE9D, 0xEAE, 0xEB0, 0xECF, 0xED1, 0xEE2, 0xEFC DCW 0xF02, 0xF1C, 0xF2F, 0xF31, 0xF4E, 0xF50, 0xF63, 0xF7D, 0xF89, 0xF97, 0xFA4, 0xFBA, 0xFC5, 0xFDB, 0xFE8, 0xFF6 DCW 0x1005, 0x101B, 0x1028, 0x1036, 0x1049, 0x1057, 0x1064, 0x107A, 0x108E, 0x1090, 0x10A3, 0x10BD, 0x10C2, 0x10DC, 0x10EF, 0x10F1 DCW 0x110F, 0x1111, 0x1122, 0x113C, 0x1143, 0x115D, 0x116E, 0x1170, 0x1184, 0x119A, 0x11A9, 0x11B7, 0x11C8, 0x11D6, 0x11E5, 0x11FB DCW 0x120C, 0x1212, 0x1221, 0x123F, 0x1240, 0x125E, 0x126D, 0x1273, 0x1287, 0x1299, 0x12AA, 0x12B4, 0x12CB, 0x12D5, 0x12E6, 0x12F8 DCW 0x1306, 0x1318, 0x132B, 0x1335, 0x134A, 0x1354, 0x1367, 0x1379, 0x138D, 0x1393, 0x13A0, 0x13BE, 0x13C1, 0x13DF, 0x13EC, 0x13F2 DCW 0x1402, 0x141C, 0x142F, 0x1431, 0x144E, 0x1450, 0x1463, 0x147D, 0x1489, 0x1497, 0x14A4, 0x14BA, 0x14C5, 0x14DB, 0x14E8, 0x14F6 DCW 0x1508, 0x1516, 0x1525, 0x153B, 0x1544, 0x155A, 0x1569, 0x1577, 0x1583, 0x159D, 0x15AE, 0x15B0, 0x15CF, 0x15D1, 0x15E2, 0x15FC DCW 0x160B, 0x1615, 0x1626, 0x1638, 0x1647, 0x1659, 0x166A, 0x1674, 0x1680, 0x169E, 0x16AD, 0x16B3, 0x16CC, 0x16D2, 0x16E1, 0x16FF DCW 0x1701, 0x171F, 0x172C, 0x1732, 0x174D, 0x1753, 0x1760, 0x177E, 0x178A, 0x1794, 0x17A7, 0x17B9, 0x17C6, 0x17D8, 0x17EB, 0x17F5 DCW 0x1803, 0x181D, 0x182E, 0x1830, 0x184F, 0x1851, 0x1862, 0x187C, 0x1888, 0x1896, 0x18A5, 0x18BB, 0x18C4, 0x18DA, 0x18E9, 0x18F7 DCW 0x1909, 0x1917, 0x1924, 0x193A, 0x1945, 0x195B, 0x1968, 0x1976, 0x1982, 0x199C, 0x19AF, 0x19B1, 0x19CE, 0x19D0, 0x19E3, 0x19FD DCW 0x1A0A, 0x1A14, 0x1A27, 0x1A39, 0x1A46, 0x1A58, 0x1A6B, 0x1A75, 0x1A81, 0x1A9F, 0x1AAC, 0x1AB2, 0x1ACD, 0x1AD3, 0x1AE0, 0x1AFE DCW 0x1B00, 0x1B1E, 0x1B2D, 0x1B33, 0x1B4C, 0x1B52, 0x1B61, 0x1B7F, 0x1B8B, 0x1B95, 0x1BA6, 0x1BB8, 0x1BC7, 0x1BD9, 0x1BEA, 0x1BF4 DCW 0x1C04, 0x1C1A, 0x1C29, 0x1C37, 0x1C48, 0x1C56, 0x1C65, 0x1C7B, 0x1C8F, 0x1C91, 0x1CA2, 0x1CBC, 0x1CC3, 0x1CDD, 0x1CEE, 0x1CF0 DCW 0x1D0E, 0x1D10, 0x1D23, 0x1D3D, 0x1D42, 0x1D5C, 0x1D6F, 0x1D71, 0x1D85, 0x1D9B, 0x1DA8, 0x1DB6, 0x1DC9, 0x1DD7, 0x1DE4, 0x1DFA DCW 0x1E0D, 0x1E13, 0x1E20, 0x1E3E, 0x1E41, 0x1E5F, 0x1E6C, 0x1E72, 0x1E86, 0x1E98, 0x1EAB, 0x1EB5, 0x1ECA, 0x1ED4, 0x1EE7, 0x1EF9 DCW 0x1F07, 0x1F19, 0x1F2A, 0x1F34, 0x1F4B, 0x1F55, 0x1F66, 0x1F78, 0x1F8C, 0x1F92, 0x1FA1, 0x1FBF, 0x1FC0, 0x1FDE, 0x1FED, 0x1FF3 DCW 0x2003, 0x201D, 0x202E, 0x2030, 0x204F, 0x2051, 0x2062, 0x207C, 0x2088, 0x2096, 0x20A5, 0x20BB, 0x20C4, 0x20DA, 0x20E9, 0x20F7 DCW 0x2109, 0x2117, 0x2124, 0x213A, 0x2145, 0x215B, 0x2168, 0x2176, 0x2182, 0x219C, 0x21AF, 0x21B1, 0x21CE, 0x21D0, 0x21E3, 0x21FD DCW 0x220A, 0x2214, 0x2227, 0x2239, 0x2246, 0x2258, 0x226B, 0x2275, 0x2281, 0x229F, 0x22AC, 0x22B2, 0x22CD, 0x22D3, 0x22E0, 0x22FE DCW 0x2300, 0x231E, 0x232D, 0x2333, 0x234C, 0x2352, 0x2361, 0x237F, 0x238B, 0x2395, 0x23A6, 0x23B8, 0x23C7, 0x23D9, 0x23EA, 0x23F4 DCW 0x2404, 0x241A, 0x2429, 0x2437, 0x2448, 0x2456, 0x2465, 0x247B, 0x248F, 0x2491, 0x24A2, 0x24BC, 0x24C3, 0x24DD, 0x24EE, 0x24F0 DCW 0x250E, 0x2510, 0x2523, 0x253D, 0x2542, 0x255C, 0x256F, 0x2571, 0x2585, 0x259B, 0x25A8, 0x25B6, 0x25C9, 0x25D7, 0x25E4, 0x25FA DCW 0x260D, 0x2613, 0x2620, 0x263E, 0x2641, 0x265F, 0x266C, 0x2672, 0x2686, 0x2698, 0x26AB, 0x26B5, 0x26CA, 0x26D4, 0x26E7, 0x26F9 DCW 0x2707, 0x2719, 0x272A, 0x2734, 0x274B, 0x2755, 0x2766, 0x2778, 0x278C, 0x2792, 0x27A1, 0x27BF, 0x27C0, 0x27DE, 0x27ED, 0x27F3 DCW 0x2805, 0x281B, 0x2828, 0x2836, 0x2849, 0x2857, 0x2864, 0x287A, 0x288E, 0x2890, 0x28A3, 0x28BD, 0x28C2, 0x28DC, 0x28EF, 0x28F1 DCW 0x290F, 0x2911, 0x2922, 0x293C, 0x2943, 0x295D, 0x296E, 0x2970, 0x2984, 0x299A, 0x29A9, 0x29B7, 0x29C8, 0x29D6, 0x29E5, 0x29FB DCW 0x2A0C, 0x2A12, 0x2A21, 0x2A3F, 0x2A40, 0x2A5E, 0x2A6D, 0x2A73, 0x2A87, 0x2A99, 0x2AAA, 0x2AB4, 0x2ACB, 0x2AD5, 0x2AE6, 0x2AF8 DCW 0x2B06, 0x2B18, 0x2B2B, 0x2B35, 0x2B4A, 0x2B54, 0x2B67, 0x2B79, 0x2B8D, 0x2B93, 0x2BA0, 0x2BBE, 0x2BC1, 0x2BDF, 0x2BEC, 0x2BF2 DCW 0x2C02, 0x2C1C, 0x2C2F, 0x2C31, 0x2C4E, 0x2C50, 0x2C63, 0x2C7D, 0x2C89, 0x2C97, 0x2CA4, 0x2CBA, 0x2CC5, 0x2CDB, 0x2CE8, 0x2CF6 DCW 0x2D08, 0x2D16, 0x2D25, 0x2D3B, 0x2D44, 0x2D5A, 0x2D69, 0x2D77, 0x2D83, 0x2D9D, 0x2DAE, 0x2DB0, 0x2DCF, 0x2DD1, 0x2DE2, 0x2DFC DCW 0x2E0B, 0x2E15, 0x2E26, 0x2E38, 0x2E47, 0x2E59, 0x2E6A, 0x2E74, 0x2E80, 0x2E9E, 0x2EAD, 0x2EB3, 0x2ECC, 0x2ED2, 0x2EE1, 0x2EFF DCW 0x2F01, 0x2F1F, 0x2F2C, 0x2F32, 0x2F4D, 0x2F53, 0x2F60, 0x2F7E, 0x2F8A, 0x2F94, 0x2FA7, 0x2FB9, 0x2FC6, 0x2FD8, 0x2FEB, 0x2FF5 DCW 0x3006, 0x3018, 0x302B, 0x3035, 0x304A, 0x3054, 0x3067, 0x3079, 0x308D, 0x3093, 0x30A0, 0x30BE, 0x30C1, 0x30DF, 0x30EC, 0x30F2 DCW 0x310C, 0x3112, 0x3121, 0x313F, 0x3140, 0x315E, 0x316D, 0x3173, 0x3187, 0x3199, 0x31AA, 0x31B4, 0x31CB, 0x31D5, 0x31E6, 0x31F8 DCW 0x320F, 0x3211, 0x3222, 0x323C, 0x3243, 0x325D, 0x326E, 0x3270, 0x3284, 0x329A, 0x32A9, 0x32B7, 0x32C8, 0x32D6, 0x32E5, 0x32FB DCW 0x3305, 0x331B, 0x3328, 0x3336, 0x3349, 0x3357, 0x3364, 0x337A, 0x338E, 0x3390, 0x33A3, 0x33BD, 0x33C2, 0x33DC, 0x33EF, 0x33F1 DCW 0x3401, 0x341F, 0x342C, 0x3432, 0x344D, 0x3453, 0x3460, 0x347E, 0x348A, 0x3494, 0x34A7, 0x34B9, 0x34C6, 0x34D8, 0x34EB, 0x34F5 DCW 0x350B, 0x3515, 0x3526, 0x3538, 0x3547, 0x3559, 0x356A, 0x3574, 0x3580, 0x359E, 0x35AD, 0x35B3, 0x35CC, 0x35D2, 0x35E1, 0x35FF DCW 0x3608, 0x3616, 0x3625, 0x363B, 0x3644, 0x365A, 0x3669, 0x3677, 0x3683, 0x369D, 0x36AE, 0x36B0, 0x36CF, 0x36D1, 0x36E2, 0x36FC DCW 0x3702, 0x371C, 0x372F, 0x3731, 0x374E, 0x3750, 0x3763, 0x377D, 0x3789, 0x3797, 0x37A4, 0x37BA, 0x37C5, 0x37DB, 0x37E8, 0x37F6 DCW 0x3800, 0x381E, 0x382D, 0x3833, 0x384C, 0x3852, 0x3861, 0x387F, 0x388B, 0x3895, 0x38A6, 0x38B8, 0x38C7, 0x38D9, 0x38EA, 0x38F4 DCW 0x390A, 0x3914, 0x3927, 0x3939, 0x3946, 0x3958, 0x396B, 0x3975, 0x3981, 0x399F, 0x39AC, 0x39B2, 0x39CD, 0x39D3, 0x39E0, 0x39FE DCW 0x3A09, 0x3A17, 0x3A24, 0x3A3A, 0x3A45, 0x3A5B, 0x3A68, 0x3A76, 0x3A82, 0x3A9C, 0x3AAF, 0x3AB1, 0x3ACE, 0x3AD0, 0x3AE3, 0x3AFD DCW 0x3B03, 0x3B1D, 0x3B2E, 0x3B30, 0x3B4F, 0x3B51, 0x3B62, 0x3B7C, 0x3B88, 0x3B96, 0x3BA5, 0x3BBB, 0x3BC4, 0x3BDA, 0x3BE9, 0x3BF7 DCW 0x3C07, 0x3C19, 0x3C2A, 0x3C34, 0x3C4B, 0x3C55, 0x3C66, 0x3C78, 0x3C8C, 0x3C92, 0x3CA1, 0x3CBF, 0x3CC0, 0x3CDE, 0x3CED, 0x3CF3 DCW 0x3D0D, 0x3D13, 0x3D20, 0x3D3E, 0x3D41, 0x3D5F, 0x3D6C, 0x3D72, 0x3D86, 0x3D98, 0x3DAB, 0x3DB5, 0x3DCA, 0x3DD4, 0x3DE7, 0x3DF9 DCW 0x3E0E, 0x3E10, 0x3E23, 0x3E3D, 0x3E42, 0x3E5C, 0x3E6F, 0x3E71, 0x3E85, 0x3E9B, 0x3EA8, 0x3EB6, 0x3EC9, 0x3ED7, 0x3EE4, 0x3EFA DCW 0x3F04, 0x3F1A, 0x3F29, 0x3F37, 0x3F48, 0x3F56, 0x3F65, 0x3F7B, 0x3F8F, 0x3F91, 0x3FA2, 0x3FBC, 0x3FC3, 0x3FDD, 0x3FEE, 0x3FF0

индекс записи вычисляем как idx = (cmd << 4) + (7 && cmd) + (cmd >> 3)
cmd — 6-битный, старший бит соотв определяет младшая или старшая часть (как определил afan)

Но на самом деле структура команды чуть более сложная, так как протокол предусматривает еще некий pin-код для протокола, который видимо в данной игрушке не используется и равен 0
0
afan, #
Интересно, т.е. все же используется некая таблица, а не простое вычисление. Это похоже на предварительно рассчитанную табличку какого-то CRC?

Интересно, что в итоге моя табличка, содержащая готовые 64 байта для всех комбинаций, получилась гораздо проще, чем код из библиотеки. )
0
Vilko, #
Возможно, табличка и предрассчитанная, но вот по какому алгоритму — из библиотеки не узнать…
+1
Vilko, #
Кстати, в твоей табличке, похоже, ошибка на записи
'2300', # 19 + 32
должно быть 2100
0
afan, #
Надо проверить, спасибо за информацию!
0
Vilko, #
Сорри, формула индекса конечно же
idx = (cmd << 4) + (7 & cmd) + (cmd >> 3)
0
readmaxym, #
да, look up там есть…

вообщем — там много в таблицах, как минимум Sin/Phase Coef рассчитываються так же,

понятно, скорость…
0
afan, #
Да, забыл спросить: а этот PIN-код как-то влияет на первые два байта команды? У меня ощущение, что PIN-код — это и есть то самый третий байт, который по умолчанию просто равен 1032.
0
Vilko, #
Пинкод — да, влияет на все 3 байта. не стал разбиратся как именно, за ненадобностью. могу выложить кусок кода.
0
afan, #
Буду признателен (только в личку, наверно).
+4
kai, #
Вот так случайно и найдут команду — «убить всех человеков!»
–5
dmiceman, #
del
+3
aivs, #
А ты мужик дотошный! Молодца!
0
simbiod, #
Отличная статья! Спасибо!
+12
Agent_Smith, #
Я думал эти игрушки еще лет 10 назад из моды вышли.
0
afan, #
Собственно да, первые Furby появились еще в конце 90-х. А тут они совсем недавно перезапустили игрушку, сделав ее более интересной и интеллектуальной (если это слово к Furby вообще применимо). Ну и привязанной к мобильному приложению — куда теперь без этого.
+1
icoz, #
Только играются с ними теперь папы.
0
datacompboy, #
Так и что, ответы-то нашли? На самом интересном статью оборвали :)
0
afan, #
Ну почему же. Все, что найдено, как раз задокументировано в исходниках. Там же указано, какие команды официальные (доступны в iOS-приложении), а какие найдены самостоятельно.
+1
Ariman, #
А аудиокоманду не слышно? Все-таки там не ультразвук, 16КГц еще можно услышать.
+1
afan, #
Если включить на большую громкость, то писк и давление в ушах будет, и довольно неприятное. Но на нормальной громкости (и на той громкости, с которой общается Furby), команду не слышно. Помимо всего прочего, Furby обычно передает команду вместе со слышимым звуком, так что высокочастотная компонента полностью скрывается. Только иногда Furby в паузах издает чуть слышимые щелчки, посылая команды 706 и 707. Как я понимаю, так он ищет собеседников (если поставить несколько Furby рядом, они должны найти друг друга и начать «разговор»). Почему команд две — этого я пока не знаю.
0
Ariman, #
Ясно.
P.S.
Это правильнее назвать «частотная манипуляция», а не «модуляция», потому что сдвиг дискретный.
0
afan, #
Ясно, учту.
0
icoz, #
SYN и SYN+ACK?
0
afan, #
Если рассматривать эти команды в таких терминах, то SYN+ACK — это вроде как ответ на SYN. А тут обе команды посылает сам Furby.

Думаю, что пролить свет на этот вопрос может только запись «разговора» двух Furby.
+2
icoz, #
Уже дважды интересно. А если их соберется больше двух?
Это уже будет считаться митингом?
А если серьезно, то думаю, что ещё нераспознанные команды имеют отношение как раз к вот такому внутривидовому общению.
0
grender, #
Очень круто. У вас был опыт разборов аналоговых сигналов до этого?
+2
afan, #
Нет — это первый опыт, тем он и был интересен.
+5
svavan, #
Отличная статья. Читается как интересный роман. Была мысль когда-то сделать простую передачу данных через звук, так сказать бюджетный беспроводной интерфейс. Но информации тогда не нашел об удачной реализации.
+6
janatem, #
Штирлицу респект и уважуха! Прям как детектив читается.
–6
Flammar, #
Только мне по первости показалось «история реверс-инжиниринга одного пушистого толстого северного лиса»?
0
Iktash, #
Тайное знание о секретных командах выставлено на публику.
+2
LFK, #
А народ Путину говорит, что в НГ праздники ничем кроме алкоголя занять себя не может :)) Хорошее времяпрепровождение у Вас.
0
tyomitch, #
Третий и заключительный бит посылки всегда равен 1032.
Наверное, байт?
0
afan, #
Поправил, спасибо.
+1
Haoose, #
А вот как зверек выглядит изнутри (без шерсти)
Видео
+2
stek, #
Год назад мы работали над похожим протоколом и несколькими iOS приложениями для вот таких штуковин:

1. store.apple.com/us/product/H7644VC/A/duo-pop-for-ipad
2. store.apple.com/us/product/H7645LL/A/duo-plink-for-ipad

План заключался в создании аудио протокола работающего на частотах близких к 20кГц для того, чтобы человеческое ухо его не воспринимало и не испытывало никакого дискомфорта при работе с данными железяками (а ориентированы они были на детей, поэтому это было важно).

Первоначальный план провалился, когда оказалось, что микрофон в iPad1 очень плохо воспринимал все что было выше 18-19 кГц. А у «улучшенного» iPad2 микрофон оказался еще хуже.

В результате сейчас детишки, которые играют с этими девайсами слышат небольшой треск, но жить с ним можно, так как он действительно ели различим.

Так вот: самый частый и самый первый вопрос от всех кому я рассказывал эту историю: «А нахрена?». «Зачем мы это всё делали, когда есть Bluetooth?»

Ответ такой: Так дешевле. При производстве таких девайсов в больших масштабах считается каждый цент. А для того, чтобы использовать Bluethooth, нужно платить какую-то пошлину (по-моему Apple'у, но я точно не помню) в размере $2-3 за каждый девайс, что есть очень дорого для больших масштабов.

Вот пример приложения: bit.ly/VfOWzD
+1
afan, #
Разумеется — и дешевле (а в Furby много всего напихано для его цены) и спаривать не надо. Для устройств, которые нужно пользовать в непосредственной близости от экрана устройства — самое то!

Кстати, заметьте, что в формируемом аудио частота звука между «нотами» а также перед и после посылкой меняется плавно. Т.е. все сделано с расчетом на то, чтобы не было резких «биений» в FFT (а значит, как я понимаю, и перепадов давления, которые слышатся как щелчки). Я сначала тоже сделал по простому — просто «ноты» без плавных переходов. И на спектрограмме на границах нот были ужасные красные полосы, а при проигрывании аудио был слышен отчетливый треск. Потом сделал все красиво, почти как на оригинальной картинке, и щелчки прекратились.
0
NetBUG, #
Не единственное применение ультразвуку для «общения» устройств — кстати, в этой работе тоже используют частоты чуть выше 16 кГц (логично, ибо частота дискретизации — 44,1, теорема Котельникова и всё такое).
Сама работа — www.cs.ust.hk/~qianzh/FYTGS5100/spr2013/references/4-Mobicom12.pdf — авторы пытались сделать улучшение для Wi-Fi-фингерпринтинговой локализации с помощью соседних смартфонов. Вроде даже заработало.
0
unwrecker, #
У меня от писков на таких частотах голова болит, ну и вообще противно (до 18КГц слышу). У детей слух лучше. Так что действительно «А нахрена?».
0
AlexPancho, #
а кто-то напомнит как назывался мультсериал где были очень похожие зверьки, и какой-то зеленый дядька (похожий на Ковакса из Майзи) всё пытлался их захватить? (в Украине шел на УТ-1 в моем детстве )
0
AlexPancho, #
сам спросил сам ответил:
вот оказывается, что память делает если ее напрячь…
Приключения Тедди Ракспина ( В Росии шел по СТС,1996)
0
Semisonic, #
Поначалу оказалось, что в соседних командах числа иногда «прыгают», т.е. идут не так, как хотелось бы при последовательном инкрементировании чисел. После некоторого анализа стало понятно, что «ноты» надо нумеровать так, как на рисунке ниже

Не могли бы вы подробнее о том, что именно навело вас на мысль об ином способе нумерации? Просто исходя из описанных вами шагов по анализу сигналов не понятно, где именно вы внутри кода, передаваемого сигналами, ожидали увидеть последовательно увеличивающиеся числа. А без понимания этого шага весь процесс декодирования сигналов кажется неполным, и от этого свербящее чувство, что усвоил урок не до конца и, окажись ты в аналогичной ситуации, не факт что справился бы…

Кстати, о контрольных суммах: не проще ли было бы тупым перебором нагенерить вариантов команд, а потом скормить их этому зверю и посмотреть, на что он среагирует? Понятно что это не очень красиво, но сэкономило бы возню с декомпиляцией Android-приложения и сопутствующими трудностями.

А вообще, подобные подвиги на почве энтузиазма вызывают искреннее восхищение. Завидую вашей находчивости и мотивации.
+1
afan, #
Брал WAV-файлы для последовательно идущих команд (например, 352, 353, 354, 355, ...), по спектрограмме (по «нотам») получал код в четверичной системе и смотрел, как изменяются числа от команды к команде. Закономерность была вида 0, 1, 3, 2 вместо ожидаемой 0, 1, 2, 3, что натолкнуло на мысль, что 3 и 2 надо поменять местами. Картинка и сложилась. Выборочная проверка других случайных команд (все 79 я, разумеется, не проверял) показала, что теория работает.

Кстати, о контрольных суммах: не проще ли было бы тупым перебором нагенерить вариантов команд, а потом скормить их этому зверю и посмотреть, на что он среагирует?
Это для каждой команды дает 256 вариантов. Занятие очень утомительное, особенно когда нет гарантии, что даже на один из этих вариантов Furby как-то отреагирует. Сами команды отправляются небыстро, между ними нужны паузы, Furby не все их услышит, если будет в это время что-то делать свое и т.д. Это превратило бы увлекательное занятие в пытку.
0
Semisonic, #
Я наверное яростно туплю, но из вашего рассказа не совсем понятно, есть ли вообще какая-то корреляция между номером команды (именем WAV-файла) и кодом, зашифрованном в её спектрограмме. Или вы хотите сказать, что собственно в тех десяти битах (по 5 в каждой из двух «посылок») и закодирован номер команды, соответствующий номеру WAV-файла?
0
afan, #
в тех десяти битах (по 5 в каждой из двух «посылок») и закодирован номер команды, соответствующий номеру WAV-файла?


Именно так и оказалось, да.
0
Semisonic, #
Теперь всё встало на свои места, спасибо за отдельное пояснение =).
+2
dug, #
Наконец то, хабр — тот!
+4
BelBES, #
Ну как всегда: лучший подарок для ребенка тот подарок, который папа разберет первым)
+2
ltwood, #
Oo-tah-toh-toh. Kah way-loh.


Ми хим ен тоу кан де лаш. Кан тои — кан тах. Кан де лаш, оз па.

Уж извините, почти прямая асстоциация с Кингом.
0
darksimpson, #
Если у меня правильная информация, то основой Furby является RSC-4128. Самой игрушки у меня нет, увы, но расковырял и посмотрел бы, так это или нет, с удовольствием. У Sensory есть как раз технология передачи аудио-токенов, SonicNet. Но, судя по описанному в статье, это немного другое. Вообще, если там действительно стоит 4128, то я достаточно подробно описал его на примере EasyVR вот тут. И там же выложил весь необходимый для создания своих собственных приложений софт. Так что, при удачном стечении обстоятельств, можно было бы для Furby и собственный фирмварь написать, чтобы использовать его в целях разных уведомлений, как предложил автор.
0
afan, #
Этот микропроцессор был в одной из старых моделей. Что в новой — неизвестно. К сожалению, игрушка не поддается аккуратному раздербаниванию, обратно ее собрать «как было» не получится, поэтому я ее не разбирал. Вот здесь виден процесс разборки, но микросхем на фото нет.
0
darksimpson, #
Понял, значит у меня устаревшая информация. Жаль :)
0
afan, #
Вот тут нашел картинку где видны его запчасти, включая основную плату.
0
afan, #
О, и вот тут еще кое-что покрупнее.
0
darksimpson, #
Спасибо. Правда, все равно не понятно на чем он сделан, просто залитые кристаллы :(
0
Razbezhkin, #
А набор wav файлов где можно раздобыть?
0
samodum, #
Можете поделиться WAV-файлами?
Хочу проверить их на Furby Boom. По крайней мере сигналы для сна и еды подходят от старой модели (обычного Furby)

Только зарегистрированные пользователи могут оставлять комментарии.
Войдите, пожалуйста.