К примеру, есть программа, из которой необходимо экспортировать какие-то данные. Это может быть, например каталог товаров конкурента, база вопросов для тестирования и пр.
Обычно разработчики дают файлам с данными вполне осмысленные имена, и найти их несложно (расширение файла значения не имеет, важен внутренний формат). Здесь я рассмотрю вариант с базой данных на SQLite.
Выбор среди расширений для защиты SQLite баз данных небольшой. К тому же некоторые из них коммерческие. Компания Hwaci, Inc., отвечающая за разработку SQLite предлагает пару таких коммерческих расширений:
Обычно разработчики дают файлам с данными вполне осмысленные имена, и найти их несложно (расширение файла значения не имеет, важен внутренний формат). Здесь я рассмотрю вариант с базой данных на SQLite.
- SQLite EncryptionExtension (SEE) шифрует БД по мере того как она пишется на диск, по-видимому эффективная штука.
- Compressed and Encrypted Read-Only Database (CEROD) это расширение пошло дальше и не только шифрует БД, но еще и обеспечивает сжатие. Сжатие естественно уменьшает занимаемое базой данных место, но есть побочный эффект база данных становится read-only. Предлагают использовать при распространении лицензионных материалов.
Первый шаг определить зашифрована БД или нет. При моем первом знакомстве с SQLite я использовал программу SQLabs SQLiteManager. А эта программа иногда при открытии БД показывала сообщение «Database file seems to be encrypted. Please enter the encryption key». Казалось, что БД защищена каким-нибудь SEE или CEROD. Однако БД нормально открывалась стандартным sqlite3.exe или другой тулзой например SQLite Administrator.
Далее если схема БД нетривиальная, то разобраться что к чему довольно сложно. Или названия таблиц и полей могут быть сокращены до неузнаваемости. В таких случаях, хорошо бы посмотреть на SQL-запросы, которые программа делает к БД.
Способ, который далее описывается, работает, только если SQLite представлен в программе в виде внешней библиотеки (sqlite3.dll). Идея в том чтобы скомпилировать свой SQLite с логированием запросов и подменить им тот, который используется программой.
Я буду использовать компилятор Visual C++ 2010, но в принципе это неважно.
1) Открываем MSVC и создаем новый Win32 Project. В Application Wizard выбираем DLL и ставим галочку "Empty project".
2) Добавим в проект файлы sqlite3.h и sqlite3.c из исходников SQLite.
3) Также скопируем в папку с проектом файл sqlite3.def из дистрибутива SQLite. .def файл можно сгенерировать из файла sqlite3.dll с помощью утилиты dumpbin.
4) В свойствах проекта, добавим sqlite3.def в Linker -> Input -> Module definition file.
5) Также в С/С++ -> Preprocessor -> Preprocessor Definitions можно добавить:
- WIN32
- _DEBUG
- _WINDOWS
- _USRDLL
- SQLITE3_EXPORTS
- SQLITE_ENABLE_RTREE
- SQLITE_ENABLE_COLUMN_METADATA
- SQLITE_ENABLE_ATOMIC_WRITE
- SQLITE_ENABLE_FTS3
- SQLITE_ENABLE_FTS3_PARENTHESIS
- SQLITE_ENABLE_FTS4
- SQLITE_ENABLE_IOTRACE
- SQLITE_ENABLE_LOCKING_STYLE
- SQLITE_ENABLE_MEMORY_MANAGEMENT
- SQLITE_ENABLE_MEMSYS3
- SQLITE_ENABLE_MEMSYS5
- SQLITE_ENABLE_STAT2
- SQLITE_ENABLE_STAT3
- SQLITE_ENABLE_UNLOCK_NOTIFY
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT
SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; FILE *fp; fp = fopen("c:\\sqlite3_prepare_v2.txt","a+"); fprintf(fp, "%s\n\n", zSql); fclose(fp); rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; }
SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; /* Return code */ const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ char **azCols = 0; /* Names of result columns */ int nRetry = 0; /* Number of retry attempts */ int callbackIsInit; /* True if callback data is initialized */ FILE *fp; fp = fopen("c:\\sqlite3_exec.txt","a+"); fprintf(fp, "%s\n\n", zSql); fclose(fp);
SELECT customFunction();
int sqlite3_load_extension( sqlite3 *db, const char *ext_name, const char *entry_point, char **error )