RE: WinVerifyTrust Failure on WinXP



Hi,

The fact that it's working on a Vista PC doesn't give you the guarantee that
it will work on all Vista platforms: this is a well know stability issue on
Windows OSs and it will show up sooner or later on production systems, so you
should definitely take it into account.

Forcing users to call a global initialization function is obvious : before
calling any function, you check that a global flag has been set (in a global
variable for example). This flag will only be set if the user has called the
initialization function. If this flag is missing, then all the functions will
fail.

This mechanism has the same security as the one involving DllMain but it's
guaranteed to work in all platforms and all situations.

Do you see any issues with that?

Cheers,


--
Mounir IDRASSI
IDRIX
http://www.idrix.fr

To reach me: mounir_idrix_fr (replace the underscores with the at and dot
characters respectively)


"scharan" wrote:

Hi.

Yes. WinVerifyTrust is called in __DllMain(). I dont want to leave it to
application programmers to call init functions. Is there some way to force
them to call init function? Cos this step is absolutely mandatory for our
application.

Note that this is not working ONLY on Windows XP. It works perfectly as
expected in Windows Vista.

Here is the sample code. VerifyEmbeddedSignature() is called in __DllMain()

BOOL VerifyEmbeddedSignature()
{
DWORD dwLastError;

//get the name of the executable who is loading me.
TCHAR szModuleFile[MAX_PATH] = {0};
HMODULE mDllMod = reinterpret_cast<HMODULE>(&__ImageBase);
int x = WIN::GetModuleFileName(mDllMod, szModuleFile, MAX_PATH);
MessageBox(NULL, szModuleFile, _T("DLL Loaded by(using
GetModuleFileName)"), MB_OK | MB_ICONEXCLAMATION);

//WIN::GetModuleHandle( szModuleFile );
//MessageBox(NULL, szModuleFile, _T("DLL Loaded by(using
GetModuleHandle)"), MB_OK | MB_ICONEXCLAMATION);

itvEnum itv = itvUnTrusted;
GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;

WINTRUST_FILE_INFO sWintrustFileInfo;
WINTRUST_DATA sWintrustData;
HRESULT hr;

memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO)); //
zero out
memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA)); // zero out

sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
sWintrustFileInfo.pcwszFilePath = szModuleFile;
sWintrustFileInfo.hFile = NULL;

sWintrustData.cbStruct = sizeof(WINTRUST_DATA);
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
sWintrustData.dwUnionChoice = WTD_CHOICE_FILE;
sWintrustData.pFile = &sWintrustFileInfo;
sWintrustData.dwStateAction = WTD_STATEACTION_VERIFY;

HMODULE hWinTrust = LoadLibrary(_T(WINTRUST_DLL));
if (!hWinTrust)
{
//WinTrust is unavailable on the machine
//return itvWintrustNotOnMachine;
itv = itvWintrustNotOnMachine;
goto cleanup;
}
PFnWinVerifyTrust pfnWinVerifyTrust =
(PFnWinVerifyTrust)GetProcAddress(hWinTrust, WINTRUSTAPI_WinVerifyTrust);
PFnWTHelperProvDataFromStateData pfnWTHelperProvDataFromStateData=
(PFnWTHelperProvDataFromStateData)GetProcAddress(hWinTrust,
WINTRUSTAPI_WTHelperProvDataFromStateData);
PFnWTHelperGetProvSignerFromChain pfnWTHelperGetProvSignerFromChain =
(PFnWTHelperGetProvSignerFromChain)GetProcAddress(hWinTrust,
WINTRUSTAPI_WTHelperGetProvSignerFromChain);
PFnWTHelperGetProvCertFromChain pfnWTHelperGetProvCertFromChain =
(PFnWTHelperGetProvCertFromChain)GetProcAddress(hWinTrust,
WINTRUSTAPI_WTHelperGetProvCertFromChain);
if (!pfnWinVerifyTrust || !pfnWTHelperProvDataFromStateData ||
!pfnWTHelperGetProvSignerFromChain || !pfnWTHelperGetProvCertFromChain)
{
// WinTrust is unavailable on the machine
FreeLibrary(hWinTrust);
//return itvWintrustNotOnMachine;
itv = itvWintrustNotOnMachine;
goto cleanup;
}

hr = pfnWinVerifyTrust(/* UI Window Handle */(HWND)INVALID_HANDLE_VALUE,
&guidAction, &sWintrustData);

itv = (TRUST_E_PROVIDER_UNKNOWN == hr) ? itvWintrustNotOnMachine :
((S_OK == hr) ? itvTrusted : itvUnTrusted);

if (itvWintrustNotOnMachine == itv)
{
// release state data
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
pfnWinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction,
&sWintrustData);

FreeLibrary(hWinTrust);
//return itv; // return immediately
goto cleanup;
}

if (TRUST_E_NOSIGNATURE == hr)
{
// release state data
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
pfnWinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction,
&sWintrustData);

FreeLibrary(hWinTrust);
//return itv;
goto cleanup;
}

cleanup:
switch ( itv )
{
case itvTrusted:
wprintf_s(L"The file \"%s\" is signed and the signature "
L"was verified.\n",
szModuleFile);
break;

case itvUnTrusted:
// The file was not signed or had a signature
// that was not valid.
{
// Get the reason for no signature.
dwLastError = GetLastError();
if (TRUST_E_NOSIGNATURE == dwLastError ||
TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError ||
TRUST_E_PROVIDER_UNKNOWN == dwLastError)
{
// The file was not signed.
wprintf_s(L"The file \"%s\" is not signed.\n",
szModuleFile);
return true;
//MessageBox(NULL, _T("File not signed or signature not trusted"),
szModuleFile, MB_OK );
}
else
{
// The signature was not valid or there was an error
// opening the file.
wprintf_s(L"An unknown error occurred trying to "
L"verify the signature of the \"%s\" file.\n",
szModuleFile);
}
return false;
}
break;

case itvWintrustNotOnMachine:
{
wprintf_s(L"The file %s is not trusted on this machine", szModuleFile);
return false;
}
break;

default:
// The UI was disabled in dwUIChoice or the admin policy
// has disabled user trust. lStatus contains the
// publisher or time stamp chain error.
{
wprintf_s(L"Error is: 0x%x.\n", itv);
return false;
}
break;
}

return true;
}

"Mounir IDRASSI" wrote:

Hi,

Are you calling the verification function in DllMain? If yes, then the
problem comes from here: when WinVerifyTrust is called and if it detects that
the file given to here contains a signature, it will dynamically load many
dlls and ti is not advised by Microsoft and it's known to cause stability
problems (Here is what MSDN says : "The entry-point function should perform
only simple initialization or termination tasks. It must not call the
LoadLibrary or LoadLibraryEx function (or a function that calls these
functions), because this may create dependency loops in the DLL load order.
This can result in a DLL being used before the system has executed its
initialization code" )
In this case, you should move the verification function from DllMain and put
it in an initialization function that must be called before using any service
exported by your Dll.

If, on the other hand, you are not calling WinVerifyTrust in DllMain, then
there must be another problem, certainly coming from the way you are using
the API. In this case, you should post a sample implementation that
demonstrate the problem in order to better understand your issue.


Cheers,

--
Mounir IDRASSI
IDRIX
http://www.idrix.fr

To reach me: mounir_idrix_fr (replace the underscores with the at and dot
characters respectively)


"scharan" wrote:

Scenario: Executable loads DLL. Before being loaded, DLL needs to verify its
own signature and that of the loading EXE.

In the event that the DLL is not signed, WinVerifyTrust returns correctly
with "Not Signed" message. In the event that the DLL OR the EXE is signed,
WinVerifyTrust does not return.

In debug mode, I put a break point at the function call. When I step into or
step over at that point, the debug button (step-into, step-over, step-return
etc) get disabled. Further, the call stack window also gets cleared and
disabled. So I am unable to investigate further.

Interesting further, we noted that this code works perfectly on Windows Vista.

Anybody faced similar situations?

Regards,
scharan.

.



Relevant Pages

  • RE: WinVerifyTrust Failure on WinXP
    ... WinVerifyTrust is called in __DllMain. ... //return itvWintrustNotOnMachine; ... PFnWTHelperProvDataFromStateData pfnWTHelperProvDataFromStateData= ... because this may create dependency loops in the DLL load order. ...
    (microsoft.public.platformsdk.security)
  • Re: DeleteFileW returns incorrect error code in Vista for DLLs
    ... MSN Messenger was just an example, we actually discovered this problem with our own software when trying to replace an in-use DLL. ... Our software offers to schedule a replacement at reboot if it gets an ERROR_SHARING_VIOLATION, and it appeared in testing that this was only failing on Vista under UAC - it works fine on XP, and it works fine on Vista in locations that do not require elevation. ... I just tested this on an XP system, and attempting to delete an in-use DLL from the Program Files folder gives the "sharing violation" error. ... Microsoft Online Community Support ...
    (microsoft.public.win32.programmer.kernel)
  • Re: Strange dll problem
    ... I have a strange problem with my app and I can't find a solution. ... Windows XP and Windows Vista. ... dll and a static lib, ... with the Unicode build of the Codex library, so I tried a non-Unicode ...
    (microsoft.public.vc.mfc)
  • Re: Vista and VB6 DLL
    ... there are some pretty cool things in vista that a lot of people don't know ... The first thing I did after installing Vista was to turn off the UAC. ... Pearson Software Consulting ... When you compile an ActiveX DLL in VB6, ...
    (microsoft.public.excel.programming)