Does anyone have a simple method of determining whether the running EXE has been modified? With or without code signing, Windows doesn’t help.
For example, I did a search and replace on Clarion.exe and changed “SoftVelocity” to “HardVelocity” and nothing complained when I ran the EXE. If you inspect the code signing certificate, it says it’s invalid, but the program runs anyway. So why bother with code signing if it can’t detect modified code? No wonder viruses can modify executables with impunity!
So firstly, yes, exe’s can be changed without windows complaining. Your program needs to explicitly check the certificate on startup if you want to prevent that. I don’t have the code to do that to hand, but Wolfgang did a webinar on this, and posted code to the newsgroup.
ClarionLive #503, #512 and #515. Thanks.
Then there’s this: Masquerading as a Windows System Binary Using Digital Signatures
I’m curious to know whether a self-signed certificate triggers an alarm in the Ultimate Code Sign Checker. Has anyone tried it?
20+ years ago, before code signing certificates were a thing, we had a similar requirement from the Venezuelan government to ensure our code for dealing with fiscal printers hadn’t been tampered with.
IIRC we came up with a post-compile process that used extra fields in the MZ DOS header of the executable to store the current date & time. Then when the application ran it checked the timestamp we added against the date/time the OS had for the file and if they were different it refused to run
Is there a third party app that can be used to warn if I launch a signed app that has been modified?
Or a whitelisting program for Windows? I don’t have secpol.msc
There may be a reasonable way to implement this as a class and template. There should be a Checksum written into the PE Header by the Linker every build.
Checksum: The image file checksum. The algorithm for computing the checksum is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all Drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process.
The Checksum is Not required to be correct nor checked for ordinary binaries, as noted above, only Drivers and critical.
Maybe @also can confirm if the Clarion Linker follows the Microsoft standard. The below link gives the code for the Checksum algorithm (not sure it is correct). And it discusses it’s use for spotting malware.
Note: I don’t think this method is not going to work for digitally signed binaries because the signature is part of the file added after the Linker calculated. Also malware could update the Linker Checksum in the header.
Clarification: I’m looking for a program that can inspect ANY EXE or DLL that has been signed and tell me if it has been tampered with. I have the template that can tell if my (signed) application is broken when it runs.
The closest I can find is Airlock Digital but it isn’t open source
You can use SignTool, but I think MS is weird about distributing it. That’s why SetupBuilder has a menu choice to install it from the MS site.
As Bruce said, there is code in the Newsgroup for this.
Graham Dawson posted this sample (thanks Graham) which does exactly as you request, ie: can check any file.
Clarion-Demo-Verify-Code-Signing.zip (16.4 KB)
@CarlBarnes “There should be a Checksum written into the [PE Header] by the Linker every build.”
A long time ago the CW linker used it’s own checksum. When I complained about it (probably to Ole or Richard Chapman, but I forget who) they didn’t care. Don’t know if that’s changed by now.
I knew I saw that somewhere. Thanks Julian and @Graham_Dawson
FWIW, in case anyone is interested the IQCQO.DLL that the example app ships with appears to be a C DLL that’s “just” a wrapper around the WinVerifyTrust() API call using the WINTRUST_ACTION_GENERIC_VERIFY_V2 GUID
I wrote this before @PaulAttryde posted about IQCQO.
That relies on 2 functions
The IQCQO DLL properties shows No Details and No Digital Signature. Did @Graham_Dawson say the source of that DLL? Seems like a bad idea to check security using an unknown unsigned DLL.
ReturnSigningInfo(const *cstring inFilename,*cstring outputStr,*long bufferSize),long,C,raw,name('ReturnSigningInfo')
VerifySignature(const *cstring inFilename,*cstring outputStr,*long bufferSize),long,C,raw,name('VerifySignature')
... CODE ...
bufferSizeNeeded = size(CStrBuffer)
result = VerifySignature(filename,CStrBuffer,bufferSizeNeeded)
Message('Error ' & CStrBuffer,filename)
IF CStrBuffer <> 'The file is not signed<13,10>'
bufferSizeNeeded = size(CStrBuffer)
result = ReturnSigningInfo(filename,CStrBuffer,bufferSizeNeeded)
message('Error ' & CStrBuffer,filename)