最近在用C3dServer将一些文本格式的marker点数据转换为.c3d格式,可是marker点的名称一直没法很好地设置。本来这个名称是存储在Group/POINT/LABELS里面的,可是默认的名称长度只有6,所以只能用AddParameter重建这个参数。可是我一直没重建成功,代码如下:
int iLabelNameId = p->GetParameterIndex(_bstr_t(L"Point"), _bstr_t(L"Labels"));nRes = p->DeleteParameter(iLabelNameId);
int nRes = p->AddParameter(BSTR(L"LABELS"), BSTR(L"Marker Names"), BSTR(L"POINT"), 0, -1, 2, varDims, varMNames);
VARIANT varDims;
{
int *pDim = NULL;
VariantInit( &varDims );
SAFEARRAY *psaDim = SafeArrayCreateVector(VT_INT, 0, 2 );
pDim[0] = 64; pDim[1] = 32;
SafeArrayUnaccessData( psaDim );
varDims.vt = VT_ARRAY | VT_INT;
varDims.parray = psaDim;
}
今天用IDA调试了一下,终于发现了问题。
v32 = psa;
if ( SafeArrayGetLBound(psa, 1u, &plLbound) < 0 )
SafeArrayGetUBound(v32, 1u, &plUbound);
SafeArrayAccessData(v32, &ppvData);
if ( v32->rgsabound[0].cElements >= (unsigned int)v29 )
{
for ( j = 0; j < (signed int)v29; ++j )
{
v34 = *((_WORD *)ppvData + j);
if ( v34 >= 0 )
*(_BYTE *)(*(_DWORD *)(v27 + 52) + j) = v34;
}
}
SafeArrayUnaccessData(v32);
这是IDA反编译出来的C代码(sub_10004CCE)。可以看到它用的是_WORD,所以把varDims从int改为short就可以了。
关于C3dServer的破解:搜索Sleep函数就可以找到相应地址,nop掉即可。还可以用RegOpenKey找到sub_1000248C函数,将line 142 *(_DWORD *)(v7 + 304) = 1;中的1改为2。64位类似。
关于IDA:IDA没有自带64位的调试器,需要安装WinDbg,挺麻烦的。而且IDA调试不支持查看内存,无法设置内存断点,只能配合VS使用。另外发现一个反汇编的网站挺好用的:https://www.onlinedisassembler.com/odaweb/,支持64位。