2014-02-08 46 views
1

我一直在探索Windows系统文件的来龙去脉,并且注意到一个好奇的东西:如果我执行一个Windows系统的低级按位副本 可执行文件到我选择的目标位置产生的文件小于原来的 。微软系统可执行副本的差异性

例子:我写了一个小程序复制无处不在的calc.exe可执行文件...

C:\test> copyit c:\windows\system32\calc.exe c:\test\calc.exe 

这是生成的文件:

C:\test>dir 
Volume in drive C is OS 
Volume Serial Number is DEAD-BEEF 

Directory of C:\test 

02/08/2014 03:37 PM <DIR>   . 
02/08/2014 03:37 PM <DIR>   .. 
02/08/2014 03:37 PM   798,720 calc.exe 
       1 File(s)  798,720 bytes 
       2 Dir(s) 291,059,347,456 bytes free 

这很有趣,因为找位于C :\ windows \ system32 \ calc.exe给我...

C:\test>dir c:\Windows\System32\calc.exe 
Volume in drive C is OS 
Volume Serial Number is DEAD-BEEF 

Directory of c:\Windows\System32 

08/22/2013 05:51 AM   922,112 calc.exe  <------Why is this larger? 
       1 File(s)  922,112 bytes 
       0 Dir(s) 291,059,322,880 bytes free 

为了您的观赏乐趣, “copyit”节目我在C++中写道:

int main(int argc, char* argv[]) 
{ 
    std::ifstream is(argv[0], std::ios::in | std::ios::binary); 
    std::ofstream os(argv[1], std::ios::out| std::ios::binary); 

    is.seekg(0, std::ios::end); 
    std::streampos size = is.tellg(); 
    is.seekg(0); 

    char* buffer = new char[(size_t)size]; 

    is.read(buffer, size); 
    os.write(buffer, size); 

    delete [] buffer; 

    os.close(); 
    is.close(); 

    return 0; 
} 

如果我在应用程序中设置断点并检查大小可变的所以tellg()调用之后我 看到798720.

???

请注意,生成的calc.exe不会在我的测试目录中运行,但如果我降低我的 UAC安全设置,它将运行。

有什么可以解释这种尺寸差异?一些软件与 system32 \ calc.exe捆绑的元数据?如果是这样,为什么我的小复制程序只复制 ,因为它在同一个文件中? Microsoft是否将TrustedInstaller 的某些证书​​捆绑使用?如果是这样,那么为什么我的小应用程序没有复制?

如果我用peexplorer看这两个文件...他们看起来正好是一样。与使用hexeditor的 相同。

使用Cywin的md5sum,这些文件导致不同的散列。

在其他非MS系统可执行文件上运行我的应用程序会产生完美副本,无论大小还是 哈希和可执行文件运行都不会触及UAC控件。

我重写了copyit使用CopyFile API ...相同的结果。还有_fopen()。同上。 我高度怀疑我遇到了一些未公开的安全功能。

+2

如果你打开文件为'binary',为什么要分配一个'wchar_t * buffer'?您正在尝试复制**二进制字节**,而不是**宽字符**。难怪文件不匹配(或散列相同)。 –

+0

请注意,文件可以包含备用数据流,但在检查文件大小时不会看到它。文件大小只适用于正常的数据流。请参阅[NTFS中的备用数据流](https://blogs.technet.com/b/askcore/archive/2013/03/24/alternate-data-streams-in-ntfs.aspx) – wimh

+1

优秀点@Ken White,然而请注意,将缓冲区更改为char *而不是wchar_t *仅具有这样的效果,即我不会将缓冲区分配为其所需大小的两倍。由于所有IO都是二进制模式,所以wchar_t没有任何作用(除了需要的两倍)。两个版本之间的结果校验和是相同的。然而,我会更新显示的代码来反映你的bug,因为它可以分散你手头的问题。 – user3288203

回答

4

您可能正在运行64位版本的Windows,并且您的程序是32位。当您在c:\Windows\System32中打开文件时,它将被重定向到C:\Windows\SysWOW64。所以你不是复制c:\windows\system32\calc.exe,而是C:\Windows\SysWOW64\calc.exe。我推断calc.exe的文件大小为798720.

另请参阅File System Redirector

+0

优秀答案@Wimmel!这似乎是这种情况。对不起,我没有要点票给你。 – user3288203