某个sqlcrypto的算法概要

C/C++代码 blackfeather

逆向分析某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);
}


没错。。就这么多,测试可用。

评论列表:

Coo1
博主请问哪里找得到sqlite with encrypt的代码呢,普通的sqlite3没有加密解密功能
Coo12020/12/26 15:16:46 回复
tt
老哥还在嘛,这aes加密是128\cbc\pks5吗,我把数据库文件解密出来后只能解出sqlite format3头部,内容还是没变
tt2020/12/13 15:24:18 回复
wzy
小白想请教一下博主,代码中的头文件 aes.h可以从哪里找到?多谢!
blackfeather
这就是标准的aes算法,使用普通的aes模块 、openssl、 cryptopp 都可以
blackfeather2019/7/9 12:34:17 回复
wzy2019/7/8 16:46:51 回复
zxp
博主,sqlcrypto加密的数据库,怎么解密?已经知道了密钥,不知道怎么解密
博主
sqlite3_key是明文密钥初始化入口,内部完成密码生成解密key的操作。
sqlite3Codec就是加密和解密接口,内部有加密和解密。
zxp
博主,你有使用该模块的测试用例吗?通过加载动态库,可以实现数据库解密吗?
博主
核心代码就在这里,剩下的自己去学习整理补上,不要拿来主义。
博主2019/7/22 14:18:12 回复
zxp2019/7/21 23:01:48 回复
博主2019/7/5 12:40:14 回复
zxp2019/7/4 19:15:22 回复
blackfeather
此代码是sqlite with encrypt开启了has_codec宏后的接口代码,引入即可使用。
哈哈
哈哈估计博主 花了大把时间逆向 这下被你一说 更加郁闷了
哈哈2017/4/19 4:25:16 回复
哈哈
哈哈估计博主 花了大把时间逆向 这下被你一说 更加郁闷了。。。
博主
自己回复自己而已。。。你有这么搞笑么。。。
博主2017/6/11 21:02:15 回复
哈哈2017/4/19 4:25:31 回复
blackfeather2016/4/18 12:28:53 回复

发表评论: