Прикалывался над детской камерой. Решил написать что-то вроде статьи про свои эксперименты.
0. Обзор камеры
Как называть эту камеру я не знаю. Это буквально НОУНЕЙМ устройство. Никаких логотипов, надписей и проч опознавательных знаков просто нет. На маркетплейсах они продаются под тысячей разных брендов и названий. Общее только то, что все они позиционируются как камера для ребенка.

Кроме того, все подобные камеры немного отличаются друг от друга. Для своих экспериментов я приобрел аж три таких в трех разных местах: на avito, ozon и aliexpress. Все три камеры были хоть и похожи друг на друга, но имели некоторые странные отличия. Например, на одном из устройств не обнаружилось фронтальной камеры. На другом устройстве пластик корпуса заметно отличался от остальных камер. По софту так же были отличия. Где-то были небольшие лаги, ощущалась общая тормознутость. Где-то вместо самописных игр есть эмулятор NES со странным набором игр. Интерфейс вроде и одинаков везде, но некоторые картинки немного отличаются и т.д.
Из трех я выбрал наиболее приятную для использования камеру, которая приехала мне с озона.
После включения, нас встречает следующее меню:

Нам доступна съемка фото, видео, просмотр отснятого материала, настройки, игры, прослушивание музыки.
При съемке фото на изображение можно наложить забавные детские рамки.

Игры представляют собой набор ROMов от NES со срезанными копирайтами, видимо, чтоб маркетплейсы не отклоняли устройства из-за незаконного распространения пиратского контента. Сам набор игр достаточно странный. Из интересного есть только классический тетрис, остальные какие-то не особо интересные ноунейм игры.

Можно прослушивать музыку с флешки. Для этого файлы нужно разместить в папке mp3.

1. Разбираем устройство
ПРЕДУПРЕЖДЕНИЕ: ЕСЛИ КТО-ТО ЗАХОЧЕТ РАЗОБРАТЬ ПОДОБНУЮ КАМЕРУ, ПОЖАЛУЙСТА, БУДЬТЕ МАКСИМАЛЬНО ОСТОРОЖНЫ. ТУДА СТАВЯТ МАКСИМАЛЬНО ОТВРАТИТЕЛЬНЫЕ АККУМУЛЯТОРЫ, КОТОРЫЕ ИМЕЮТ СВОЙСТВО ВЫСАЖИВАТЬСЯ В 0, НЕСМОТРЯ НА ЗАЩИТУ НА БАНКЕ, А ТАК ЖЕ ВЗДУВАТЬСЯ! ИЗ ТРЕХ РАЗОБРАННЫЙ МНОЙ КАМЕР, В ДВУХ ИЗ НИХ БЫЛИ ВЗДУТЫЕ АККУМУЛЯТОРЫ, А В ТРЕТЬЕЙ ПРОСТО МЕРТВАЯ.
Разобрать камеру не так сложно: необходимо открутить 4 винта с лицевой стороны корпуса. Далее откручиваем модули камер, и главную плату.
С передней стороны плата выглядит так.
Видим разъем для micro-SD карты (1), кнопку спуска затвора (2), кнопочку сброса устройства (3), аж две контактные площади для батарейки (4), 24-пиновый коннектор камеры (4), дублирующиеся контактные площадки для динамика (5), небольшой микрофон (6), 22-пиновый MIPI коннектор для LCD (7) и кварц (8). Из интересного на шелкографии можно заметить серийный номер и дату изготовления платы. Забавно, что камера была куплена недавно, а дата производства платы 2020. Тепепь понятно, почему батарейка была такой вздутой. Видимо, когда-то было напечатано огромное количество таких плат, что их до сих пор продают. Поиск серийника в интернете, очевидно, ни к чему не привел.
Вид платы сзади.
На обратной стороне, помимо mini-USB (1), кнопок (2), светодиодов (3), коннектора для камеры(4), обнаружилось два интересных чипа. Первый чип (5) - центральный процессор в корпусе LQFP64 с еле различимой гравировкой. При использовании небольшого увеличительного стекла и очень яркой подсветке лампы все-таки удалось различить надпись, однако она не похожа на название, скорее всего это какой-то специфический серийный номер.
Рядом с микроконтроллером располагается SPI-флешка (6) YC25Q32W1 в корпусе SOIC8, аналог чипа производства Winbond W25Q32, с объемом памяти равным 4МБ. В этой памяти, скорее всего, вместе с отснятыми фотографиями находятся и те самые всратые детские картинки и звуки, которые мы видим и слышим в интерфейсе камеры.
2. Подключаем к ПК
Для начала попробуем подключить камеру к компьютеру. lsusb выдает следующее.Bus 001 Device 011: ID 1b3f:2002 Generalplus Technology Inc. 808 Camera
Поиском в интернете Generalplus Technology Inc. нахожу сайт предполагаемого производителя MCU данной камеры. При попытке зайти на сайт вижу это:
ОКЕЙ. Просто так зайти на сайт не получается. Даже используя три запрещенные буквы, соединение все равно сбрасывается. Решил, что вернусь к этому чуть позже, тем более пока никакой полезной информации о типе или серии микроконтроллера найти еще не получилось.
3. Анализируем дамп флешки
Следующим шагом попробуем считать программатором прошивку с SPI-флешки.
Для этого у меня есть простенький программатор на микросхеме CH341, который позволяет читать и записывать микросхемы памяти по SPI или I2C.
Цепляемся прищепкой к контактам памяти и делаем дамп.

flashrom -p ch341a_spi -r firmware.bin
Первое, что нужно проверить, зашифрованы ли данные на флешке или нет. Самый простейший способ это проверить - просто получить все читаемые строки из файла. Если строки будут иметь осмысленный вид, то данные точно не зашифрованы.
$ strings firmware.bin -n 10
GP DV BootLoader v2.2 Entry @ %d MHz
GPDV chip detect
TA GPDV 64Pin chip detect
UNKNOWN:%d
GPNVBtLdr Recover well done
BtLdr Read well
GPNVNV checksum:0x%08x
Btldr checksum:0x%08x
BtLdr NV-Source CheckSum:0x%08x error, Recover it back
NV CLK: %d MHz
APP Hdr Parse fail
BootLoader PC Jump to 0x%08x
...
Интересно… Изначально я предполагал, что на флешке хранятся только ресурсные файлы и записанные фотографии, а сама прошивка располагается в ПЗУ микроконтроллера, но дамп SPI-флешки содержит очень много читаемых строк, которые точно являются частью отладочного вывода прошивки. После беглого осмотра выхлопа, были найдены довольно интересные строки:
...
TA GPDV 64Pin chip detect
...
GP$303 Generalplus AVI Parser 2010.3.12 by Homer Lu
...
Первая строка - часть лога инициализации процессора, так как тот как раз 64-пиновый. Она содержит непонятную пока комбинацию символов GPDV, что очень похоже на название серии или модель используемого микроконтроллера.
Вторая строчка выглядит как копирайт библиотеки для парсинга AVI файлов, разработанная аж в 2010 году в компании GeneralPlus. Это подтвержает, что производитель процессора - Generalplus.
Из прочего интересного нашел что-то подозрительно напоминающее закладку для обновления прошивки с sd-карты:
...
C:\gp_cardvr_upgrade.bin
...
Чуть позже мы проверим это.
Попробуем посмотреть, какие данные можно найти на этой флешке при помощи утилиты binwalk. Binwalk — это открытый инструмент, позволяющий вести поиск всех компонентов в образе прошивки, сопоставляя их с магическими байтами, кодирующими разные типы файлов.
$ binwalk firmware.bin
/home/kivyfreakt/Documents/camera/firmware.bin
--------------------------------------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------------------------------------
652800 0x9F600 JPEG image, total size: 44046 bytes
1190088 0x1228C8 JPEG image, total size: 429989 bytes
1623552 0x18C600 JPEG image, total size: 18541 bytes
1702400 0x19FA00 JPEG image, total size: 58036 bytes
1793634 0x1B5E62 JPEG image, total size: 114983 bytes
1912832 0x1D3000 JPEG image, total size: 204527 bytes
--------------------------------------------------------------------------------------------------------------
Analyzed 1 file for 85 file signatures (187 magic patterns) in 48.0 milliseconds
Негусто, всего-то 5 картинок. Даже с ключом -a больше ничего достать не получается. Попробуем использовать утилиту foremost, изначально предназначенную для восстановления удаленных файлов, которая позволяет обнаружить файлы на основе их магических байт и заголовков.
$ foremost -v firmware.bin
Foremost version 1.5.7 by Jesse Kornblum, Kris Kendall, and Nick Mikus
Audit File
Foremost started at Sun Oct 19 15:30:36 2025
Invocation: foremost -v firmware.bin
Output directory: /home/kivyfreakt/Documents/camera/output
Configuration file: /etc/foremost.conf
Processing: firmware.bin
|------------------------------------------------------------------
File: firmware.bin
Start: Sun Oct 19 15:30:36 2025
Length: 4 MB (4194304 bytes)
Num Name (bs=512) Size File Offset Comment
0: 00001275.jpg 29 KB 652800
1: 00002324.jpg 15 KB 1190088
2: 00002355.jpg 18 KB 1206174
3: 00002393.jpg 25 KB 1225487
4: 00002444.jpg 17 KB 1251814
5: 00002480.jpg 12 KB 1270145
6: 00002506.jpg 15 KB 1283393
7: 00002536.jpg 20 KB 1298939
8: 00002578.jpg 15 KB 1320055
9: 00002608.jpg 3 KB 1335569
10: 00002616.jpg 3 KB 1339416
11: 00002623.jpg 25 KB 1343136
12: 00002673.jpg 19 KB 1368765
13: 00002711.jpg 10 KB 1388288
14: 00002731.jpg 20 KB 1398781
15: 00002772.jpg 10 KB 1419613
16: 00002794.jpg 14 KB 1430733
17: 00002823.jpg 5 KB 1445473
18: 00002833.jpg 12 KB 1450900
19: 00002858.jpg 15 KB 1463648
20: 00002890.jpg 14 KB 1479735
21: 00002919.jpg 20 KB 1494612
22: 00002960.jpg 15 KB 1515964
23: 00002991.jpg 2 KB 1531490
24: 00002996.jpg 3 KB 1534418
25: 00003004.jpg 3 KB 1538466
26: 00003012.jpg 6 KB 1542502
27: 00003025.jpg 5 KB 1549196
28: 00003036.jpg 3 KB 1554589
29: 00003079.jpg 24 KB 1576448
30: 00003128.jpg 18 KB 1601536
31: 00003171.jpg 18 KB 1623552
32: 00003325.jpg 14 KB 1702400
33: 00003503.jpg 2 KB 1793634
34: 00003508.jpg 3 KB 1796562
35: 00003516.jpg 3 KB 1800610
36: 00003524.jpg 6 KB 1804646
37: 00003537.jpg 5 KB 1811340
38: 00003548.jpg 3 KB 1816733
39: 00003642.jpg 27 KB 1864704
40: 00003736.jpg 26 KB 1912832
41: 00001176.wav 6 KB 602112
42: 00001189.wav 13 KB 608768
43: 00001224.wav 6 KB 626688
44: 00001242.wav 11 KB 635904
45: 00001266.wav 4 KB 648192
46: 00001803.wav 82 KB 923136
47: 00001968.wav 8 KB 1007616
48: 00003228.wav 12 KB 1652736
49: 00003253.wav 25 KB 1665536
*|
Finish: Sun Oct 19 15:30:36 2025
50 FILES EXTRACTED
jpg:= 41
rif:= 9
------------------------------------------------------------------
Foremost finished at Sun Oct 19 15:30:36 2025
Получилось достать аж в 10 раз больше файлов, большинство из них - это картинки, но есть и немного системных звуков. Большинство изображений - это рамки, которые накладываются поверх изображения.

Судя по картинке, при помощи черного цвета в прошивке реализуется базовая прозрачность.
Так же foremost нашел некоторые фоновые картинки, заставки включения и выключения.
Еще в папке обнаружились картинки, которые при использовании камеры ни разу мне не встречались. Более того, внимательно перепроверив все пункты меню в камере, я так и не смог никаким образом получить эти изображения на экране. Либо это какие-либо незадокументированные пасхалочки, либо мусор от старых версий прошивок, который просто забыли убрать.


4. Первые эксперименты
Утилита foremost позволяет узнать начальные адреса конкретных файлов и их точный размер. Если мы создадим другой файл, идентичный по размеру и способу кодирования данных, и запишем его биты с начального адреса оригинального файла, то мы сможем подменить один файл другим.
В качестве примера решил попробовать заменить картинку выключения устройства. Изначально она выглядит таким образом:
С помощью утилиты exiftool прочитаем метаданные этой картинки.
$ exiftool 00003171.jpg
ExifTool Version Number : 13.36
File Name : 00003171.jpg
Directory : .
File Size : 22 kB
File Modification Date/Time : 2025:10:04 13:55:29+03:00
File Access Date/Time : 2025:11:25 02:09:48+03:00
File Inode Change Date/Time : 2025:10:12 21:57:38+03:00
File Permissions : -rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : inches
X Resolution : 300
Y Resolution : 300
Image Width : 320
Image Height : 240
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 320x240
Megapixels : 0.077
Картинка имеет размеры 320x240 и использует Baseline DCT.
В качестве подопытной картинки взял случайно попавшееся изображение из папки Pictures. Ей оказалась:

Повезло, что эта картинка тоже сжата при помощи Baseline DCT:
$ exiftool images.jpeg
ExifTool Version Number : 13.36
File Name : images.jpeg
Directory : .
File Size : 7.5 kB
File Modification Date/Time : 2025:11:25 02:37:32+03:00
File Access Date/Time : 2025:11:25 02:42:34+03:00
File Inode Change Date/Time : 2025:11:25 02:37:32+03:00
File Permissions : -rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : inches
X Resolution : 300
Y Resolution : 300
Image Width : 299
Image Height : 168
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 299x168
Megapixels : 0.050
Поменяем размерность изображения на необходимую и для надежности скопируем все метаданные с исходной картинки.
$ magick ~/Pictures/images.jpeg -resize 320x240\! out.jpeg
$ exiftool -tagsFromFile 00003171.jpg -all:all out.jpeg
1 image files updated
Новый файл получился меньшего размера, чем оригинальный. Дополним его нулями.
$ wc -c 00003171.jpg out.jpeg
18541 00003171.jpg
9993 out.jpeg
28534 total
$ truncate -s 18541 out.jpeg
Перезапишем оригинальный файл в прошивке при помощи утилитыdd. Файл с обновленной версией прошивки назовем gp_cardvr_upgrade.bin, чтоб проверить возможную закладку с обновлением прошивки через sd-карту.
$ cp firmware.bin gp_cardvr_upgrade.bin
$ dd if=out.jpeg of=gp_cardvr_upgrade.bin bs=1 seek=1623552 conv=notrunc
18541+0 records in
18541+0 records out
18541 bytes (19 kB, 18 KiB) copied, 0.0300031 s, 618 kB/s
Загрузив файл на флешку и вставив ее в камеру, увидел следующий экран.

Действительно, в прошивке камеры есть функция обновления через sd-карту. Это очень упросит жизнь, так как не придется каждый раз подцепляться к SPI-флешке, чтоб протестировать очередное изменение.
После обновления, пробуем отключить камеру и видим ту самую картинку на заставке выключения. Кайф!

Значит, на устройстве не реализовано никакой проверки целостности прошивки и можно менять содержимое как заблагорассудится.
5. Пробуем найти больше информации
Перед тем, как погружаться глубже, необходимо собрать какую-нибудь полезную информацию, например, даташит на процессор, средства разработки, BSDL файлы для граничного сканирования через JTAG и проч. Обладая этой информацией, спектр доступных к реализации атак на устройство значительно расширяется.
Во время анализа строк в прошивке, были обнаружены интересные зацепки. Попробуем начать с них.
До этого у меня не получилось попасть на сайт компании производителя микроконтроллера камеры - Generalplus. Поискав немного информации в гугле, нашел интересный пост на реддите, в котором упоминалась аналогичная проблема с доступом к сайту. Почитав ответы, появилась мысль попробовать зайти на сайт с китайского айпишника, может во всем виновата великая китайская стена интернет-цензуры (ну или кривые руки сисадмина). Нахожу первый попавшийся рабочий китайский прокси и снова пытаюсь зайти на сайт.
И на этот раз получилось! Более того, после небольшого серфинга по сайту в списке выпускаемых ими Multimedia Processors даже нашлась необходимая серия GPDV с единственным доступным в списке контроллером.
Однако счастье продлилось не долго, перейдя на страницу сразу же обнаружилось:

Да. На странице нет ни то что даташита, а даже какого-либо внятного описания. Причем, это чуть ли не единственный процессор с таким скудным наполнением страницы, в остальных есть хотя бы какие-то подробности.
Грустненько, но не отчаиваемся. На соседней вкладке есть ссылка на SDK для ARM, может оттуда можно будет извлечь какую-нибудь полезную информацию. Но как минимум уже можно зафиксировать, что архитектура микроконтроллера - ARM. Пробуем скачать архив с сайте. Из-за плохого интернета и отвратительного прокси скорость загрузки была жутко медленной, так что пришлось ожидать скачивания примерно часа три, если не больше.
Пока качается файл, решил поискать что-нибудь в интернете по запросу GPDV6624D. При помощи DuckDuckGo смог найти сайт с распиновкой процессора.
Попробовал потыкаться в пины GND, 5V_BATN, VCC_3.3, VCC_2.8 при помощи мультиметра. Оказалось, что эти реальные пины совпадают с теми, что изображены на картинке. Так что я сделал вывод, что скорее всего, распиновка верная. Из интересного тут можно определить JTAG, однако BSDL файлов на этот процессор в открытом доступе, естественно, не обнаружилось. Да и не исключено, что JTAG отлючен на физическом уровне.
Наконец скачав и разархивировав файл, пробуем установить средства для разработки. Оказалось, это немного модифицированный китайцами Keil.

Пробуем создать новый проект и…
Необходимого микроконтроллера просто нет в списке. ПРОСТО ПУШЕЧКА. Впустую потратил несколько часов своей жизни…
6. Погружаемся глубже
Печально, что никакой информации о процессоре, кроме общей архитектуры, мы так и не узнали. Но это не мешает загрузить образ прошивки в IDA и попробовать поковыраться в нем.
Создаем новый проект, в качестве архитектуры выбираем ARM Little-Endian (практически стопроцентная вероятность того, что это правильный выбор). Так как, скорее всего, это крайне бюджетный ARM процессор, то можно вырубить инструкции для аппаратного сопроцессора для ускорения операций с плавающей точкой и SIMD инструкции. В остальном догадок больше нет, поэтому оставим по дефолту.
После загрузки прошивки в IDA, первым делом необходимо найти простейшие функции: функции для работы со строками, памятью, ввод-вывод и тд. Это очень сильно поможет при дальнейшем анализе. Найти такие функции довольно просто, если иметь базовое представление о их сигнатурах.
Следующим шагом можно попробовать отыскать точку входа в программу. Для этого перемещаемся на нулевой адрес, где в ARM процессорах должна храниться таблица векторов прерываний.

Однако, мы видим, что в самом начале файла располагаются какие-то данные и нули. Первые 4 бита образуют строку GPNV. Расшифровал это как General Plus Non-Volatile. Скорее всего часть флешки, которая используется как энергонезависимая память, в которой хранятся важные для прошивки данные, которые должны сохраняться устройством после отключения питания.
Блок данных заканчивается на адресе 0x200. Оттуда начинается таблица векторов прерываний. В таблице векторов ARM вектор сброса (reset vector) обычно располагается первым. При запуске процессора он начинает выполнение с адреса, указанного в векторе сброса.
Проанализировав код, можно найти вызов главной функции и перейти к ней.
Эта функция представляет собой реализацию простого Bootloader. Он ответственен за базовую инициализацию перефирии, поиск основного приложения/ОС во flash, обновление прошивки и проч.
Проанализировав фунции, расположенные рядом с bootloader-ом, нашел довольно много интересного, например, ту самую закладку с обновлением устройства через SD-карту, которой мц уже смогли воспользоваться.
Попробуем найти точку входа в операционную систему. К слову, тут действительно используется операционная система реального времени uC/OS-II. Это можно было понять по специфическим строкам, которые используются в прошивке:
Пролистав чуть ниже бутлоадера была найдена секция данных по адресу 0x2C00, начинающаяся со строки GPAP. Расшифровал это как General Plus App Point.

Ниже располагается область памяти с большим количеством нулей. Возможно, это какая-то память приложения, так как есть DATA XREF в эту область памяти.
После нулей начинается уже код операционной системы и пользовательского приложения. Были обраружены функции инициализации операционной системы, функции задач операционной системы, механизмы синхронизации и проч.
В прошивке есть еще одна секция - секция с ресурсами. Она начинается по адресу 0x8E000 с символов GP.

В целом, нашел еще много интересных функций, но писать обо всех них не имеет смысла.
7. Издеваемся над камерой
Так как никакой документации по устройству и процессору попросту нет, то понять, какие функции с какой переферией работают практически невозможно (либо придется красноглазить слишком долго). Отсуствие понимания работы с переферией лишает практически всех интересных хаков прошивки. (либо я не смог своей тупой головой придумать что-то интересное)
В общем, решил я отложить идею пропатчить прошивку так, чтоб запустить какой-нибудь интересный кастомный код. Возможно, если мне хватит интереса, то я еще вернусь к этой идее. А пока я решил, что можно было бы попробовать написать патчер для изменения ресурсов в прошивке. Было бы интересно поменять стандартные детские иконки, картинки и рамки на что-то более интересное.
Чтоб реализовать это, я решил проанализировать секцию с ресурсными файлами.
7.1 Анализ структуры файловой системы
С адреса 0x8E000 располагаются файлы, используемые устройством. Если прочитать первые 1024 байта этого раздела, то помимо нулей, можно обнаружить вполне читаемые и понятные названия файлов, рядом с которыми находится один или несколько байт данных. Это очень напоминает таблицу файловой системы. В первых 24 байтах, скорее всего, располагается какая-то служебная информация о файловой системе.
Первые два байта заголовка файловой системы - GP. Стандартный заголовок для всех разделов, которые были в прошивке до этого.
Третий байт 0x1C = 28. Если посчитать количество строк, в которых написаны названия файлов, то это число совпадет со значением из третьего байта. Делаем вывод, что этот байт означает количество доступных файлов.
Далее идут байты 0x00 0x02 0x00 0x02. Их назначение так и не смог понять.
Остальные байты в 24-байтном заголовке файловой системы - нули.
Далее идет таблица файловой системы. На каждую ячейку таблицы выделяется 24 байта. Первые 20 байт содержат название файла. Имя файла капсом, разширение файла - последние три байта названия. Значения с 21 байта содержат некое число. Очевидно, это число каким-то образом должно отсылать к началу файла. Для того, чтобы понять, что оно означает, стоит внимательнее взглянуть на то, как располагаются файлы в этой файловой системе. Можно обратить внимание, что файлы в этой файловой системе хранятся последовательно в блоках, выровненных по 512-байтовым секторам. Тогда в таблице файлов для каждого файла записан номер стартового сектора относительно базового смещения таблицы. Для извлечения файла считывается блок данных, начиная с указанного сектора и заканчивая перед началом следующего файла.
Написав простейший парсер подобной файловой системы, получилось достать все файлы, которые присутствуют в прошивке.
$ ls -la
total 1212
drwxr-xr-x 2 kivyfreakt kivyfreakt 4096 Nov 18 17:00 .
drwxr-xr-x 14 kivyfreakt kivyfreakt 4096 Nov 28 05:04 ..
-rw-r--r-- 1 kivyfreakt kivyfreakt 19050 Oct 4 13:55 AP_ICON.GPZ
-rw-r--r-- 1 kivyfreakt kivyfreakt 6656 Oct 4 13:55 BEEP.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 13360 Oct 4 13:55 CAMERA.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 3938 Oct 4 13:55 CAP.IMG
-rw-r--r-- 1 kivyfreakt kivyfreakt 6772 Oct 4 13:55 CLICK.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 1715 Oct 4 13:55 CONFIG.TXT
-rw-r--r-- 1 kivyfreakt kivyfreakt 11992 Oct 4 13:55 DEL_FILE.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 4160 Oct 4 13:55 FOCUS.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 30340 Oct 4 13:55 GAME_MAIN.JPG
-rw-r--r-- 1 kivyfreakt kivyfreakt 188696 Oct 4 13:55 GAME_NES.BIN
-rw-r--r-- 1 kivyfreakt kivyfreakt 50314 Oct 4 13:55 GAME_PIC.BIN
-rw-r--r-- 1 kivyfreakt kivyfreakt 84457 Oct 4 13:55 GAME_SEL.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 9164 Oct 4 13:55 GAME_YES.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 126117 Oct 4 13:55 GPRS.PAK
-rw-r--r-- 1 kivyfreakt kivyfreakt 34383 Oct 4 13:55 MAIN_UI.GPZ
-rw-r--r-- 1 kivyfreakt kivyfreakt 11653 Oct 4 13:55 PC_CAM.GPZ
-rw-r--r-- 1 kivyfreakt kivyfreakt 368024 Oct 4 13:55 PIC_MEGER.BIN
-rw-r--r-- 1 kivyfreakt kivyfreakt 24980 Oct 4 13:55 PLAYER_BG.JPG
-rw-r--r-- 1 kivyfreakt kivyfreakt 18160 Oct 4 13:55 PLAY.IMG
-rw-r--r-- 1 kivyfreakt kivyfreakt 12542 Oct 4 13:55 POWEROFF_AUDIO.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 22007 Oct 4 13:55 POWER_OFF_LOGO.JPG
-rw-r--r-- 1 kivyfreakt kivyfreakt 26581 Oct 4 13:55 POWERON_AUDIO.WAV
-rw-r--r-- 1 kivyfreakt kivyfreakt 28680 Oct 4 13:55 POWER_ON_LOGO.JPG
-rw-r--r-- 1 kivyfreakt kivyfreakt 10058 Oct 4 13:55 REC.IMG
-rw-r--r-- 1 kivyfreakt kivyfreakt 14912 Oct 4 13:55 SET_BG.JPG
-rw-r--r-- 1 kivyfreakt kivyfreakt 40040 Oct 4 13:55 SETUP.IMG
-rw-r--r-- 1 kivyfreakt kivyfreakt 2726 Oct 4 13:55 U_DISK.GPZ
-rw-r--r-- 1 kivyfreakt kivyfreakt 5 Oct 4 13:55 Z_1.TXT
Помимо уже полученных нами картинок и звуков, есть файлы с довольно специфическими расширениями:
- файлы с расширением GPZ: AP_ICON.GPZ, MAIN_UI.GPZ, PC_CAM.GPZ, U_DISK.GPZ
- файлы с расширением BIN: GAME_NES.BIN, GAME_PIC.BIN, PIC_MEGER.BIN
- файлы с расширением IMG: CAP.IMG, REC.IMG, SETUP.IMG
Интерес так же может представлять конфигурационный файл CONFIG.TXT, который хранит все стандартные настройки камеры. По сути это файл типа ключ-значение, который парсится в программе. Дополнительно в файле можно обнаружить заботливо оставленные комментарии к каждой строке, правда на китайском языке. Файл с примерным переводом содержимого:
----Системные настройки по умолчанию-----
language = 10 [Язык, 1:Английский, 2:Китайский традиционный, 3:Китайский упрощенный, 4:Японский, 5:Французский, 6:Немецкий, 7:Корейский, 8:Итальянский, 9:Португальский, 10:Русский, 11:Испанский, 12:Арабский]
total_lang = 12 [Количество отображаемых языков в настройках]
record_time = 0 [Время записи, 0:Выкл, 1:1 минута, 2:3 минуты, 3:5 минут, 4:10 минут]
mic_off = 0 [Микрофон, 0:Вкл, 1:Выкл]
timestamp = 0 [Временной штамп, 0:Не показывать, 1:Показывать]
panel_off = 2 [Выключение экрана, 0:Вкл, 1:1 минута, 2:2 минуты, 3:3 минуты]
auto_off = 3 [Автовыключение, 0:Выкл, 1:1 минута, 2:3 минуты, 3:5 минут]
volume = 3 [Громкость, 0~7]
freq_hz = 0 [Частота, 0:50Гц, 1:60Гц]
LED_set = 0 [Светодиодная подсветка, 0:Выкл, 1:Вкл, 2:Авто]
LDW_set = 2 [Предупреждение о смещении с полосы, 0:Выкл, 1:Высокий, 2:Стандартный, 3:Низкий]
FCW_set = 1 [Предупреждение о столкновении, 0:Выкл, 1:Вкл]
LINE_set = 1 [Помощник при движении по полосе, 0:Выкл, 1:Вкл]
res_set = 0 [Разрешение записи, 0:720P, 1:VGA (если есть опция 1080P: тогда 0:1080P, 1:720P, 2:VGA)]
park_moni = 0 [Парковочный монитор, 0:Выкл, 1:Высокий, 2:Стандартный, 3:Низкий]
g_sensor = 1 [Чувствительность датчика удара, 0:Выкл, 1:Высокий, 2:Стандартный, 3:Низкий]
cap_size = 3 [Разрешение фото, 0:3Мп, 1:2Мп, 2:1.3Мп, 3:VGA]
key_tone = 1 [Звук клавиш, 0:Выкл, 1:Вкл]
def_year = 2025 [Дата производства, год]
def_mon = 10 [Дата производства, месяц]
def_day = 01 [Дата производства, день]
logo_freeze = 1 [Время показа экрана включения/выключения, в секундах]
----Включение функций----
motion_det = 1 [Детектор движения, 0:Не требуется, 1:Требуется]
led_enable = 1 [Ночное видение, 0:Не требуется, 1:Требуется]
ui_FHD = 1 [Опция 1080P, 0:Не требуется, 1:Требуется]
sen_rotate = 0 [Поворот камеры на 180°, 0:Не требуется, 1:Требуется]
LDW_en = 1 [Функция предупреждения о смещении с полосы, 0:Не требуется, 1:Требуется]
ui_gsensor = 1 [Детектор столкновений, 0:Не требуется, 1:Требуется]
----Версия ресурсов----
rs_ver = antihype [Строка "RES:V1.0" может быть заменена на пользовательский текст, <9 символов]
----Модель продукта----
product = kvfrkt [Текст для определения модели продукта, например K6000, если пусто - используется текст по умолчанию, <9 символов]
Еще есть довольно интересный файл - GPRS.PAK. Скорее всего, он содержит в себе локализацию для каждого языка, которые можно выбрать в настройках. Было бы очень круто понять, как он устроен и пофиксить ОЧЕНЬ корявый и кринжовый машинный перевод от китайцев, но я так и не смог понять его устройства. Не хватило терпения и усидчивости(
7.2 Файлы формата GPZ
Попробуем разобраться, что из себя представляют файлы с расширением GPZ. Из названий ясно, что файлы этого типа каким-то образом хранят главный интерфейс и иконки.
Посмотрим в IDA функцию, параметром которой является строка MAIN_UI.GPZ

В данной функции мы ищем файл с названием MAIN_UI в файловой системе. Если файл был найден, то вычисляется размер этого файла. Далее указатель на адрес файла и его размеры передаются в фунцию, которая читает файл из ресурсной области памяти со всеми необходимыми смещениями и проверками. Далее вызывается функция sub_54508. Причем, можно заметить, что адрес смещения относительно буфера, в котором хранится файл, больше на 4 байта, чем при чтении файла.

В sub_54508 вызывается функция, которую я назвал как mb_gpz, в которой уже и происходит вся магия.

Тут можно найти интересный цикл. Внутри него мы читаем 3 бита данных. Если побитовое И этого числа с числом 6 равно 2, то вызывается функция sub_54568. Цикл прекращает выполняться, если прочитанные побитовое И прочитанных 3 байт из файла с числом 1 равно 0.
Попытаемся немного расшифровать результат дизассемблера.
Начнем с условия попадания в функцию sub_54568:
Число 6 в двоичном виде - 110
Число 2 в двоичном виде - 010
Побитовое И v5 и 110 должно давать 010. Получается, что младший бит числа v5 может быть абсолютно любым. Второй бит обязательно должен быть 1. Третий бит обязательно должен быть 0.
Получаем, что v5 = 01x.
Посмотрим на условие выхода из цикла.
V5 & 1 == 0. Это может быть лишь в том случае, если младший бит точно 0.
Немного погуглив и попинав LLM-ки, пришел к тому, что данная функция очень похожа на обработчик данных, сжатых алгоритмом Deflate.
Deflate-поток содержит серии блоков. Перед каждым блоком находится трёхбитовый заголовок:
- Один бит: флаг последнего блока.
- 1: блок последний.
- 0: блок не последний.
- Два бита: метод, с помощью которого были закодированы данные.
- 00: данные не закодированы (в блоке находятся непосредственно выходные данные).
- 01: данные закодированы по методу статического Хаффмана.
- 10: данные закодированы по методу динамического Хаффмана.
- 11: зарезервированное значение (ошибка).
Число v5, которое мы считываем в самом начале, является трехбитным заголовком deflate-блока. Условие входа в функцию sub_54568 проверяет, является ли блок закодированным по методу статического Хаффмана, а условие выхода из цикла проверяет, является ли deflate-блок последним.
Если заглянуть в функцию sub_54568, то действительно окажется, что она похожа на реализацию deflate со статическим Хаффманом.
Так же, некоторое время я потратил на просмотр файлов этого типа в hex-редакторе. Во-первых, все такие файлы начинаются с магических байт GPZP. Именно поэтому в функции sub_54508 есть смещение на 4 байта. Во-вторых, в конце файла был обнаружен хвост. Он состоит из контрольной суммы CRC-32 и размера разжатого файла ISIZE.
Для реализации распаковщика и упаковщика файлов такого типа можно использовать стандартную библиотеку zlib в питоне. В параметрах компрессора необходимо лишь задать стратегию сжатия Z_FIXED, чтобы явно использовать статический Хаффман. По просмотренным мной функциям не похоже, чтобы хоть где-то использовалась проверка магических байт в начале файла, и проверка контрольной суммы, но при реализации решил учитывать их.
пример разжатого файла:
7.3 Файлы формата BIN
Для анализа файлов этого формата я решил подойти немного с другой стороны. Во-первых, из названий файлов и опыта анализа дампа утилитой foremost очевидно, что это какой-то контейнер для других файлов, причем точно не сжатый, как предыдущий формат файла. Скорее всего, ничего сложного в структуре этого файла не будет, поэтому можно попробовать внимательнее рассмотреть hex представление этого файла.
С самого начала файла идут блоки по 4 байта. После 200 байт начинаются сами данные, которые идут подряд без каких-либо разделителей. В данном случае это jpeg картинки.
Ненулевых групп по 4 байта тут 28. Это число совпадает с количеством рамок, которые доступны из прошивки камеры. Значит, что первые 200 байт представляют собой какую-то таблицу.
Логично предположить, что программа должна как-то разделить файлы из контейнера друг от друга, а так как никаких разделителей между данными нет, то можно предположить, что эта таблица хранит в себе размеры файлов. Действительно, если перевести первую четверку байт в little-endian представлении в обыкновенное десятичное число, то получим ровно размер файла первой рамки.
Написать скрипт, который будет распаковывать и запаковывать файлы данного типа, задача довольно тривиальная.
8. Меняем ресурсы камеры
Теперь, когда у нас есть все скрипты, которые позволяют создавать и изменять файлы, необходимые для камеры, мы можем наконец попробовать изменить интерфейс камеры, поменять детские всратные рамки на что-то более интересное, ну и, конечно, загрузить нормальные игры для эмулятора NES.
Хотелось как-то обыграть розовый цвет корпуса. Пришла идея сделать что-то в духе ЭМО и ностальгии эстетике компьютеров 10-х.
Получилось, конечно, очень всрато: разные элементы, которые не то что-бы гармонично смотрелись друг с другом; кривая верстка; шакальное качество. Хуевый из меня дизайнер) Но позже я подумал, что в этом тоже есть свой т.н. ВАЙБ. Думаю, многие вспомнят кривые странные темы для кнопарей, большиство из которых тоже были сделаны криво-косо, но был в них какой-то свой шарм.
Результат:
КАРТИНКИ
9. Глитчи
Помимо чисто программного моддинга, давно хотелось поэкспериментировать с небольшим аппаратным моддингом, который называется circuit bending. Смысл этого вида модификаций - добавление замыкания между компонентами, сигнальными линиями или случайными точками на плате для достижения новых эффектов и неожиданных возможностей. В основном данная техника ассоциируется с экспериментальной музыкой, так как многие современные музыканты экспериментировали с этой техникой на различных цифровых синтезаторах.
Внутри устройства есть несколько модулей камеры, которые передают информацию с сенсора на основную плату через 24-контактный гибкий шлейф. Материнская плата преобразовывает сигналы с камеры в картинку, отображаемую на экране. Если посреди двух этих частей внести контролируемые ошибки, посредством замыкания определенных контактов коннектора шлейфа, то можно добиться интересных визуальных эффектов.
Для получения интересных эффектов можно просто делать тупой перебор различных варинатов соединения между контактами коннектора. Некоторые комбинации никак не влияют на получаемое изображение, а некоторые комбинации могут быть опасными и привести к перезагрузке/поломке устройства. В шлейфах камер или дисплеев линии высокого уровня и землю часто дублируют для снижения электромагнитных помех на линиях данных, уменьшения падения напряжения на модуле и повышения надежности. Логично, что соединения точек с одинаковыми потенциалами ни к чему не приведет, ток течь не будет или будет очень малым, а вот прямое КЗ (без резистора или потенциометра) между GND и VCC приводит к большому току, нагреву, что скорее всего приведет к выходу из строя компонента или целой платы, так что стоит опасаться такого соединения.
Для простоты я соединял лишь две линии между собой через тумблер. Примеры эффектов, которые у меня получились:
10. Кастом
Решил так же немного разнообразить внешний вид камеры.
Во-первых, перекрасил декоративный объектив и кнопки камеры в матовый черный. Это был мой первый опыт покраски чего-либо краской из баллончика, поэтому получилось очень плохо. Старался соблюдать все условия для хорошего окрашивания: перед покраской обезжирил поверхность изопропиловым спиртом, старался наносить тонким слоем на достаточном расстоянии, но все равно вышло не оч. Издалека еще ОК, но вот вблизи видны все косяки.
КАРТИНКА
Во-вторых, решил добавить немного розовых и черных страз на корпус камеры, вдохновившись этой картинкой из пинтереста:
КАРТИНКА
В итоге получилось примерно так: