逆向XX引擎:库文件解密
2008 年 9 月 19 日
火绒所有的库文件都使用同一种方法解密的,具体解密算法都是在libxsse_30中实现的.
数据库头部数据都是通用的,结构如下:
struct database_header { _DWORD DRAV; _DWORD SFHY; _WORD lowVersion; _WORD hiVersion; _QWORD timeStamp; _DWORD db_attr; _DWORD recordCount; _DWORD propSize; _DWORD origin_size; //未加密前的数据大小 _DWORD compress_size;//zlib压缩数据的大小 _DWORD key2[32]; char dbName[8]; _DWORD end[4];//0结尾 };
pset.db的如图
dbName是数据库的类型,找了几个库看了下,发现有如下几种
DB:RAW 解密后就是原始数据 DB:HWL和DB:TROJ 是hash类的特征,格式比较简单 DB:PSET和DB:PROP 特征库,解密后数据是按照一定格式组织的
读取头部0xc0个字节。
database_header* dh = &a1->db; int readytes = stream->pread(a2, dh, 0xC0); if (!readytes) return 0; if (readytes != 0xc0) return -5;
首先判断是不是火绒的病毒库,通过文件magic
//判断db文件的magic
if (dh->DRAV != 'DRAV' || dh->SFHY != 'SFHY' || a3 && (_WORD)(a3 + 2) != HIWORD(a1->db.lowVersion))
return -9;
简单的异或生成另一个key。然后生成的key再通过gen_new_xor_key函数算法生成另一个key。这个函数比较复杂就不说了。
unsigned char g_xor_key[260] = { 0x42, 0xE6, 0x70, 0x7B, 0x08, 0x64, 0x27, 0x04, 0xFD, 0x7C, 0xC2, 0x73, 0x6C, 0x8A, 0x1B, 0x8F, 0x0C, 0x36, 0x1E, 0x3C, 0x91, 0x10, 0x28, 0x28, 0x8C, 0xD1, 0xD7, 0x4D, 0x5D, 0x93, 0xEB, 0x0D, 0xC2, 0x16, 0xDA, 0xBC, 0x5C, 0xA8, 0x1A, 0xD9, 0x45, 0xD4, 0xE9, 0x03, 0x47, 0x85, 0x77, 0x35, 0x6E, 0x92, 0xF5, 0x24, 0x6E, 0x4D, 0xFA, 0x9A, 0x12, 0xC8, 0x3B, 0x91, 0x35, 0xFA, 0x21, 0x41, 0x13, 0xF5, 0x26, 0x89, 0xF5, 0xC3, 0x03, 0x93, 0xC6, 0x81, 0x1D, 0xA0, 0xF4, 0xA1, 0x48, 0x1A, 0x77, 0xC6, 0xD7, 0xD8, 0xE4, 0xA7, 0x3C, 0x96, 0x6E, 0x73, 0xA6, 0xDD, 0xD9, 0xB5, 0x6D, 0x38, 0x4D, 0x28, 0xB9, 0xC9, 0x63, 0x6C, 0x9C, 0x54, 0x74, 0x00, 0xAC, 0xC9, 0x67, 0xD2, 0x8B, 0x14, 0xB5, 0x26, 0xBE, 0x1F, 0x5A, 0xB1, 0xDE, 0xFB, 0xEB, 0xE9, 0x18, 0xF3, 0x7A, 0xF3, 0x0B, 0xC8, 0x47, 0x42, 0x64, 0xC6, 0xC8, 0x81, 0x2B, 0x2A, 0xB2, 0xC6, 0xCB, 0x5B, 0x6B, 0xF6, 0x9C, 0x99, 0x4D, 0x45, 0x6C, 0xF8, 0x04, 0x85, 0x30, 0x2E, 0xCC, 0xFA, 0xE9, 0x1F, 0x85, 0x3B, 0x2E, 0x5C, 0x0A, 0x7F, 0x10, 0x07, 0xB8, 0xAA, 0xAF, 0xB1, 0xCB, 0x07, 0x1E, 0xEE, 0xFA, 0x4E, 0xD9, 0x1D, 0xB5, 0x45, 0x98, 0x2C, 0x04, 0x8C, 0x6B, 0x6A, 0xD8, 0xCA, 0x39, 0xA4, 0x8E, 0x3C, 0xD9, 0x97, 0xF1, 0xDC, 0x7C, 0x6A, 0x65, 0xF1, 0x85, 0x1A, 0xA3, 0xBE, 0xFB, 0xC3, 0x1C, 0x67, 0x24, 0x88, 0x5D, 0xCD, 0x62, 0x10, 0x8D, 0xB4, 0xA1, 0xDE, 0xFC, 0x62, 0x91, 0x87, 0x3A, 0x2B, 0x3E, 0x33, 0x9B, 0x0C, 0xE3, 0x61, 0x03, 0x49, 0xCE, 0x16, 0xAB, 0xFE, 0x07, 0xDF, 0x9C, 0xBF, 0x68, 0x84, 0xC5, 0x5C, 0xA1, 0xAD, 0x00, 0x0D, 0xE8, 0x12, 0x41, 0xF2, 0x21, 0xDB, 0xB6, 0xA3, 0x26, 0x81, 0x47, 0xDD, 0xF4, 0xA3 }; //异或计算key char key1[260] = {}; memcpy(key1, g_xor_key, sizeof(g_xor_key)); for (int i = 0; i db.key2, 0x80, key1);
现在开始解密被加密的数据,使用最后生成的key
void* origin_buffer = malloc(a1->db.origin_size); if (!origin_buffer) return -12; int compress_size = a1->db.compress_size; if (compress_size) { //!压缩的数据先异或解密 char* compress_buf = (char*)malloc(compress_size); if (!compress_buf) return -1; //读取压缩数据, 在文件偏移0xc0 stream->pread(a2, compress_buf, compress_size); //异或解密数据 if (a1->db.db_attr >= 0x80000000 && compress_size) { for (int i = 0; i db.compress_size); //unsigned char sha1[0x14] = {}; //rhash_sha1_final(&ctx, (unsigned char*)& sha1); ////////////////////////////////////////////////////////////////////////// //!原代码还会比较sha1和xor_gen_key的前0x10字节是否相同,去掉了 if (a1->db.db_attr & 0x40000000) { //zlib解压 rt = uncompress((Bytef*)origin_buffer, (uLongf*)& a1->db.origin_size, (Bytef*)compress_buf, compress_size); } /////将解压的文件写入文件 }
uncompress是zlib的解压缩函数,只要hook这个地方就能把解密后的数据dump出来
纯属好玩
扫码打赏,你说多少就多少


打开 支付宝 扫一扫,即可进行扫码打赏哦