如果比较原始/解压文件的哈希值,则它们是不同的,因为upx -d不会逐位还原原始文件。实际上,UPX解析原始文件并仅保留信息,以便解压后的打包数据可以与原始文件完全相同地执行,即原始/解压文件在语义上等效但在物理上不等效^^。
这是可以理解的,因为存在不影响二进制文件执行的信息,一个简单的例子是 DOS 存根结束和 PE 头开始之间的数据。更详细的可以参考pack类的功能,例如PE的PackW32Pe(in p_w32pe.h/cpp)和unpack类的功能Packer(in packer.h/cpp)。
例如,我们可以看到UPX使用以下代码修改了解压文件的(DOS和PE)头(为了更容易理解,我重新命名了一些变量)。首先,它解压缩并提取标头:
// decompress
decompress(input_buffer, output_buffer);
upx_byte *extrainfo = output_buffer + get_le32(output_buffer + ph.u_len - 4);
memcpy(&output_header, extrainfo, sizeof (output_header));
然后稍微修改标题:
...
output_header.headersize = rvamin;
output_header.chksum = 0;
//NEW: disable reloc stripping if ASLR is enabled
if(input_header.dllflags & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE)
opt->win32_pe.strip_relocs = false;
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
if ((opt->win32_pe.strip_relocs && !isdll) || (input_header.flags & RELOCS_STRIPPED))
{
output_header.flags |= RELOCS_STRIPPED;
ODADDR(PEDIR_RELOC) = 0;
ODSIZE(PEDIR_RELOC) = 0;
}
// write decompressed file
if (output_file)
{
...