https://bugs.winehq.org/show_bug.cgi?id=36257
Bug ID: 36257 Summary: Gears of War fails on startup, reporting 'binkw32.dll: You cannot run the game with modified executable code. Please reinstall the game.' (WINTRUST_FILE_INFO file handle member not reset on cleanup when opened internally) Product: Wine Version: 1.7.17 Hardware: x86 OS: Linux Status: NEW Severity: normal Priority: P2 Component: wintrust Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net
Hello folks,
as the summary says.
No, this is not the infamous mess up that hit everyone who bought this game in Jan 2009: https://support.microsoft.com/kb/967644
(the original PE executables carry an Authenticode Signature with an expiry date Jan 29, 2009)
Unfortunately, even with the re-signed/updated executables the message is still shown.
Relevant part of trace log:
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/Gears of War/Binaries
$ WINEDEBUG=+tid,+seh,+relay,+wintrust wine ./Startup.exe >>log.txt 2>&1 ... 0027:Call wintrust.WinVerifyTrust(00000000,024af720,024af6f0) ret=00f78780 0027:trace:wintrust:WinVerifyTrust ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) 0027:trace:wintrust:dump_wintrust_data 0x24af6f0 0027:trace:wintrust:dump_wintrust_data cbStruct: 48 0027:trace:wintrust:dump_wintrust_data pPolicyCallbackData: (nil) 0027:trace:wintrust:dump_wintrust_data pSIPClientData: (nil) 0027:trace:wintrust:dump_wintrust_data dwUIChoice: 2 0027:trace:wintrust:dump_wintrust_data fdwRevocationChecks: 00000000 0027:trace:wintrust:dump_wintrust_data dwUnionChoice: 1 0027:trace:wintrust:dump_file_info 0x24af6d4 0027:trace:wintrust:dump_file_info cbStruct: 16 0027:trace:wintrust:dump_file_info pcwszFilePath: L"C:\Program Files\Gears of War\Binaries\WarGame-G4WLive.exe" 0027:trace:wintrust:dump_file_info hFile: (nil) 0027:trace:wintrust:dump_file_info pgKnownSubject: (null) 0027:trace:wintrust:dump_wintrust_data dwStateAction: 0 0027:trace:wintrust:dump_wintrust_data hWVTStateData: (nil) 0027:trace:wintrust:dump_wintrust_data pwszURLReference: (null) 0027:trace:wintrust:dump_wintrust_data dwProvFlags: 00000100 0027:trace:wintrust:dump_wintrust_data dwUIContext: 0 ... 0027:Call wintrust.CryptSIPGetSignedDataMsg(0016c5b8,0016c3e8,00000000,024af420,00000000) ret=7de26f02 0027:trace:wintrust:CryptSIPGetSignedDataMsg (0x16c5b8 0x16c3e8 0 0x24af420 (nil)) 0027:trace:wintrust:WINTRUST_GetSignedMsgFromPEFile (0x16c5b8 0x16c3e8 0 0x24af420 (nil)) ... 0027:trace:wintrust:WINTRUST_GetTimeFromSigner returning time from message 1/29/2009 0027:trace:wintrust:WINTRUST_AddSgnr (0x16c3b0, 0, 0, 0x24af414) ... 0027:trace:wintrust:WINTRUST_AddCert (0x16c3b0, 0, 0, 0, 0x4eda754) ... 0027:Call crypt32.CertVerifyCertificateChainPolicy(00000002,04ed8ac0,024af440,024af464) ret=7debb243 0027:Ret crypt32.CertVerifyCertificateChainPolicy() retval=00000001 ret=7debb243 0027:trace:wintrust:SoftpubAuthenticode returning 0 (00000000) 0027:Ret wintrust.SoftpubAuthenticode() retval=00000000 ret=7debc27a 0027:trace:wintrust:WINTRUST_DefaultVerify returning 00000000 0027:trace:wintrust:WINTRUST_DefaultClose ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) 0027:Call wintrust.SoftpubCleanup(0016c3b0) ret=7debc7a4 ... 0027:trace:wintrust:WINTRUST_DefaultClose returning 00000000 0027:trace:wintrust:WINTRUST_DefaultVerifyAndClose returning 00000000 0027:trace:wintrust:WinVerifyTrust returning 00000000 0027:Ret wintrust.WinVerifyTrust() retval=00000000 ret=00f78780 --- snip ---
The first file 'C:\Program Files\Gears of War\Binaries\WarGame-G4WLive.exe' is successfully validated.
The second file 'binkw32.dll' fails ...
--- snip --- 0027:Call wintrust.WinVerifyTrust(00000000,024af720,024af6f0) ret=00f78780 0027:trace:wintrust:WinVerifyTrust ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) 0027:trace:wintrust:dump_wintrust_data 0x24af6f0 0027:trace:wintrust:dump_wintrust_data cbStruct: 48 0027:trace:wintrust:dump_wintrust_data pPolicyCallbackData: (nil) 0027:trace:wintrust:dump_wintrust_data pSIPClientData: (nil) 0027:trace:wintrust:dump_wintrust_data dwUIChoice: 2 0027:trace:wintrust:dump_wintrust_data fdwRevocationChecks: 00000000 0027:trace:wintrust:dump_wintrust_data dwUnionChoice: 1 0027:trace:wintrust:dump_file_info 0x24af6d4 0027:trace:wintrust:dump_file_info cbStruct: 16 0027:trace:wintrust:dump_file_info pcwszFilePath: L"binkw32.dll" 0027:trace:wintrust:dump_file_info hFile: 0x12c 0027:trace:wintrust:dump_file_info pgKnownSubject: (null) 0027:trace:wintrust:dump_wintrust_data dwStateAction: 0 0027:trace:wintrust:dump_wintrust_data hWVTStateData: (nil) 0027:trace:wintrust:dump_wintrust_data pwszURLReference: (null) 0027:trace:wintrust:dump_wintrust_data dwProvFlags: 00000100 0027:trace:wintrust:dump_wintrust_data dwUIContext: 0 0027:trace:wintrust:WINTRUST_DefaultVerifyAndClose ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) 0027:trace:wintrust:WINTRUST_DefaultVerify ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) ... 0027:Call wintrust.SoftpubInitialize(0016cc90) ret=7debc27a 0027:trace:wintrust:SoftpubInitialize (0x16cc90) 0027:trace:wintrust:SoftpubInitialize returning 00000000 0027:Ret wintrust.SoftpubInitialize() retval=00000000 ret=7debc27a 0027:Call wintrust.SoftpubLoadMessage(0016cc90) ret=7debc27a 0027:trace:wintrust:SoftpubLoadMessage (0x16cc90) 0027:Call KERNEL32.GetFileTime(0000012c,0016ccf0,00000000,00000000) ret=7deb8a5c 0027:Ret KERNEL32.GetFileTime() retval=00000000 ret=7deb8a5c 0027:trace:wintrust:SOFTPUB_OpenFile returning 0 0027:Call crypt32.CryptSIPRetrieveSubjectGuid(03a618c0 L"binkw32.dll",0000012c,0016e2dc) ret=7deb8b27 0027:Call KERNEL32.SetFilePointerEx(0000012c,00000000,00000000,024af328,00000001) ret=7de25ce2 0027:Ret KERNEL32.SetFilePointerEx() retval=00000000 ret=7de25ce2 0027:Call KERNEL32.SetFilePointer(0000012c,00000000,00000000,00000000) ret=7de25d08 0027:Ret KERNEL32.SetFilePointer() retval=ffffffff ret=7de25d08 0027:Call KERNEL32.ReadFile(0000012c,024af324,00000004,024af338,00000000) ret=7de25d37 0027:Ret KERNEL32.ReadFile() retval=00000000 ret=7de25d37 0027:Call KERNEL32.SetFilePointerEx(0000012c,7bcd1000,7bc3b401,00000000,00000000) ret=7de265e5 0027:Ret KERNEL32.SetFilePointerEx() retval=00000000 ret=7de265e5 0027:Ret crypt32.CryptSIPRetrieveSubjectGuid() retval=00000000 ret=7deb8b27 0027:Call KERNEL32.GetFileSizeEx(0000012c,024af420) ret=7deb8b58 0027:Ret KERNEL32.GetFileSizeEx() retval=00000000 ret=7deb8b58 0027:trace:wintrust:SOFTPUB_GetFileSubject returning 6 0027:trace:wintrust:SoftpubLoadMessage returning 1 (00000006) 0027:Ret wintrust.SoftpubLoadMessage() retval=00000001 ret=7debc27a 0027:trace:wintrust:WINTRUST_DefaultVerify returning 00000006 0027:trace:wintrust:WINTRUST_DefaultClose ((nil), {00aac56b-cd44-11d0-8cc2-00c04fc295ee}, 0x24af6f0) 0027:Call wintrust.SoftpubCleanup(0016cc90) ret=7debc7a4 ... 0027:trace:wintrust:WINTRUST_DefaultClose returning 00000000 0027:trace:wintrust:WINTRUST_DefaultVerifyAndClose returning 00000006 0027:trace:wintrust:WinVerifyTrust returning 00000006 0027:Ret wintrust.WinVerifyTrust() retval=00000006 ret=00f78780 ... 0027:Call user32.MessageBoxW(00000000,024a773c L"binkw32.dll: You cannot run the game with modified executable code. Please reinstall the game.",01915d30 L"Message",00001000) ret=00f78081 --- snip ---
The data structure passed to WinVerifyTrust() is fully reused on subsequent calls. Only the filename is changed, all other members remain untouched - including the file handle value.
Wine's wintrust set the 'hFile' member during processing of the first file but forgot to reset the value upon return (in non-error case).
Since Wine checks the handle for NULL or INVALID_HANDLE_VALUE it assumes the client passed a valid handle (which is not true because the client never dealt with handles).
All file related API calls subsequently fail on the second PE image (returning 'FALSE'), indicated by lasterror 0x6 (invalid handle).
Source: http://source.winehq.org/git/wine.git/blob/ba78b54820b5a5cdb4cdcfb5556b35781...
--- snip --- 76 /* Assumes data->pWintrustData->u.pFile exists. Makes sure a file handle is 77 * open for the file. 78 */ 79 static DWORD SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data) 80 { 81 DWORD err = ERROR_SUCCESS; 82 83 /* PSDK implies that all values should be initialized to NULL, so callers 84 * typically have hFile as NULL rather than INVALID_HANDLE_VALUE. Check 85 * for both. 86 */ 87 if (!data->pWintrustData->u.pFile->hFile || 88 data->pWintrustData->u.pFile->hFile == INVALID_HANDLE_VALUE) 89 { 90 data->pWintrustData->u.pFile->hFile = 91 CreateFileW(data->pWintrustData->u.pFile->pcwszFilePath, GENERIC_READ, 92 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 93 if (data->pWintrustData->u.pFile->hFile != INVALID_HANDLE_VALUE) 94 data->fOpenedFile = TRUE; 95 else 96 err = GetLastError(); 97 } 98 if (!err) 99 GetFileTime(data->pWintrustData->u.pFile->hFile, &data->sftSystemTime, 100 NULL, NULL); 101 TRACE("returning %d\n", err); 102 return err; 103 } --- snip ---
Problem:
http://source.winehq.org/git/wine.git/blob/ba78b54820b5a5cdb4cdcfb5556b35781...
--- snip --- 1180 HRESULT WINAPI SoftpubCleanup(CRYPT_PROVIDER_DATA *data) 1181 { ... 1206 1207 CryptMsgClose(data->hMsg); 1208 1209 if (data->fOpenedFile && 1210 data->pWintrustData->dwUnionChoice == WTD_CHOICE_FILE && 1211 data->pWintrustData->u.pFile) 1212 CloseHandle(data->pWintrustData->u.pFile->hFile); 1213 1214 return S_OK; 1215 } --- snip ---
If you close the handle you need to reset the handle value too.
I already tested a fix which lets the signature validation of all PE files succeed. This allows the game to run further - only to run into next problem.
Regards