首页
论坛
专栏
课程

[原创]阿里旺旺数据库解密算法分析

2019-10-14 15:48 1812

[原创]阿里旺旺数据库解密算法分析

2019-10-14 15:48
1812
1. 获取user_id
profiles 目录下的 目录名  cntaobaotb051706067 就是  user_id .

2. 计算  pass , pass = md5( user_id ), 代码在 rvcomlib.dll 里.

上图三个函数依次是MD5_Init,MD5_Update, MD5_Final
MD5_Update  参数


MD5_Final 结果


3.  计算db_key ,  db_key = sha1( pass )

SHA1_Update  参数

SHA1_Final 结果


4. 数据库每页的大小是 0x400, 用的是 DES 加密
DES_Set_key_unchecked 的第一个参数8 byte  大小就是  db_key  取前八个字节


DES_ncbc_encrypt 解密后的结果


可以看到 sqlite 文件头了,第一个页面解密成功。
完整代码
#include <Windows.h>
#include <stdio.h>
#include <openssl/des.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <string>
using namespace std;

unsigned char desTestKey[8] = {0x0};
#define SHA1_LEN 20

wstring Ascii2Unicode(const string& str) {
	 
	int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
 
	wchar_t* pUnicode = (wchar_t*)malloc(sizeof(wchar_t) * unicodeLen);
	 
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);
	wstring ret_str = pUnicode;
	free(pUnicode);
	return ret_str;
}
string	Unicode2Ascii(const wstring& wstr) {
	  
	int ansiiLen = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
	 
	char* pAssii = (char*)malloc(sizeof(char) * ansiiLen);
 
	WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);
	string ret_str = pAssii;
	free(pAssii);
	return ret_str;
}

int wmain(int argc, wchar_t* argv[])
{
	wchar_t* uin = argv[2];
	string uin_ascii = Unicode2Ascii(uin);

	unsigned char hash[SHA1_LEN] = { 0 };

	unsigned char md5hash[0x10] = { 0 };
	MD5_CTX md5Ctx = { 0 };
	MD5_Init(&md5Ctx);
	MD5_Update(&md5Ctx, (const void*)uin_ascii.c_str(), uin_ascii.length());
	MD5_Final(md5hash, &md5Ctx);

	char dbKey[0x100] = { 0 };
	for (int i = 0; i < 0x10; i++)
	{
		sprintf(&dbKey[i * 2], "%02x", md5hash[i]);
	}

	wstring dbKey_unicode = Ascii2Unicode(dbKey);
	SHA_CTX ctx = { 0 };
	
	SHA1_Init(&ctx);
	SHA1_Update(&ctx, (const void*)dbKey_unicode.c_str(), dbKey_unicode.length()*2);
	SHA1_Final(hash, &ctx);
	memcpy(desTestKey, hash, sizeof(desTestKey));

	wchar_t* infile = argv[1];
	wchar_t outfile[MAX_PATH] = { 0 };
	wsprintf(outfile, L"%s_plain", infile);

	FILE* fpdb = _wfopen(infile, L"rb+");
	if (!fpdb)
	{
		return 0;
	}
	fseek(fpdb, 0, SEEK_END);
	long nFileSize = ftell(fpdb);
	fseek(fpdb, 0, SEEK_SET);
	unsigned char* pDbBuffer = new unsigned char[nFileSize];
	fread(pDbBuffer, 1, nFileSize, fpdb);
	fclose(fpdb);

	DES_key_schedule schedule = { 0 };
	//void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);
	
	//void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output,
	//long length, DES_key_schedule* schedule,
	//	DES_cblock* ivec, int enc);
	DES_cblock ivec = { 0 };

	int pageSize = 0x400;
	int blockCnt = nFileSize / pageSize;

	unsigned char* output = (unsigned char*)malloc(pageSize);
	
	for (int i = 0; i < blockCnt; i++)
	{
		unsigned char* input = &pDbBuffer[i* pageSize];
		memset(output, 0, pageSize);

		DES_set_key_unchecked((const_DES_cblock*)(desTestKey), &schedule);

		DES_ncbc_encrypt(input,   output,
			pageSize, &schedule,
			&ivec, 0);

		FILE* fp = _wfopen(outfile, L"ab+");
		{
			fwrite(output, 1, pageSize, fp);
			fclose(fp);
		}
		memset(&ivec, 0, sizeof(ivec));
	}
	free(output);
}
解密 user.db, DB Browser (SQLite) 可以正常打开




2020安全开发者峰会(2020 SDC)议题征集 中国.北京 7月!

最后于 2019-10-14 15:54 被欧阳brother编辑 ,原因:
最新回复 (1)
mb_jrbhkper 2019-10-17 19:36
2
0
此楼层已删除
游客
登录 | 注册 方可回帖
返回