Open ncook-hxgn opened 2 years ago
After a day of investigating the issue, debugging and reverse engineering system DLLs I found the cause of the problem. The call chain starts at function mssign32.SignerSignEx3 and among other things, the ConvertTextToUnicode function in wshext.dll is called in the call chain.
int __fastcall ConvertTextToUnicode(int a1, int a2, BSTR *a3)
{
int v3; // esi
int v4; // eax
OLECHAR *v5; // ecx
OLECHAR *v7; // ecx
int v8; // [esp-18h] [ebp-3Ch] BYREF
_DWORD v9[5]; // [esp-14h] [ebp-38h] BYREF
int v10; // [esp+0h] [ebp-24h] BYREF
int v11; // [esp+Ch] [ebp-18h]
int v12; // [esp+10h] [ebp-14h]
int v13; // [esp+14h] [ebp-10h]
LPVOID ppv; // [esp+18h] [ebp-Ch] BYREF
DWORD dwErrCode; // [esp+1Ch] [ebp-8h]
BSTR bstrString; // [esp+20h] [ebp-4h] BYREF
v3 = 0;
v12 = a2;
v11 = a1;
dwErrCode = 0;
v13 = 0;
ppv = 0;
bstrString = 0;
if ( CoInitialize(0) >= 0 )
{
v13 = 1;
...
The problem is in the call to the CoInitialize function. According to documentation https://learn.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize
Initializes the COM library on the current thread and identifies the concurrency model as single-thread apartment (STA).
However, the signature function is called from Task, which initializes the thread as an MTA apartment.
The return value from the CoInitialize function call is then 0x80010106 (RPC_E_CHANGED_MODE) and the ConvertTextToUnicode fails.
The issue can be fixed by calling mssign32.SignerSignEx3 from STA thread. I tested it with this my dirt fix https://github.com/engycz/AzureSignTool/commit/4de63af21544fca1b1950338566984dab267011c and now I'm able to sign VBS and js script
WScript.Echo "XX"
'' SIG '' Begin signature block
'' SIG '' MIIt6wYJKoZIhvcNAQcCoIIt3DCCLdgCAQExDzANBglg
'' SIG '' hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor
'' SIG '' BgEEAYI3AgEeMCQCAQEEEE7wKRaZJ7VNj+Ws4Q8X66sC
...
Is there anyone (@vcsjones) with better knowledge of C# to finish the fix?
This comment is also relevant to #124 and #137
@engycz amazing stuff, thank you for looking into this
Are there any plans to implement this fix?
I'm trying to replace SignTool.exe with AzureSignTool so that I can keep my signing certificate and associated secrets more secure when used in Azure DevOps Pipelines.
I have discovered that AzureSignTool does not have the same functionality as SignTool. Some of our products ship with JavaScript and VBS files, and we'd like to continue signing these, but AzureSignTool throws an error when we try to sign them.
This has been reported by others previously:
It would be good if these limitations were at least documented, which would prevent wasted development effort. Better would be to implement these features?
Edited to add:
From the whitepaper found here, emphasis mine: Code-Signing Best Practices