我一直在探索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()。同上。 我高度懷疑我遇到了一些未公開的安全功能。
如果你打開文件爲'binary',爲什麼要分配一個'wchar_t * buffer'?您正在嘗試複製**二進制字節**,而不是**寬字符**。難怪文件不匹配(或散列相同)。 –
請注意,文件可以包含備用數據流,但在檢查文件大小時不會看到它。文件大小隻適用於正常的數據流。請參閱[NTFS中的備用數據流](https://blogs.technet.com/b/askcore/archive/2013/03/24/alternate-data-streams-in-ntfs.aspx) – wimh
優秀點@Ken White,然而請注意,將緩衝區更改爲char *而不是wchar_t *僅具有這樣的效果,即我不會將緩衝區分配爲其所需大小的兩倍。由於所有IO都是二進制模式,所以wchar_t沒有任何作用(除了需要的兩倍)。兩個版本之間的結果校驗和是相同的。然而,我會更新顯示的代碼來反映你的bug,因爲它可以分散你手頭的問題。 – user3288203