逆向分析某app的本地存储是发现其平台下所有APP都是利用了同一个基于sqlite的加密库,网上没有搜索到任何有用信息,猜测是自己定制的(文件名:libdatabase_sqlcrypto.so,内部名是alibaba.sqlcrypto)。
ps:如果有人觉得此文不妥,立即联系博主处理(我发现了一些事情,表示你们响应速度还蛮快的)。
于是逆向分析了下其加密算法,然后参考着sqlite的加密接口重写了此库。
关键函数很少:
#include "sqlite3.c" #include "aes.h" #define KEYLENGTH 16 typedef struct _codec_ctx { char *pszPass; int nPassLen; aes_ctx m_ctxde; aes_ctx m_ctxen; Btree* m_bt; /* Pointer to B-tree used by DB */ }codec_ctx; void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { codec_ctx *ctx = (codec_ctx *) iCtx; unsigned char *pData = (unsigned char *) data; int pageSize = sqlite3BtreeGetPageSize(ctx->m_bt); int nBlock = pageSize / 16; int i; unsigned char szTmp[16]; switch(mode) { case 0: /* decrypt */ case 2: case 3: for (i = 0; i < nBlock; i++) { aes_decrypt(&pData[i * 16], szTmp, &ctx->m_ctxde); memcpy(&pData[i * 16], szTmp, 16); } break; case 6: /* encrypt */ for (i = 0; i < nBlock; i++) { aes_encrypt(&pData[i * 16], szTmp, &ctx->m_ctxen); memcpy(&pData[i * 16], szTmp, 16); } break; case 7: /* Encrypt a page for the journal file */ for (i = 0; i < nBlock; i++) { aes_encrypt(&pData[i * 16], szTmp, &ctx->m_ctxde); memcpy(&pData[i * 16], szTmp, 16); } break; } return data; } void sqlite3FreeCodecArg(void *pCodecArg) { codec_ctx *ctx = (codec_ctx *)pCodecArg; if(pCodecArg == NULL) return; sqlite3_free(ctx->pszPass); memset(ctx, 0, sizeof(codec_ctx)); sqlite3_free(ctx); } int sqlite3CodecAttach(sqlite3* db, int nDb, const void* zKey, int nKey) { struct Db *pDb = &db->aDb[nDb]; if(nKey && zKey && pDb->pBt) { codec_ctx *ctx = sqlite3Malloc(sizeof(codec_ctx)); aes_decrypt_key128((const unsigned char *)zKey, &ctx->m_ctxde); aes_encrypt_key128((const unsigned char *)zKey, &ctx->m_ctxen); ctx->m_bt = pDb->pBt; /* assign pointer to database btree structure */ ctx->pszPass = (char *)sqlite3Malloc(nKey + 1); memcpy(ctx->pszPass, zKey, nKey); ctx->pszPass[nKey] = '\0'; ctx->nPassLen = nKey; sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx); } return SQLITE_OK; } void sqlite3pager_get_codec(Pager *pPager, void **ctx) { *ctx = pPager->pCodec; } void sqlite3CodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey) { struct Db *pDb = &db->aDb[nDb]; if( pDb->pBt ) { codec_ctx *ctx; sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); if(ctx) { *zKey = ctx->pszPass; *nKey = ctx->nPassLen; } else { *zKey = NULL; *nKey = 0; } } } void sqlite3_activate_see(const char *info) { //啥也不用做 } int sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey) { //懒得写了。。。好烦 return SQLITE_ERROR; } int sqlite3_key(sqlite3 *db, const void *zKey, int nKey) { /* The key is only set for the main database, not the temp database */ return sqlite3CodecAttach(db, 0, zKey, nKey); }
没错。。就这么多,测试可用。
sqlite3Codec就是加密和解密接口,内部有加密和解密。