这个补丁出来有几天了,以前没DIFF比较过,所以这次很感兴趣,欢迎指出错误。
由于IDA版本问题。用不起来BINDIFF,只好用DarunGrim了。也蛮强的,结果如下
改动较大的是这个:sub_147CF40A sub_147CF412 6
又是添加又是修改,我们近IDA看,整理后,如下
代码:
signed int __thiscall sub_147CF40A(void *this, int temp2) { ...... v19 = this; result_1 = 0; if ( temp2 ) { src_copy = temp2 + 16; if ( *temp2 == 'ilaV' && (parm1 = *(temp2 + 4), parm1_ = *(temp2 + 4), parm2 = *(temp2 + 8), parm2 <= 512) ) { // Vali offset = 0; v21 = 0; if ( parm1 > 0 ) { while ( v21 < 128 ) { total_size_ = *(src_copy + 16); v5 = total_size_ + offset; total_size = *(src_copy + 16); // 拷贝大小 offset += total_size_; if ( total_size_ < 0 || v5 < 0 || v5 > parm2 ) { result_1 = -2147024809; break; } mem_address = alloc_bstr_0x20u(); mem_address_ = mem_address; mem_address__ = mem_address; if ( !mem_address ) { result_1 = -2147024882; goto error; } result_1 = adapt_new_mem(mem_address, *src_copy, *(src_copy + 4), 0); if ( result_1 < 0 ) goto error; data_size = total_size_ - 32; if ( total_size_ - 32 > 0 ) { length = (data_size + 1) >> 1; // BSTR长度 BSTR_address = SysAllocStringLen_(&bstrString, (data_size + 1) >> 1); parm3 = (mem_address_ + 24); sub_147CE7E8(parm3, BSTR_address); SysFreeString(bstrString); // if ( !*v12 || !SysStringLen(*v12) ){error!} (*parm3)[length - 1] = 0; // V11 指针? memcpy(*parm3, (src_copy + 32), total_size - 32); SysStringByteLen(*parm3); SysStringByteLen(*parm3); total_size_ = total_size; mem_address_ = mem_address__; } sub_147CF06A(mem_address_); src_copy += total_size_; ++v21; if ( v21 >= parm1_ ) break; } if ( result_1 >= 0 ) goto LABEL_21; error: sub_147CF3EE(v19); } LABEL_21: result = result_1; } else { result = -2147024809; } } else { result = -2147024809; } return result; }
代码:
signed int __thiscall sub_147CF412(void *this, int temp2) { ..... v19 = this; result_1 = 0; if ( temp2 ) { check_file = *temp2 == 'ilaV'; src_copy_ = temp2 + 16; src_copy = temp2 + 16; if ( check_file && (parm1 = *(temp2 + 4), parm1_ = *(temp2 + 4), parm2 = *(temp2 + 8), parm2 <= 512) ) { offset = 0; v22 = 0; if ( parm1 > 0 ) { while ( v22 < 128 ) { total_size = *(src_copy_ + 16); v6 = total_size + offset; v14 = *(src_copy_ + 16); offset += total_size; if ( total_size < 0 || v6 < 0 || v6 > parm2 ) { result_1 = -2147024809; break; } mem_address = alloc_bstr_0x20u(); mem_address_ = mem_address; mem_address__ = mem_address; if ( !mem_address ) goto error; result_1 = adapt_new_mem(mem_address, *src_copy_, *(src_copy_ + 4), 0);//传递地址 if ( result_1 < 0 ) goto LABEL_21; data_size = total_size - 32; // 拷贝大小 if ( data_size > 0 ) { BSTR_address = SysAllocStringLen_(&bstrString, (data_size + 1) >> 1); parm3 = (mem_address_ + 24);//可控参数,直接读文件 sub_147CE7F0(parm3, BSTR_address);//进去!!!,此函数修改了 SysFreeString(bstrString); if ( !*parm3 || !SysStringLen(*parm3) )//这里!!补丁添加的校验 { error: result_1 = -2147024882; goto LABEL_21; } (*parm3)[((data_size + 1) >> 1) - 1] = 0; memcpy(*parm3, (src_copy + 32), data_size); SysStringByteLen(*parm3); SysStringByteLen(*parm3); src_copy_ = src_copy; mem_address_ = mem_address__; } sub_147CF072(mem_address_); src_copy_ += v14; ++v22; src_copy = src_copy_; if ( v22 >= parm1_ ) break; }
这个parm3怎么来的呢。我们网上看到如此字样:
check_file = *temp2 == 'ilaV';
src_copy_ = temp2 + 16;
同时随便找一个样本文件打开,这里用的是http://samples.mplayerhq.hu/dvr_ms/microsoft-new-way-to-shove-mpeg2-in-asf.dvr-ms
成功查找到如下字段
我们在进
sub_147CE7F0(parm3, BSTR_address);看一看
改动影响不大。于是,
memcpy(*parm3, (src_copy + 32), total_size - 32);3个参数都可控,任意地址写任意数据最终造成漏洞
附件为encdec.dll 补丁前后