рейтинг блогов

История про Avant и его bookmarks.dat

топ 100 блогов sharpc18.09.2022 Почти с появления у меня интернета в 2003-м и года до 2009-го я использовал в качестве основного браузера китайский Avant Browser. В нем были табы, жесты мышью, быстрое отключение скриптов/картинок/флэша и удобный органайзер избранного, и все это в инсталляторе размером 2 МБ.


Какая ж няшка.

История про Avant и его bookmarks.dat

Где-то между 7-й и 11-й версией он начал хранить закладки пользователя в одном файле собственного формата bookmarks.dat. Когда я переходил на Chrome, этот файл я аккуратно забэкапил (несколько раз) рядом с избранным из IE, 4000 .url файлами. На днях у меня дошли до него руки.

Первым делом оказалось, с использованием Lister, libmagic и binwalk, что формат этого bookmarks.dat бинарный, высокоэнтропийный и ничего знакомого не содержит. Первые 4 байта были похожи на размер файла, но именно что похожи — для 4 файлов меньше на неодинаковое число байт, для 1 больше.

Запустим Avant Browser 11.7.46, завалявшийся на винте, под популярной в 2008-м операционной системой. Procmon говорит, что bookmarks.dat читается. Подложим вместо него самый большой bookmarks.dat из бэкапа и обнаружим, что его парсить Avant отказывается. Да если бы и прочитал, подопытная версия ни во что экспортировать не умеет.

Запустим Avant под x64dbg и получим Protection Error. PEId подскажет, что avant.exe написан на Delphi и накрыт ASProtect. К счастью, DecomAS умеет его снимать, хотя и не без потерь, полученный avant_u.exe падает на старте.

Про распакованный avant_u.exe PEId + KANAL сообщают, что внутри есть ADLER32, BASE64, CRC32, MD5, RIJNDAEL (AES), SHA-256 и ZLIB.

Заметим рядом bookmarks.dat.vdt с base64 от каких-то рандомных 32 байт. Возможно, это и есть AES-ключ, тогда, конечно, он не сохранился. Придем в отчаяние. Методом тыка обнаружим, что другой bookmarks.dat из бэкапа, поменьше, открывается. Уйдем из отчаяния.

В популярном дизассемблере пометим функции, использующие найденные адреса AES-таблиц. Загрузим FLIRT-сигнатуры b32vcl, чтобы превратить часть call нечитабельной индиректности в T-имена. Экспортируем из DeDe browser.map с адресами функций, содержащих имена контролов Delphi и импортируем его в дизассемблер, почертыхавшись с адаптированием чьего-то скрипта. Помедитировав на декомпилят, осознаем, что букмарки хранятся в XML, но лапищи автора не столь длинны, чтобы в 4-метровом exe найти, откуда берется ключ для перегонки одного TCustomMemoryStream в другой. Рядом светились какие-то странные длинные строковые константы типа sdfdsjh2983hn2938fh32789ry32jhbjsf2, но не с длиной 32, и key derivation function тоже отыскать не удалось.

На странице плагинов x64dbg находим ScyllaHide, обещающий нормальный анти-анти-дебаг. Как водится, никто не тестирует софт под популярную операционную систему с виртуальной машиной весом 1.5 ГБ (вместо 12 ГБ у более новой популярной операционной системы), поэтому свежий x64dbg ругается на K32GetProcessImageFileNameW и разработчик не спешит это чинить. Что ж, берем snapshot_2020-12-14_15-31.zip. Аналогичную процедуру проделываем с ScyllaHide, которая жаждет функцию CompareStringEx, появившуюся в Vista, у нее берем снапшот с похожей датой. И, о чудо, Avant Browser запускается под отладчиком. Да, он все еще вылетает с Protection Error, если ставить аппаратные брекпойнты, но можно поставить обычные на адреса всех 4 найденных функций, которые что-то делают с AES.

И вот он, долгожданный бряк на 4B2808. В EAX адрес первого блока bookmarks.dat[4:20], в EDX адрес ключа sdkl239r20dk22k3. Внезапно хитрый китаец использовал префикс читабельной паролеобразной строки в качестве ключа AES. Подбираем режим, им оказывается, без особых сюрпризов, MODE_ECB. Размер из 4 первых байт файла bookmarks.dat, очевидно, длина расшифрованных данных. Пристально смотрим на них, начало "PK\x03\x04" неоднозначно намекает на ZIP. Внутри него лежит bm.dat, XML с ложкой cp1251 в бочке utf-8 (суровые ЧПУ 15-летней давности) и достаточно простой онтологией

_rootfolder
    _folder @_title (0 или больше вложений)
        _link @_created @_title @_url @_visited


Что же с самым большим bookmarks.dat, который не открывался, и у которого расшифрованный размер больше его самого? Наверно, побился хвост, но, к счастью, небольшой, всего 110 байт из 32 КБ. Откроем расшифрованный ZIP в популярном hex-редакторе и обнаружим, что единственная PK-запись размером 36 байт предшествует надкушенному стриму со сжатием deflate. Подсмотрим в zipfile.py, что для распаковки стрима можно воспользоваться zlib.decompressobj(-15).decompress(s). Поле frUncompressedSize равно 98781, но zlib достает только 98736 байт. 45 байт потеряны безвозвратно!

Чтобы смягчить горечь утраты, смотрим на конец файла.

<_link _title="Пётр Маковецкий. Смотри в корень!. Книги. Наука и техника" _url="http://n-t.ru/ri/mk/s

Эта ссылка жива и теперь. Можно продолжить запись по образцу соседних записей и соседних файлов.

k.htm" _created="1194??????"/></_rootfolder>\x0A

Ровно 45 байт. Ну хорошо, дата добавления закладки потеряна навсегда. Будем считать ее навеки ушедшим ноябрем 2007-го.

Если вдруг найдутся еще горемыки с меньшим опытом в CTF, вот скрипт:

import struct, zipfile, zlib
from io import BytesIO
from Crypto.Cipher import AES

filename = 'z:\\bookmarks.dat'
f = open(filename, 'rb').read()

dec_len = struct.unpack('I', f[:4])[0]

key = 'sdkl239r20dk22k3'
zipped = AES.new(key, AES.MODE_ECB).decrypt(f[4:])[:dec_len]

frSignature, frVersion, frFlags, frCompression, frFileTime, frFileDate, frCrc, frCompressedSize, frUncompressedSize = struct.unpack(', zipped[:0x1A])

try:
    z = zipfile.ZipFile(BytesIO(zipped))
    for fileinfo in z.filelist:
        unpacked = z.read(fileinfo)
        open(filename + '.xml', 'wb').write(unpacked)
except Exception as e:
    print repr(e)
    print 'Recovering...'
    decompressor = zlib.decompressobj(-15)
    dec = decompressor.decompress(zipped[0x24:])
    open(filename + '.xml', 'wb').write(dec)
    print 'Lost %d bytes' % (frUncompressedSize - len(dec))


А в это время все прогрессивное человечество ждало от меня прорывов в нейронауке! Ну спасибо тебе, Anderson Che!

Оставить комментарий

Архив записей в блогах:
Со вчерашнего вечера получаю сообщения примерно такого содержания: “Илья, поздравляю! Счастья Вам!”; “Чувак, ну что за дела? Как ты мог не позвать меня на свадьбу?!” “Лживый мудак, я так и знала, что у тебя есть невеста!” Друзья и подруги, ...
На правах воскресного рака: ...
Хотите узнать, как на самом деле у нас обстоят дела с сексуальной свободой и раскрепощенностью у женщин? Совершенно простой тест и совершенно простая история про стандартную семейную пару, где даже никто никого не содержит, не обеспечивает и не спонсирует. Я, если честно, была ...
Давным-давно, будучи еще мальчишкой, я знал одного очень везучего рыбака. Он ходил на рыбалку со здоровенным рюкзаком, с кучей снастей и в широкополой шляпе — прямо лубочный рыболов. Все говорили, что он очень везучий, мол знает какую-то тайну. А я был очень любопытным и решил ...
Чокак? Куда деньги сберегли? Во что? Сберегли ли? Было ли что сберегать? Что успели, а о чем жалеете сейчас как о невосполнимом пройобе? Что бы предприняли немедленно прям завтра, окажись у вас завтра миллион рублей? А 50 миллионов? Просто интересно. ...