#include "stdinc.h" #include "lhport.h" #include "imagehlp.h" #include "winthrow.h" #include "fusionbuffer.h" #include "sxshimlib.h" #include "fusionhandle.h" #include BOOL SxspFormatGUID( IN const GUID &rGuid, IN OUT F::CBaseStringBuffer &rBuffer ); // // Not yet used but I expect either we'll need it, or we'll just not shim msvcrt.dll at all. // This list is derived from searching public\sdk\inc\crt for "_CRTIMP extern" // BOOL SxpepIsKnownDataSymbol() { return FALSE; } // // arg, the implementation but not the declaration of this was removed.. // #include "yvals.h" #pragma warning(disable:4663) #include class CMySmallANSIStringBuffer : public std::vector { public: CMySmallANSIStringBuffer() { } ~CMySmallANSIStringBuffer() { } void RemoveTrailingNuls() { while (this->size() != 0 && this->operator[](this->size() - 1) == 0) this->resize(size() - 1); } BOOL Win32Append(PCSTR s) { return this->Win32Append(s, ::strlen(s)); } BOOL Win32Append(PCSTR s, SIZE_T i) { this->RemoveTrailingNuls(); SIZE_T j = this->size(); this->resize(j + i + 1); CopyMemory(&*begin() + j, s, i); this->operator[](i + j) = 0; return TRUE; } BOOL Win32Assign(PCSTR s, SIZE_T i) { this->clear(); return this->Win32Append(s, i); } operator PCSTR() { this->EnsureTrailingNul(); return &*begin(); } void EnsureTrailingNul() { if (this->size() == 0 || this->operator[](size() - 1) != 0) { this->push_back(0); } } }; BOOL SxPepApplyShims( PCSXPE_APPLY_SHIMS_IN in, SXPE_APPLY_SHIMS_OUT* out ) { FN_PROLOG_WIN32 ULONG Size = 0; PIMAGE_SECTION_HEADER ImportSection = NULL; PBYTE FromHandle = NULL; PIMAGE_NT_HEADERS FromNtHeader = NULL; PCWSTR ToPath = NULL; PBYTE ImportData = NULL; DWORD OldImportSectionVirtualProtection = 0; PCSTR ImportDllName = NULL; PCSTR* ImportFunctionNames = NULL; PBYTE* ImportFunctionAddresses = NULL; CMySmallANSIStringBuffer PrefixedFunctionName; F::CDynamicLinkLibrary ToHandle; SIZE_T PrefixLength = 0; FromHandle = reinterpret_cast(in->DllToRedirectFrom); FromNtHeader = ImageNtHeaderOrThrow(FromHandle); ToPath = in->DllToRedirectTo.Path; out->DllToRedirectTo.Path = ToPath; ToHandle = in->DllToRedirectTo.DllHandle; if (ToHandle == static_cast(NULL)) { ToHandle = LoadLibraryWOrThrow(ToPath); } out->DllToRedirectTo.DllHandle = ToHandle; ImportData = reinterpret_cast(ImageDirectoryEntryToDataExOrThrow( FromHandle, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size, &ImportSection)); // ImageDirectoryEntryToDataEx almost never returns the ImportSection. if (ImportSection == NULL) ImportSection = ImageRvaToSectionOrThrow(FromNtHeader, FromHandle, static_cast(ImportData - FromHandle)); VirtualProtectOrThrow( FromHandle + ImportSection->VirtualAddress, ImportSection->Misc.VirtualSize, PAGE_WRITECOPY, &OldImportSectionVirtualProtection ); if (in->Prefix != NULL) PrefixLength = ::strlen(in->Prefix); for ( PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = reinterpret_cast(ImportData); ImportDescriptor->Characteristics != 0 ; ++ImportDescriptor ) { PCSTR ImportDllName = reinterpret_cast(FromHandle + ImportDescriptor->Name); printf("%s\n", ImportDllName); DWORD* ImportFunctionNames = reinterpret_cast(FromHandle + ImportDescriptor->OriginalFirstThunk); PVOID* ImportFunctionAddresses = reinterpret_cast(FromHandle + ImportDescriptor->FirstThunk); for ( ; *ImportFunctionNames != NULL && *ImportFunctionAddresses != NULL ; ++ImportFunctionNames, ++ImportFunctionAddresses ) { typedef WORD HINT; PCSTR NonPrefixedFunctionName = sizeof(HINT) + reinterpret_cast(FromHandle + *ImportFunctionNames); PCSTR PossiblyPrefixedFunctionName = NonPrefixedFunctionName; // we should make this available to the shims, like to enable shim chaining //PVOID OriginalFunctionAddress = *ImportFunctionAddresses; if (PrefixLength != 0) { IFW32FALSE_EXIT(PrefixedFunctionName.Win32Assign(in->Prefix, PrefixLength)); IFW32FALSE_EXIT(PrefixedFunctionName.Win32Append(NonPrefixedFunctionName)); PossiblyPrefixedFunctionName = PrefixedFunctionName; } PVOID NewFunctionAddress = ::GetProcAddress(ToHandle, PossiblyPrefixedFunctionName); if (NewFunctionAddress == NULL) { printf( "%s%s%s%s not shimmed\n", NonPrefixedFunctionName, PossiblyPrefixedFunctionName != NonPrefixedFunctionName ? "(" : "", PossiblyPrefixedFunctionName != NonPrefixedFunctionName ? PossiblyPrefixedFunctionName : "", PossiblyPrefixedFunctionName != NonPrefixedFunctionName ? ")" : "" ); } else { PVOID OldAddress = *ImportFunctionAddresses; printf("%p.%s.%p shimmed to %ls%s%p.%s.%p\n", in->DllToRedirectFrom, NonPrefixedFunctionName, OldAddress, (ToPath != NULL) ? ToPath : L"", (ToPath != NULL) ? "." : "", ToHandle, PossiblyPrefixedFunctionName, NewFunctionAddress); *ImportFunctionAddresses = NewFunctionAddress; // // if they have export named OriginalFoo, poke // it with the old address (we include the prefix so that // chaining might work) // IFW32FALSE_EXIT(PrefixedFunctionName.Win32Assign(in->Prefix, PrefixLength)); IFW32FALSE_EXIT(PrefixedFunctionName.Win32Append("Original")); IFW32FALSE_EXIT(PrefixedFunctionName.Win32Append(NonPrefixedFunctionName)); PVOID* InformOriginalAddress = reinterpret_cast(::GetProcAddress(ToHandle, PrefixedFunctionName)); if (InformOriginalAddress != NULL) *InformOriginalAddress = OldAddress; } } } VirtualProtectOrThrow( FromHandle + ImportSection->VirtualAddress, ImportSection->Misc.VirtualSize, OldImportSectionVirtualProtection, &OldImportSectionVirtualProtection ); FN_EPILOG }