Jump to content
Nytro

MS14-066 schannel.dll SPVerifySignature (Windows 2003 SP2)

Recommended Posts

Posted

MS14-066 schannel.dll SPVerifySignature (Windows 2003 SP2)

/*

Summarizing the most likely conditions here these bugs occur:

Code Execution: Heap smash via qmemcpy() if CryptDecodeObject() returns more than 40 bytes in pcbStructInfo
Verification Bypass: A failed decode results in a positive return value. This is not STATUS_SUCCESS, but
a caller that is checking <0 vs == 0 would think verification succeeded on a bad decode.

*/


//----- (7676F6D4) --------------------------------------------------------
int __stdcall SPVerifySignature(HCRYPTPROV hProv, int a2, ALG_ID Algid, BYTE *pbData, DWORD dwDataLen, BYTE *pbEncoded, DWORD cbEncoded, int a8)
{
signed int v8; // esi@4
BOOL v9; // eax@8
DWORD v10; // eax@14
DWORD pcbStructInfo; // [sp+Ch] [bp-3Ch]@11
HCRYPTKEY phKey; // [sp+10h] [bp-38h]@1
HCRYPTHASH phHash; // [sp+14h] [bp-34h]@1
BYTE *pbSignature; // [sp+18h] [bp-30h]@1
char pvStructInfo[40]; // [sp+1Ch] [bp-2Ch]@11

phKey = 0;
phHash = 0;
pbSignature = 0;
if ( hProv && a2 )
{
// Allocate cbEncoded bytes on the heap for the signature
pbSignature = (BYTE *)SPExternalAlloc(cbEncoded);
if ( !pbSignature )
{
// Exit early if the allocation failed
v8 = -2146893056;
goto LABEL_18;
}

// Import the key and create the hash, bailing out if it fails
if ( !CryptImportKey(hProv, *(const BYTE **)a2, *(_DWORD *)(a2 + 4), 0, 0, &phKey)
|| !CryptCreateHash(hProv, Algid, 0, 0, &phHash) )
goto LABEL_12;

// Verify that CryptHashData or CryptSetHashParam succeeds (but how is a8 being set?)
v9 = a8 ? CryptHashData(phHash, pbData, dwDataLen, 0) : CryptSetHashParam(phHash, 2u, pbData, 0);
if ( !v9 )
goto LABEL_12;

if ( *(_DWORD *)(*(_DWORD *)a2 + 4) == 8704 )
{
// Indicate that we have 40 bytes to decode the signature value
pcbStructInfo = 40;

// CryptDecodeObject() states that pvStructInfo can be larger than pcbStructInfo
// Bail out if the decode fails

/*

BOOL WINAPI CryptDecodeObject(
_In_ DWORD dwCertEncodingType, (X509_ASN_ENCODING)
_In_ LPCSTR lpszStructType, (X509_DSS_SIGNATURE)
_In_ const BYTE *pbEncoded, (Caller)
_In_ DWORD cbEncoded, (Caller)
_In_ DWORD dwFlags, (0)
_Out_ void *pvStructInfo, (40 byte stack variable)
_Inout_ DWORD *pcbStructInfo (in:40, out:arbitrary)
);

pcbStructInfo [in, out]:

A pointer to a DWORD value specifying the size, in bytes, of the buffer pointed to by the pvStructInfo parameter.
When the function returns, this DWORD value contains the size of the decoded data copied to pvStructInfo.
The size contained in the variable pointed to by pcbStructInfo can indicate a size larger than the decoded structure,
as the decoded structure can include pointers to other structures. This size is the sum of the size needed by the
decoded structure and other structures pointed to.
*/

if ( !CryptDecodeObject(X509_ASN_ENCODING, X509_DSS_SIGNATURE, pbEncoded, cbEncoded, 0, &pvStructInfo, &pcbStructInfo) )
{
LABEL_12:
// this might be the signature bypass vector if the caller incorrectly checks <0 vs STATUS_SUCCESS
GetLastError();
v8 = 3;
goto LABEL_18;
}

v10 = pcbStructInfo;

// This is likely our RCE vector, if pcbStructInfo > cbEncoded
qmemcpy(pbSignature, &pvStructInfo, pcbStructInfo);

// Changes cbEncoded to the (possibly bad) returned value of pcbStructInfo
cbEncoded = v10;
}
else
{
ReverseMemCopy((unsigned int)pbSignature, (int)pbEncoded, cbEncoded);
}
v8 = CryptVerifySignatureA(phHash, pbSignature, cbEncoded, phKey, 0, 0) != 0 ? 0 : -2147483391;
}
else
{
v8 = -1;
}
LABEL_18:
if ( phKey )
CryptDestroyKey(phKey);
if ( phHash )
CryptDestroyHash(phHash);
if ( pbSignature )
SPExternalFree(pbSignature);
return v8;
}

Sursa: https://gist.github.com/hmoore-r7/3379af8b0419ddb0c76b

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...