某个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);
}


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

评论列表:

blackfeather
此代码是sqlite with encrypt开启了has_codec宏后的接口代码,引入即可使用。
blackfeather2016/4/18 12:28:53 回复

发表评论: