Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building: Windows: Set EXE checksums (#5579). #5580

Merged
merged 1 commit into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions PyInstaller/building/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ def assemble(self):
logger.info("Fixing EXE for code signing %s", self.name)
import PyInstaller.utils.osx as osxutils
osxutils.fix_exe_for_code_signing(self.name)
if is_win:
# Set checksum to appease antiviral software.
from PyInstaller.utils.win32.winutils import set_exe_checksum
set_exe_checksum(self.name)

os.chmod(self.name, 0o755)
# get mtime for storing into the guts
Expand Down
14 changes: 14 additions & 0 deletions PyInstaller/utils/win32/winutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,17 @@ def convert_dll_name_to_str(dll_name):
return str(dll_name, encoding='UTF-8')
else:
return dll_name


def set_exe_checksum(exe_path):
"""Set executable's checksum in its metadata.

This optional checksum is supposed to protect the executable against
corruption but some anti-viral software have taken to flagging anything
without it set correctly as malware. See issue #5579.
"""
import pefile
pe = pefile.PE(exe_path)
pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
pe.close()
pe.write(exe_path)
2 changes: 2 additions & 0 deletions bootloader/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ def set_arch_flags(ctx):
ctx.env.append_value('CFLAGS', '/D_CRT_SECURE_NO_WARNINGS')
# We use SEH exceptions in winmain.c; make sure they are activated.
ctx.env.append_value('CFLAGS', '/EHa')
# Set the PE checksum on resulting binary
ctx.env.append_value('LINKFLAGS', '/RELEASE')

# Ensure proper architecture flags on Mac OS X.
elif ctx.env.DEST_OS == 'darwin':
Expand Down
1 change: 1 addition & 0 deletions news/5579.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Windows: Set EXE checksums. Reduces false-positive detection from antiviral software.
21 changes: 21 additions & 0 deletions tests/functional/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,24 @@ def test_several_scripts2(pyi_builder_spec):
Verify each script has it's own global vars (basic test).
"""
pyi_builder_spec.test_spec('several-scripts2.spec')


@pytest.mark.win32
def test_pe_checksum(pyi_builder):
import ctypes
from ctypes import wintypes

pyi_builder.test_source("print('hello')")
exes = pyi_builder._find_executables('test_source')
assert exes
for exe in exes:
# Validate the PE checksum using the official Windows API for doing so.
# https://docs.microsoft.com/en-us/windows/win32/api/imagehlp/nf-imagehlp-mapfileandchecksumw
header_sum = wintypes.DWORD()
checksum = wintypes.DWORD()
assert ctypes.windll.imagehlp.MapFileAndCheckSumW(
ctypes.c_wchar_p(exe),
ctypes.byref(header_sum),
ctypes.byref(checksum)) == 0

assert header_sum.value == checksum.value