#include #include #include #include #include #include BOOL StripCv( PSZ szImage ); void __cdecl main(int argc, char *argv[]); void Usage(void); void Usage (void) { puts("USAGE: StripCV \n" "\tRemove non-public CV info from an image.\n"); } void __cdecl main( int argc, char *argv[]) { int i; if (argc < 2) { Usage(); exit(1); } for (i = 1; i < argc; i++) { StripCv(argv[i]); } } BOOL StripCv( PSZ szImage ) { PCHAR CvDebugData; unsigned int i, NumberOfDebugDirectories; ULONG DebugDirectorySize, NewCvSize = 0; PCHAR NewCvData; HANDLE FileHandle, hMappedFile; PVOID DebugDirectories, ImageBase; PIMAGE_NT_HEADERS NtHeaders; PIMAGE_DEBUG_DIRECTORY DebugDirectory; BOOL fRemoveCV = FALSE; BOOL fDbgFile = FALSE; ULONG *pDebugSize, FileSize; BOOL RC = TRUE; FileHandle = CreateFile( szImage, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if (FileHandle == INVALID_HANDLE_VALUE) { printf("Error: Unable to open %s - rc: %d\n", szImage, GetLastError()); RC = FALSE; goto cleanup1; } FileSize = GetFileSize(FileHandle, NULL); hMappedFile = CreateFileMapping( FileHandle, NULL, PAGE_READWRITE, 0, 0, NULL ); if (!hMappedFile) { printf("Error: Unable to create read/write map on %s - rc: %d\n", szImage, GetLastError()); RC = FALSE; goto cleanup2; } ImageBase = MapViewOfFile( hMappedFile, FILE_MAP_WRITE, 0, 0, 0 ); if (!ImageBase) { printf("Error: Unable to Map view of file %s - rc: %d\n", szImage, GetLastError); RC = FALSE; goto cleanup3; } if (*(USHORT *)ImageBase == IMAGE_SEPARATE_DEBUG_SIGNATURE) { fDbgFile = TRUE; PIMAGE_SEPARATE_DEBUG_HEADER DbgFile = (PIMAGE_SEPARATE_DEBUG_HEADER) ImageBase; DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)((PUCHAR)ImageBase + sizeof(IMAGE_SEPARATE_DEBUG_HEADER) + (DbgFile->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)) + DbgFile->ExportedNamesSize ); pDebugSize = &(DbgFile->DebugDirectorySize); DebugDirectorySize = DbgFile->DebugDirectorySize; } else { NtHeaders = ImageNtHeader( ImageBase ); if (NtHeaders == NULL) { printf("Error: %s is not an NT image\n", szImage); RC = FALSE; goto cleanup4; } DebugDirectories = ImageDirectoryEntryToData( ImageBase, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugDirectorySize ); pDebugSize = &(NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size); } if (DebugDirectories == NULL || DebugDirectorySize == 0) { printf("Warning: No debug info found on %s\n", szImage); RC = FALSE; goto cleanup4; } DebugDirectory = (PIMAGE_DEBUG_DIRECTORY) DebugDirectories; NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY ); CvDebugData = NULL; for (i=0; i < NumberOfDebugDirectories; i++) { if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_CODEVIEW) { CvDebugData = (PCHAR)ImageBase + DebugDirectory->PointerToRawData; break; } // Zero out the Fixup data if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FIXUP) { printf("Info: Removing Fixup data from %s\n", szImage); RtlZeroMemory(((PUCHAR)ImageBase + DebugDirectory->PointerToRawData), DebugDirectory->SizeOfData); DebugDirectory = DebugDirectory+1; *pDebugSize -= sizeof(IMAGE_DEBUG_DIRECTORY); } else { DebugDirectory++; } } if (CvDebugData == NULL) { printf("Info: No CV Debug found on %s\n", szImage); RC = FALSE; goto cleanup5; } if (RemovePrivateCvSymbolic(CvDebugData, &NewCvData, &NewCvSize)) { printf("Info: CV types info stripped from %s\n", szImage); } RtlCopyMemory(CvDebugData, NewCvData, NewCvSize); DebugDirectory = (PIMAGE_DEBUG_DIRECTORY) DebugDirectories; for (i=0; i < NumberOfDebugDirectories; i++) { if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_CODEVIEW) { if (i+1 == NumberOfDebugDirectories) { // This is the simple case. cv is the last entry. Simply truncate the image. FileSize += NewCvSize - DebugDirectory->SizeOfData; } DebugDirectory->SizeOfData = NewCvSize; break; } DebugDirectory++; } cleanup5: // All done. if (!fDbgFile) { PIMAGE_NT_HEADERS pHdr = NULL; DWORD SumHeader; DWORD SumTotal; pHdr = CheckSumMappedFile(ImageBase, FileSize, &SumHeader, &SumTotal); if (pHdr != NULL) { pHdr->OptionalHeader.CheckSum = SumTotal; } } FlushViewOfFile(ImageBase, NULL); cleanup4: UnmapViewOfFile(ImageBase); cleanup3: CloseHandle(hMappedFile); cleanup2: SetFilePointer(FileHandle, FileSize, NULL, FILE_BEGIN); SetEndOfFile(FileHandle); CloseHandle(FileHandle); cleanup1: return(RC); }