Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use an EV Code Signing Certificate on a virtual machine to sign an MSI

Tags:

We recently purchased an EV Code Signing Certificate from DigiCert to sign our MSI to get around the Windows SmartScreen warning message. The problem is that the Certificate was delivered to a USB Token that does not allow the exporting of the private key. Our build environment is on a hosted VM so there is no way we can plug the USB Token into the host VM.

Does anyone have a solution for using an EV Code Signing Certificate on a hosted VM? Do all Certificate Vendors deliver this type of certificate to a hardware token? How do you code sign an MSI in a virtual environment using this type of Cert?

like image 268
Jim Carter Avatar asked Apr 09 '13 15:04

Jim Carter


People also ask

How do you use EV code signing certificates?

How do I use my EV Code Signing certificate to sign files? To sign files with your EV Code Signing certificate, simply plug the token into your computer, follow your software's steps for signing code, and enter your YubiKey PIN.

How do I digitally sign MSI installer?

Before you place Setup.exe and MySetup. msi on the Web server, you should sign the files with your digital certificate and private key, Mycert. cer and Mycert. pvk, using the SignTool utility.

What is the difference between code signing and EV code signing?

Regular Code Signing – both gives secure environment to developers for their software codes. EV code signing keeps the private key secret using hardware token whereas in Regular code signing the private key is not provided in a separate external drive.


1 Answers

The crypto provider being shipped with the SafeNet client is accessing the USB-Token using the SmardCardAPI (winscard.dll). Because SmartCards are also used for authentication/login purposes, the RDP stack will always redirect any access to the RDP client computer.

https://docs.microsoft.com/en-us/windows/security/identity-protection/smart-cards/smart-card-and-remote-desktop-services

For scenarios like code signing this behavior can be quite cumbersome. We are using a dedicated virtual machine for signing purposes and each developer having access to this machine should be able to perform the signing process. With COVID-19 and all developers working at home the idea to use the local USB port is not feasible. Our USB-Token is attached to the dedicated machine. Each time you connect via RDP to this machine the dongle is no longer accessible, because the SmartCardAPI will redirect the access.

There is a solution to this problem however: The SmartCard stack uses the API-Calls

ProcessIdToSessionId

WinStationGetCurrentSessionCapabilities

to determine if the current process is running in a RDP session. By injecting a DLL into the signtool and using the Detours framework you can hook these API calls and report a local session, so the SmardCardAPI will access the dongle connected to the remote virtual machine.

https://github.com/microsoft/Detours

The detoured functions are quite simple (code reduced to important stuff, so you can get the idea)

DWORD WINAPI ProcessIdToSessionIdLocal(DWORD dwProcessId, DWORD *pSessionId) {   OutputDebugString("Detoured ProcessIdToSessionId\r\n");   if (pSessionId)      pSessionId = 0;   return TRUE; }  BOOL WINAPI WinStationGetCurrentSessionCapabilitiesLocal(DWORD flags, DWORD *pOutBuffer) {    BOOL bResult;        OutputDebugString("Detoured WinStationGetCurrentSessionCapabilities\r\n");    bResult = TrueGetCurStationCapabilities(flags,pOutBuffer);    if (bResult)       *pOutBuffer = 0;    return bResult; }  BOOL WINAPI DllMain (haDLL, dwReason, lpReserved)     HANDLE haDLL;     DWORD dwReason;     LPVOID lpReserved; {     LONG error;     TCHAR cBuffer[160];          wsprintf(cBuffer,"DllMain Entry %08x\r\n",dwReason);     OutputDebugString(cBuffer);     if (DetourIsHelperProcess()) {         return TRUE;     }      if (dwReason == DLL_PROCESS_ATTACH) {         OutputDebugString("Starting Detour API Calls \r\n");         hStaDLL = LoadLibrary("WINSTA.DLL");         TrueGetCurStationCapabilities = GetProcAddress(hStaDLL,"WinStationGetCurrentSessionCapabilities");                  DetourRestoreAfterWith();         DetourTransactionBegin();         DetourUpdateThread(GetCurrentThread());         DetourAttach((PVOID*)&TrueProcessIdToSessionId, ProcessIdToSessionIdLocal);         DetourAttach((PVOID*)&TrueGetCurStationCapabilities, WinStationGetCurrentSessionCapabilitiesLocal);         error = DetourTransactionCommit();          if (error == NO_ERROR) {         OutputDebugString("Successfully Detoured API Calls \r\n");          }         else {             return FALSE;         }     }     else if (dwReason == DLL_PROCESS_DETACH) {         DetourTransactionBegin();         DetourUpdateThread(GetCurrentThread());         DetourDetach((PVOID*)&TrueProcessIdToSessionId, ProcessIdToSessionIdLocal);         DetourDetach((PVOID*)&TrueGetCurStationCapabilities, WinStationGetCurrentSessionCapabilitiesLocal);         error = DetourTransactionCommit();         FreeLibrary(hStaDLL);     }     return TRUE; } 

Injecting a DLL into the signtool is also easy: just add a new entry to the IMPORTs section that will load the DLL with the detoured functions. This can be done using a tool named "Lord PE" (for 32bit executeables).

like image 185
Alatun Avatar answered Sep 18 '22 14:09

Alatun