0x00
最近在维护一个工程代码,因为对可执行文件兼容性的要求,我们就没有链接msvcr* 库。今天增加了一个新功能,编译运行时,提示找不到 msvcr90.dll,直接退出了。
使用删减代码的方法,确定了出问题的代码。
伪码如下:
BOOL bRtn = FALSE;
struct A a = {0};
struct B b;
bRtn = funcA(b.x,b.y,0,&a);
if (!bRtn || !a.x || !a.y) {
return FALSE;
}
funcB(...);
funcC(...);
return bRtn;
0x01
仔细检查了funcA,funcB与funcC,都没有看到msvcr库导出的函数。不过因为自认为funcA的嫌疑最大,所以先拿funcA开刀。
找到funcA声明的头文件,找了一个同类的函数 funcD。将代码修改为:
BOOL bRtn = FALSE;
struct A a = {0};
struct B b;
funcD(b.x);
if (!bRtn || !a.x || !a.y) {
return FALSE;
}
funcB(...);
funcC(...);
return bRtn;
编译运行后,发现一切正常。当前怀疑是不是因为bRtn 没有使用到,所以编译器将整个代码优化成如下:
BOOL bRtn = FALSE;
struct A a = {0};
struct B b;
funcD(b.x);
return FALSE;
所以,应该是funcB与funcC导致的问题。
不过等将funcB与funcC全部注释以后,重新将代码修改为funcA调用,还是存在问题。
这就很奇怪了。
0x02
继续检查代码,发现其实struct A a也是可能被优化的,a在funcD中未使用,所以应该也被优化了。
将代码修改为如下:
BOOL bRtn = FALSE;
struct A a = {0};
struct B b;
funcD(&a);
if (!bRtn || !a.x || !a.y) {
return FALSE;
}
funcB(...);
funcC(...);
return bRtn;
发现又弹框了。完美。
0x03
其实到这里,问题基本找到了。struct A a = {0}; 语句,编译器使用的是memset来置0的,将exe拖入IDA,发现果然如此。
使用自己编写的memset之后,问题解决。