/*++ Copyright (c) 1992 Microsoft Corporation Module Name: smashlck.c Abstract: This function smashes lock prefixes replacing them with NOPs Author: Mark Lucovsky (markl) 30-Apr-1993 Revision History: --*/ #include BOOL fVerbose; BOOL fUpdate; BOOL fUsage; UCHAR LockPrefixOpcode = 0xf0; UCHAR NoOpOpcode = 0x90; LPSTR CurrentImageName; PIMAGE_OPTIONAL_HEADER32 OptionalHeader32; PIMAGE_OPTIONAL_HEADER64 OptionalHeader64; PIMAGE_FILE_HEADER FileHeader; LOADED_IMAGE CurrentImage; CHAR DebugFilePath[_MAX_PATH]; LPSTR SymbolPath; PVOID ImageVaToLoadVa( PVOID ImageVa, PLOADED_IMAGE Image ) { PIMAGE_SECTION_HEADER Section; ULONG i, Rva; PVOID Va; PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL; PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL; PIMAGE_FILE_HEADER FileHeader; FileHeader = &((PIMAGE_NT_HEADERS32)Image->FileHeader)->FileHeader; OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Image->FileHeader, &OptionalHeader32, &OptionalHeader64); if (!OptionalHeader32 && !OptionalHeader64) return NULL; Rva = (ULONG)((ULONG_PTR)((PUCHAR)ImageVa - (PUCHAR)OPTIONALHEADER(ImageBase))); Va = NULL; Section = Image->LastRvaSection; if ( Rva >= Section->VirtualAddress && Rva < (Section->VirtualAddress + Section->SizeOfRawData) ) { Va = (PVOID)(Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress); } else { for(Section = Image->Sections,i=0; iNumberOfSections; i++,Section++) { if ( Rva >= Section->VirtualAddress && Rva < (Section->VirtualAddress + Section->SizeOfRawData) ) { Va = (PVOID)(Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress); Image->LastRvaSection = Section; break; } } } if ( !Va ) { fprintf(stderr,"SMASHLOCK: ImageVaToLoadVa %p in image %p failed\n",ImageVa,Image); } return Va; } int __cdecl main( int argc, char *argv[], char *envp[] ) { DWORD dw; LPSTR FilePart; CHAR Buffer[MAX_PATH]; PIMAGE_LOAD_CONFIG_DIRECTORY ConfigInfo; ULONG whocares; char c, *p; BOOLEAN LocksSmashed; ULONG CheckSum; ULONG HeaderSum; ULONG OldChecksum; int retval = 0; fUsage = FALSE; fVerbose = FALSE; fUpdate = FALSE; _tzset(); if (argc <= 1) { goto showUsage; } while (--argc) { p = *++argv; if (*p == '/' || *p == '-') { while (c = *++p) switch (toupper( c )) { case '?': fUsage = TRUE; break; case 'V': fVerbose = TRUE; break; case 'U': fUpdate = TRUE; break; case 'S': argc--, argv++; SymbolPath = *argv; break; default: fprintf( stderr, "SMASHLOCK: Invalid switch - /%c\n", c ); fUsage = TRUE; break; } if ( fUsage ) { showUsage: fputs("usage: SMASHLOCK [switches] image-names... \n" " [-?] display this message\n" " [-u] update image\n" " [-v] verbose output\n" " [-s] path to symbol files\n", stderr ); exit(1); } } else { LocksSmashed = FALSE; CurrentImageName = p; dw = GetFullPathName(CurrentImageName,sizeof(Buffer),Buffer,&FilePart); if ( dw == 0 || dw > sizeof(Buffer) ) { FilePart = CurrentImageName; } // // Map and load the current image // if ( MapAndLoad(CurrentImageName, NULL, &CurrentImage, FALSE, !fUpdate )) { FileHeader = &((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->FileHeader; OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader, &OptionalHeader32, &OptionalHeader64); // // make sure the image has correct configuration information, // and that the LockPrefixTable is set up properly // ConfigInfo = (PIMAGE_LOAD_CONFIG_DIRECTORY)ImageDirectoryEntryToData( CurrentImage.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &whocares ); if ( ConfigInfo && ConfigInfo->LockPrefixTable ) { // // Walk through the lock prefix table // PUCHAR *LockPrefixs; PUCHAR LockPrefix; LockPrefixs = (PUCHAR *)ImageVaToLoadVa((PVOID)ConfigInfo->LockPrefixTable,&CurrentImage); while(LockPrefixs && *LockPrefixs) { LockPrefix = (PUCHAR) ImageVaToLoadVa(*LockPrefixs,&CurrentImage); if ( LockPrefix && *LockPrefix == LockPrefixOpcode ) { if (fVerbose) { printf("LockPrefix Found at 0x%p = %x\n",*LockPrefixs,*LockPrefix); } if (fUpdate) { LocksSmashed = TRUE; *LockPrefix = NoOpOpcode; } } LockPrefixs++; } } if ( fUpdate && LocksSmashed ) { // // recompute the checksum. // OldChecksum = OPTIONALHEADER(CheckSum); if ( CurrentImage.hFile != INVALID_HANDLE_VALUE ) { OPTIONALHEADER_ASSIGN(CheckSum, 0); CheckSumMappedFile( (PVOID)CurrentImage.MappedAddress, GetFileSize(CurrentImage.hFile, NULL), &HeaderSum, &CheckSum ); OPTIONALHEADER_ASSIGN(CheckSum, CheckSum); } FlushViewOfFile(CurrentImage.MappedAddress,0); TouchFileTimes(CurrentImage.hFile,NULL); // And update the .dbg file (if requested) if (SymbolPath && FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) { if ( UpdateDebugInfoFileEx( CurrentImageName, SymbolPath, DebugFilePath, (PIMAGE_NT_HEADERS32) CurrentImage.FileHeader, OldChecksum) ) { if (GetLastError() == ERROR_INVALID_DATA) { printf( "Warning: Old checksum did not match for %s\n", DebugFilePath); } printf("Updated symbols for %s\n", DebugFilePath); } else { printf("Unable to update symbols: %s\n", DebugFilePath); retval=1; } } } UnmapViewOfFile(CurrentImage.MappedAddress); if ( CurrentImage.hFile != INVALID_HANDLE_VALUE ) { CloseHandle(CurrentImage.hFile); } ZeroMemory(&CurrentImage,sizeof(CurrentImage)); } else { if (!CurrentImage.fSystemImage && !CurrentImage.fDOSImage) { fprintf(stderr,"SMASHLOCK: failure mapping and loading %s\n",CurrentImageName); retval=1; } } } } return retval; }