 |

15.05.2021, 12:19
|
|
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами:
3526561
Репутация:
0
|
|
Традиционно, для работы с СУБД используются скриптовые языки типа: Python, SQL, Tcl, Perl и прочие. Это вполне оправдано, поскольку их синтаксис максимально приближен к человеческой речи, а огромный набор рычагов и предметно-ориентированных модулей превращает решение вполне серьёзных проблем, чуть-ли не в игру. Единственным недостатком скриптов является скорость выполнения ими задач, т.к. в отличии от компилируемых программ они работают через интерпретатор – т.е. сначала построчный анализ текста, перевод его в байт-код, и лишь потом исполнение.
Однако бывают ситуации, когда с базами нужно совершить элементарные действия, например не создавать её с нуля забивая данными, а тупо прочитать пару-тройку столбцов уже имеющейся в ней информации. Это могут быть кукисы в браузерах, пароли и прочая инфа личного характера. Именно в таких случаях преимущество ассма (да и любого компилируемого языка) становится очевидным. Чтобы полностью исключить криминал, мы потренируемся строго на своей машине, не совершая атак на удалённые сервера. Здесь идеальным вариантом будет разбор встраиваемой базы SQLite – на ней и остановимся. Материал получился обширным, поэтому я разделил его на три части:
Содержание часть(1):
1. Оффтоп..
2. Внутренний формат базы-данных SQLite;
• практика – чтение заголовка базы;
Содержание часть(2):
3.Функции библиотеки sqlite3.dll;
• практика – вытаскиваем "cookies" браузеров;
Содержание часть(3):
4. Функции DPAPI из библиотеки crypt32.dll;
• практика – принцип шифрования паролей Chrome;
5. Постскриптум.
-------------------------------------------------------
1. Общие сведения
Ещё в 80-х годах прошлого столетия "человек-разумный" придумал СУБД, или систему управления базами данных. В обозримом будущем, схема свои позиции сдавать не собирается, а потому представляет интерес на всех уровнях. Огромные корпорации доверяют базам конфиденциальную информацию, а кража этих баз вторыми лицами – худшее, что только может случиться с компанией.
Всё-бы ничего, однако достоянием общественности становятся и личные сведения о нас с вами, а это уже настораживает. Базы почтовых серверов и социальных сетей с завидной периодичностью утекают из (якобы) защищённых периметров и админы здесь только пожимают плечами. В результате ошибок переполнения буферов, всевозможных дыр в системе безопасности и прочих уязвимостей, вся эта конструкция держится на честном слове. По сути мы, как конечные пользователи, в войне хакеров с админами выступаем в роли сторонних наблюдателей, которые лёжа на своём диване способны лишь обсуждать/осуждать.
Но мир не без добрых людей. Некоторые энтузиасты по собственной инициативе и на бесплатной основе пытаются изменить его к лучшему. Так, в августе 2000-го, некто Ричард Хипп (северная Каролина, США) анонсировал СУБД под названием SQLite. Он точил её напильником долгих 4-года, чтобы привести в надлежащий вид и представить мировому сообществу как стабильный релиз SQLite3. На данный момент последней считается v3.35.5 от 19 апреля 2021-года. То-есть проект жив, и активно развивается.
В отличие от многих других систем управления базами данных типа: MySql, Oracle и прочих, SQLite не является клиент-серверной базой данных – это обычное хранилище, которое встраивается в клиентское приложение, ..например: веб-браузеры, аудио/видео проигрыватели, графические редакторы, мобильные телефоны и т.п. В результате, получаем достаточно мощную, компактную и простую СУБД, а как-говорится "где мало сложности – там мало ложности".
На данном этапе сразу определимся с инструментами, чтобы больше не возвращаться к ним.
Есть огромное кол-во редакторов SQLite, но лично мне приглянулся "Expert Personal". Продуманный его интерфейс позволяет без особого труда и в пару кликов создавать, просматривать и редактировать базы-данных, а бонусом – в установочном пакете сразу идёт и свежая библиотека sqlite3.dll. Дело в том, что полноценная поддержка SQLite включена только начиная с Win-10, так-что обладателям более старых систем ХР,7,8 придётся качать эту либу из репозитория автора. Получив редактор, мы убиваем сразу двух зайцев – вот линки:
Сайт разработчика "SQLite Expert Personal": SQLite administration | SQLite Expert
Исходники и библиотека от автора СУБД: SQLite Download Page
Описание функций sqlite3.dll: List Of SQLite Functions
Навороченный HEX-редактор "010 Editor":https://www.sweetscape.com/010editor
2. Знакомство с базой SQLite3
SQLite имеет свой формат и обслуживается своей подсистемой. Передвижение запросов на выполнение той или иной операции назвали "транзакациями". Вся база-данных разбивается на страницы одинакового размера, где и хранится полезная нагрузка в виде двумерной матрицы строк и столбцов. Размер одной страницы "Page" варьируется в диапазоне от 512 до 65536 байт, а под максимальное кол-во страниц в одной базе отводится 32 бита = 4'294'967'294. При таких значениях, простой арифметикой можно получить допустимый размер базы-данных:
Код:
4'294'967'294 * 65'536 = 281'474'976'645'120
, или 281 терабайт.
2.1.0. Режим[1] – Rollback, или "журнал отката" состояния
При таких гигантских объёмах в 1/4 петабайта, СУБД обязана гарантировать целостность своих данных, иначе в использовании баз просто теряется смысл. Поэтому, при операциях записи в таблицу, ядро SQLite сначала копирует содержимое модифицируемых страниц в т.н. "журнал отката", и только потом производит запись в основную базу. Журнал Rollback – это обычный дисковый файл, который всегда находится рядом с базой и имеет оригинальное имя, с добавлением суффикса
. Если транзакация на запись проходит успешно, то журнал удаляется, иначе ядро откатывает базу в прежнее состояние с сообщением об одной из следующих возможных ошибок:
Отметим, что откат происходит прозрачно для пользователя, а вся ответственность ложится на неэкспортируемую служебную процедуру, которую запускает т.н. "триггер". В зависимости от конфигурации базы, триггеры могут вызываться как для каждой операции записи, так и один раз на глобальное изменение базы (в последнем случае его называют "табличным").
2.1.1. Режим[2] – WAL, или "журнал упреждающей записи" (Write-Ahead Logging)
Традиционный откат после неудачных попыток записи подразумевает сохранение резервных копий исходных страниц в отдельный файл, и восстановлении их в случае сбоя. В более новых версиях SQLite ввели ещё один режим под названием "упреждающая запись" WAL. Этот альтернативный режим представляет собой инверсный вариант обычного отката. Теперь, запись производится не напрямую в базу, а наоборот во-временный файл с суффиксом
. Это напоминает отложенную запись в кэш процессора WriteBack, не в пример сквозной записи в память WriteThrought.
Размер временного WAL-файла на диске как-правило 1000 страниц, а транзакацию сброса их в базу назвали "контрольной точкой". Таким образом, в традиционном откате имеем две примитивные операции "чтение/запись", а в усовершенствованном WAL добавляется ещё одна операция "сброс" (контрольная точка). Обновление исходной базы страницами WAL может происходить или по запросу пользователя, или-же автоматически, при переполнении временного файла.
2.1.2. VACUUM – дефрагментация базы-данных
Ещё одним немаловажным моментом является поддержание базы в компактном/сжатом состоянии. Для этих целей, в доспехах SQLite припрятан механизм под названием "Vacuum". Суть его в том, что если мы удаляем строки из базы, то информация фактически остаётся на своём месте, а соответствующая строка просто помечается свободной. В результате, в таблице появляются паразитные (вакуумные) строки, которые не несут абсолютно никакой полезной инфы, зато занимают пространство и размер базы.
Команда "VACUUM" очищает основную базу путём копирования её содержимого во временный файл, и перезагрузки исходной базы из этой копии. При этом механизм удаляет пустые страницы, выравнивает данные (делает их смежными) и назначает каждой строке новый порядковый номер RowID. Ядро отвергнет команду, если есть активная транзакция.
Кстати это типичная ситуация в базах "cookies" браузеров. Как-правило, время жизни кукисов определяет значение в столбце "expires_utc" (time counter), по истечении которого "правильный" кукис авто-уничтожается системой. В итоге, если посмотреть на такую базу в редакторе, она будет напоминать зубы хоккеиста, как в примере ниже:
2.1.3. CachePage– кэширование страниц
Подсистема SQLite может иметь несколько страниц для кэша дискового ввода-вывода. Рассмотрим ситуацию, когда мы изменили несколько строк в таблице и дали команду на их сохранение. При этом, если транзакацию на запись ядро выполнит сразу, то это займёт много времени, и мы рискуем получить отклик через пару секунд. Запись на жёсткий диск довольно длительная операция, и лучше подкопить все модифицированные данные сначала в буферной памяти (а точнее в странице кэш), и сохранять их на диск в какой-нибудь момент бездействия. Такой алгоритм практикуют все версии операционных систем Windows при файловых операциях ввода-вывода, и подсистема SQLite не исключение, хотя на практике применяет редко.
2.1.4. Формат схемы базы-данных
В настоящее время определены 4 разновидности формата схемы:
1. Legacy (проприетарный) – понимается всеми версиями SQLite, до v3.0.0 (18.06.2004).
2. Добавляет фишку, когда строки в одной таблице могут иметь различное кол-во столбцов (v3.1.3).
3. Незначительные усовершенствования формата(2).
4. Введено ключевое слово "DESC" в объявлениях индексов, которое позволяет сортировать таблицу или в порядке возрастания "ASC" (ascending), или убывания "DESC" (descending). Обратная сортировка не поддерживалась в схемах(1..3). Все современные базы-данных SQLite в дефолте используют формат(4).
2.1.5. Заголовок "Header" базы
Любая база-данных SQLite3 начинается с заголовка "Header", который занимает первые 100 байт (см. скрин 010-Editor выше). В нём указываются фундаментальные сведения о базе, её схема, кол-во и размер страниц, счётчик изменений таблицы и т.д.
Отличительной особенностью заголовка является прямой порядок байт, что придаёт ему нетрадиционную форму черепа. Например, числа в оперативной памяти ОЗУ наших компьютеров с процессорами х86/64 хранятся младшим байтом вперёд – такой порядок называют ещё "Little-Endial" и число
будет представлено в ячейках памяти как
hex. В заголовке-же базы SQLite нужно воспринимать их в привычном нам виде слева-направо, т.е. "Big-Endian". Отметим, что для таких случаев в системе-команд процессоров Intel/AMD имеется специальная инструкция
, которая отражает порядок байт в числе(Byte Swap).
В таблице выше представлены поля заголовка, а для удобства их программного чтения, мы создадим одноименную структуру такого содержания:
C-подобный:
Код:
struct SQLITE_HEADER
;
//
;
//----- Запрашиваем имя файла
cinvoke printf
,
cinvoke scanf
,
,
fName
;
//----- Пробуем открыть его
invoke _lopen
,
fName
,
0
or eax
,
eax
;
// ошибка?
jns @next
cinvoke printf
,
jmp @exit
@next
:
push eax
invoke _lread
,
eax
,
buff
,
100
;
// читаем заголовок из базы в буфер
pop eax
invoke _lclose
,
eax
;
// закрыть файл базы
;
//----- Проверим на принадлежность заголовка к SQLite
call @f
db
'SQLite format 3'
;
// сигнатура,
@@
:
pop edi
;
// ..в регистре EDI
mov esi
,
buff
;
// где искать
mov ecx
,
15
;
// длина строки
repe cmpsb
;
// сравнить!
jecxz @ok
cinvoke printf
,
jmp @exit
;
//----- Заголовок корректный - выводим инфу..
@ok
:
cinvoke printf
,
,
buff
;
//
mov esi
,
buff
mov eax
,
[
esi
+
SQLITE_HEADER
.
SqliteVerNum
]
bswap eax
call GetSqlVersion
cinvoke printf
,
,
eax
,
ebx
,
ecx
mov esi
,
buff
mov eax
,
[
esi
+
SQLITE_HEADER
.
BaseCP
]
bswap eax
shl eax
,
3
mov ebx
,
[
esi
+
SQLITE_HEADER
.
SchemeFormat
]
bswap ebx
mov ecx
,
[
esi
+
SQLITE_HEADER
.
WriteCount
]
bswap ecx
mov edx
,
[
esi
+
SQLITE_HEADER
.
AppId
]
bswap edx
cinvoke printf
,
,
eax
,
ebx
,
ecx
,
edx
;
//--------------
cinvoke printf
,
mov esi
,
buff
movzx ebp
,
[
esi
+
SQLITE_HEADER
.
PageSize
]
rol bp
,
8
push ebp
mov ebx
,
[
esi
+
SQLITE_HEADER
.
TotalPage
]
bswap ebx
mov ecx
,
[
esi
+
SQLITE_HEADER
.
TotalFreePage
]
bswap ecx
pop eax
mul ebx
mov edx
,
[
esi
+
SQLITE_HEADER
.
FreePageOffset
]
bswap edx
cinvoke printf
,
,
ebp
,
ebx
,
eax
,
edx
,
ecx
;
//--------------
cinvoke printf
,
mov esi
,
buff
mov eax
,
[
esi
+
SQLITE_HEADER
.
CookieFile
]
bswap eax
mov ebx
,
[
esi
+
SQLITE_HEADER
.
CachePageSize
]
bswap ebx
movzx ecx
,
[
esi
+
SQLITE_HEADER
.
WriteWAL
]
bswap ebx
movzx edx
,
[
esi
+
SQLITE_HEADER
.
ReadWAL
]
bswap ebx
cinvoke printf
,
,
\
eax
,
ebx
,
ecx
,
edx
mov esi
,
buff
mov eax
,
[
esi
+
SQLITE_HEADER
.
IncVacuum
]
bswap eax
mov ebx
,
[
esi
+
SQLITE_HEADER
.
VacuumRootPage
]
bswap ebx
cinvoke printf
,
,
eax
,
ebx
@exit
:
cinvoke getch
cinvoke exit
,
0
;
//------------
GetSqlVersion
:
xor edx
,
edx
mov ebx
,
1000000
div ebx
push eax
xchg eax
,
edx
mov ebx
,
1000
xor edx
,
edx
div ebx
xchg ecx
,
edx
xchg ebx
,
eax
pop eax
ret
;
//------------
section
'.idata'
import data readable
library kernel32
,
'kernel32.dll'
,
msvcrt
,
'msvcrt.dll'
import msvcrt
,
printf
,
'printf'
,
scanf
,
'scanf'
,
getch
,
'_getch'
,
exit
,
'exit'
include
'api\kernel32.inc'
В следующей части рассмотрим функции библиотеки sqlite3.dll, способ работы с ними, типы запросов, ну и прочее в этом духе. В практической части попытаемся считать куки браузеров, что они представляют собой, и какого типа хранят информацию. В скрепку кладу инклуд "sqlite3.inc" и исполняемый файл приведённого выше кода. До скорого, пока!
|
|
|

30.03.2022, 23:29
|
|
Новичок
Регистрация: 11.10.2021
Сообщений: 0
С нами:
2416198
Репутация:
0
|
|
Marylin ты волшебник... преклоняюсь перед тобой великий и ужасный! )) Спасибо огромное, как только возникает какая-то тема, которую хрен нагуглишь, а у тебя уже целая статья есть по ней ))
|
|
|
|
 |
Предыдущая тема
Следующая тема
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|