如何通过故意破坏它来保护我的SQLite DB,然后通过代码进行修复?

发布于 2025-01-21 09:06:27 字数 4070 浏览 3 评论 0原文

这是我在Android上使用Java和Sqlite上的第一个应用程序。

问题:
我的应用程序上有一个本地的sqlite DB。我很惊讶地看到一旦安装了应用程序,可以访问数据库多么容易(无需成为程序员或黑客)。

我尝试将SQLCipher添加到我的应用中,但它仅适用于较新的Android版本11& 12且不适用于Android 9,这确实使我的应用程序的尺寸更大。

在研究了更多之后,我找到了一个更好的解决方案,该解决方案不涉及使用SQLCipher地cryperd DB,而是它包括损坏DB文件的第一个字节,然后在应用程序的每个启动后,代码将解析该文件并使用该文件并使用该文件。 。

固定文件 但是,我不知道如何实施Android和SQLite编程,

这是 如何实际做的。我不明白该怎么做:
1-损坏数据库文件(将其转换为字节数组并更改一些值)
2-在资产文件夹中复制它
3-在第一次运行中,从资产修复了损坏的文件,并在数据库中复制
文件夹。
更改前200个字节值:

    int index = 0;
    for(int i=0;i<100;i++)
    {
        byte tmp = b[index];
        b[index] = b[index + 1];
        b[index + 1] = tmp;
        index += 2;
    }

由于只替换了前200个字节,因此使用相同的代码来固定第一个200个字节值。

这是我的SQLiteOpenhelper的代码,如果需要:

   

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String TAG = DatabaseHelper.class.getSimpleName();

    public static String DB_PATH;
    public static String DB_NAME;

    public SQLiteDatabase database;
    public final Context context;

    public SQLiteDatabase getDb() {
        return database;
    }

    public DatabaseHelper(Context context, String databaseName, int db_version) {
        super(context, databaseName, null, db_version);
        this.context = context;

        DB_PATH = getReadableDatabase().getPath();
        DB_NAME = databaseName;

        openDataBase();

        // prepare if need to upgrade
        int cur_version = database.getVersion();
        if (cur_version == 0) database.setVersion(1);
        Log.d(TAG, "DB version : " + db_version);
        if (cur_version < db_version) {
            try {
                copyDataBase();
                Log.d(TAG, "Upgrade DB from v." + cur_version + " to v." + db_version);
                database.setVersion(db_version);
            } catch (IOException e) {
                Log.d(TAG, "Upgrade error");
                throw new Error("Error upgrade database!");
            }
        }
    }

    public void createDataBase() {
        boolean dbExist = checkDataBase();
        if (!dbExist) {
            this.getReadableDatabase();
            this.close();
            try {
                copyDataBase();
            } catch (IOException e) {
                Log.e(TAG, "Copying error");
                throw new Error("Error copying database!");
            }
        } else {
            Log.i(this.getClass().toString(), "Database already exists");
        }
    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDb = null;
        try {
            String path = DB_PATH + DB_NAME;
            checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
        } catch (SQLException e) {
            Log.e(TAG, "Error while checking db");
        }

        if (checkDb != null) {
            checkDb.close();
        }
        return checkDb != null;
    }

    private void copyDataBase() throws IOException {
        InputStream externalDbStream = context.getAssets().open(DB_NAME);
        String outFileName = DB_PATH + DB_NAME;

        OutputStream localDbStream = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = externalDbStream.read(buffer)) > 0) {
            localDbStream.write(buffer, 0, bytesRead);
        }

        localDbStream.close();
        externalDbStream.close();

    }

    public SQLiteDatabase openDataBase() throws SQLException {
        String path = DB_PATH + DB_NAME;
        if (database == null) {
            createDataBase();
            database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
        }
        return database;
    }

    @Override
    public synchronized void close() {
        if (database != null) {
            database.close();
        }
        super.close();
    }

非常感谢。
[1]: https://stackoverflow.com/a/63637685/18684673

This is my first app on Android with Java and SQLite.

ISSUE:
I have a local SQLIte db on my app. I was very surprised to see how easy it is to get access to the db once you have installed the app (no need to be a programmer nor a hacker).

I tried adding SQLCipher to my app but it only worked for newer Android versions 11 & 12 and didn't work for Android 9 for example and it did make my app's size much bigger.

After researching more I found a better solution for my case which doesn"t involve crypting the db with SQLCipher but rather it consists of corrupting the first bytes of the db file then after each launch of the app the code will decorrupt the file and use the fixed file instead. This insures that anyone who decompiles the apk will only get access to a corrupt db file and will have to put more effort to fix it which is my goal.

I came across this solution in a reply [here][1] but I don't know how to implement it as I am new to Android and SQLite programming. Any help is much appreciated on how to actually do it.

These are the steps as mentioned by the user: farhad.kargaran which need more explanation as I don't get how to do it:
1- corrupt the db file (convert it to byte array and change some values)
2- copy it in asset folder
3- in first run fix corrupted file from asset and copy it in database
folder.
Change first 200 byte values like this:

    int index = 0;
    for(int i=0;i<100;i++)
    {
        byte tmp = b[index];
        b[index] = b[index + 1];
        b[index + 1] = tmp;
        index += 2;
    }

As only the first 200 bytes were replaced, the same code is used for fixing first 200 byte values.

Here is my code for the SQLiteOpenHelper if needed:

   

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String TAG = DatabaseHelper.class.getSimpleName();

    public static String DB_PATH;
    public static String DB_NAME;

    public SQLiteDatabase database;
    public final Context context;

    public SQLiteDatabase getDb() {
        return database;
    }

    public DatabaseHelper(Context context, String databaseName, int db_version) {
        super(context, databaseName, null, db_version);
        this.context = context;

        DB_PATH = getReadableDatabase().getPath();
        DB_NAME = databaseName;

        openDataBase();

        // prepare if need to upgrade
        int cur_version = database.getVersion();
        if (cur_version == 0) database.setVersion(1);
        Log.d(TAG, "DB version : " + db_version);
        if (cur_version < db_version) {
            try {
                copyDataBase();
                Log.d(TAG, "Upgrade DB from v." + cur_version + " to v." + db_version);
                database.setVersion(db_version);
            } catch (IOException e) {
                Log.d(TAG, "Upgrade error");
                throw new Error("Error upgrade database!");
            }
        }
    }

    public void createDataBase() {
        boolean dbExist = checkDataBase();
        if (!dbExist) {
            this.getReadableDatabase();
            this.close();
            try {
                copyDataBase();
            } catch (IOException e) {
                Log.e(TAG, "Copying error");
                throw new Error("Error copying database!");
            }
        } else {
            Log.i(this.getClass().toString(), "Database already exists");
        }
    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDb = null;
        try {
            String path = DB_PATH + DB_NAME;
            checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
        } catch (SQLException e) {
            Log.e(TAG, "Error while checking db");
        }

        if (checkDb != null) {
            checkDb.close();
        }
        return checkDb != null;
    }

    private void copyDataBase() throws IOException {
        InputStream externalDbStream = context.getAssets().open(DB_NAME);
        String outFileName = DB_PATH + DB_NAME;

        OutputStream localDbStream = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = externalDbStream.read(buffer)) > 0) {
            localDbStream.write(buffer, 0, bytesRead);
        }

        localDbStream.close();
        externalDbStream.close();

    }

    public SQLiteDatabase openDataBase() throws SQLException {
        String path = DB_PATH + DB_NAME;
        if (database == null) {
            createDataBase();
            database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
        }
        return database;
    }

    @Override
    public synchronized void close() {
        if (database != null) {
            database.close();
        }
        super.close();
    }

Much appreciated.
[1]: https://stackoverflow.com/a/63637685/18684673

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

策马西风 2025-01-28 09:06:27

作为CopyDatabase的一部分,请更正然后编写损坏的数据,然后复制其余的数据。

可以做各种方式,

例如

    long buffersRead = 0;  //<<<<< ADDED for detecting first buffer        
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = externalDbStream.read(buffer)) > 0) {
        if (bufferesRead++ < 1) {
            //correct the first 200 bytes here before writing ....
        }
        localDbStream.write(buffer, 0, bytesRead);
    }

As part of the copyDatabase, correct and then write the corrupted data, then copy the rest.

Could be done various ways

e.g.

    long buffersRead = 0;  //<<<<< ADDED for detecting first buffer        
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = externalDbStream.read(buffer)) > 0) {
        if (bufferesRead++ < 1) {
            //correct the first 200 bytes here before writing ....
        }
        localDbStream.write(buffer, 0, bytesRead);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文