//// DelCert - Delete all certificates in Win32 image // ///// delCert Command line // //c delCert Executable // //p Executable: Win32 binary to update // #pragma warning( disable : 4786 ) // map creates some ridiculously long debug identifiers #include "stdio.h" #include "windows.h" #include "imagehlp.h" #include "time.h" #define DBG 1 void __cdecl DebugMsg(char *fmt, ...) { va_list vargs; va_start(vargs, fmt); vfprintf(stderr, fmt, vargs); } BOOL g_fError = FALSE; #define warn DebugMsg #define MUST(a,b) {HRESULT hr; hr = (a); if (hr!= S_OK) {if (!g_fError) DebugMsg b; g_fError = TRUE; return E_FAIL;};} #define SHOULD(a,b) {HRESULT hr; hr = (a); if (hr!= S_OK) {DebugMsg b; g_fWarn = TRUE; return S_FALSE;};} #if DBG #pragma message("Checked build") #define OK(a) {HRESULT hr; hr = (a); if (hr!= S_OK) {DebugMsg("%s(%d): error RSRC999 : HRESULT not S_OK: "#a"\n", __FILE__, __LINE__); return hr;};} #define ASSERT(a) {if (!(a)) {DebugMsg("%s(%d): error RSRC999 : Assertion failed: "#a"\n", __FILE__, __LINE__); return E_UNEXPECTED;};} #else #pragma message ("Free build") #define OK(a) {HRESULT hr; hr = (a); if (hr != S_OK) return hr;} #define ASSERT(a) {if (!(a)) {return E_UNEXPECTED;};} #endif //// Mapped files // // File mapping is used to read executable and token files. // // File mapping is also used to update in place checksum information // in executable and symbol files. class MappedFile { HANDLE m_hFileMapping; BOOL fRW; // True when writeable char m_szFileName[MAX_PATH]; public: BYTE *m_pStart; BYTE *m_pLimit; MappedFile() {m_hFileMapping = NULL;} HRESULT Open(const char *pcFileName, BOOL fWrite) { HANDLE hFile; strcpy(m_szFileName, pcFileName); hFile = CreateFileA( pcFileName, GENERIC_READ | (fWrite ? GENERIC_WRITE : 0), FILE_SHARE_READ | (fWrite ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0 ), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); m_hFileMapping = CreateFileMapping( hFile, NULL, fWrite ? PAGE_READWRITE : PAGE_WRITECOPY, 0,0, NULL); ASSERT(m_hFileMapping != NULL); m_pStart = (BYTE*) MapViewOfFile( m_hFileMapping, fWrite ? FILE_MAP_WRITE : FILE_MAP_READ, 0,0, 0); ASSERT(m_pStart != NULL); m_pLimit = m_pStart + GetFileSize(hFile, NULL); CloseHandle(hFile); fRW = fWrite; return S_OK; } DWORD CalcChecksum() { DWORD dwHeaderSum; DWORD dwCheckSum; if (CheckSumMappedFile((void*)m_pStart, (DWORD)(m_pLimit-m_pStart), &dwHeaderSum, &dwCheckSum) == NULL) { return 0; } else { return dwCheckSum; } } HRESULT Close() { if (m_pStart) { UnmapViewOfFile(m_pStart); CloseHandle(m_hFileMapping); m_hFileMapping = NULL; m_pStart = NULL; } return S_OK; } }; class Win32Executable : public MappedFile { IMAGE_NT_HEADERS *m_pNtHeader; IMAGE_SECTION_HEADER *m_pSections; public: DWORD GetChecksum() const {return m_pNtHeader->OptionalHeader.CheckSum;} void SetChecksum(DWORD dwChecksum) {m_pNtHeader->OptionalHeader.CheckSum=dwChecksum;} void SetCertificateRVA (DWORD rva) { m_pNtHeader->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] .VirtualAddress = rva; } HRESULT Open(const char *pcFileName, BOOL fWrite) { int i; OK(MappedFile::Open(pcFileName, fWrite)); MUST(( *(WORD*)m_pStart == IMAGE_DOS_SIGNATURE && *(WORD*)(m_pStart+0x18) >= 0x40) // WinVer >= 4 ? S_OK : E_FAIL, ("RSRC : error RSRC501: %s is not an executable file\n", pcFileName)); m_pNtHeader = (IMAGE_NT_HEADERS*)(m_pStart + *(WORD*)(m_pStart+0x3c)); MUST((m_pNtHeader->Signature == IMAGE_NT_SIGNATURE) ? S_OK : E_FAIL, ("RSRC : error RSRC502: %s is not a Win32 executable file\n", pcFileName)); m_pSections = (IMAGE_SECTION_HEADER*)(m_pNtHeader+1); return S_OK; } }; void DeleteCertificates( const char *fileName ) { HANDLE fileHandle = CreateFile( fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if (fileHandle == INVALID_HANDLE_VALUE) { warn("Could not access %s\n", fileName); return; } DWORD certificateCount; DWORD *certificateIndices; if (!ImageEnumerateCertificates( fileHandle, CERT_SECTION_TYPE_ANY, &certificateCount, NULL, 0 )) { warn("Could not enumerate certificates in %s.\n", fileName); CloseHandle(fileHandle); return; } if (certificateCount == 0) { warn("No certificates found in %s.\n", fileName); CloseHandle(fileHandle); return; } certificateIndices = new DWORD[certificateCount]; if (certificateIndices == NULL) { CloseHandle(fileHandle); warn("Couldn't allocate buffer for %d certificate indices for %s.\n", certificateCount, fileName); return; } ImageEnumerateCertificates( fileHandle, CERT_SECTION_TYPE_ANY, &certificateCount, certificateIndices, certificateCount ); if (certificateCount == 0) { warn("Couldn't get certificate indices for %s.\n", fileName); CloseHandle(fileHandle); return; } for (DWORD i=0; i0 && *p0) && (*p' ')) { *s=**p; s++; (*p)++; l--; } // Skip any part of token that didn't fit into s while ((*p' ')) (*p)++; } if (l>0) *s++ = 0; else *(s-1) = 0; SkipWhitespace(p, pE); } void ParseName(char** p, char* pE, char* s, int l) { // Uses ParseToken to parse a name such as a filename. // If the name starts with '/' or '-' it is assumed to be // an option rather than a filename and ParseName returns // a zero length string. if (*p