Ищется программа, которая, получив на вход PE файл, и, скажем, def файл, выдаст на выход PE файл с таблицей экспорта по именам. Также, для полноты, хотелось бы иметь аналогичную утилиту для таблицы импорта. Буду признателен за любую конкретную информацию, особенно если будут еще и исходники. PS: Afaik, DLL forwarders не работают по ординалам, так что в данном случае, входной def файл может быть любым, например состоящим из имен типа f0, f1, .... PS/2: Прииенение DLL forwarders единственно приемлемо в данной ситуации, так что обсуждению <font size=5>не подлежит.</font><!--size-->
> PS: Afaik, DLL forwarders не работают по ординалам, так что в данном случае Почему не работают? kernel.#10
2 Dr. Golova: Спасибо огромнейшее! Такого синтаксиса я нигде не встречал. Также большой THANX 2 Red Plait за его прекрасный DLL Wrapper Wizard на Perl. 2 Volodya: Как поведет себя NT-подобный loader? Однако, я, тем временем, почти уже написал свой tool. Т.к. Вы, уважаемый Volodya, судя по замечательному циклу статей "Об упаковщиках в последний раз", являетесь специалистом по NT-подобному loaderу, хотелось бы кое-что уточнить и подтвердить некоторые догадки. (Реально они работают, во всяком случае у меня на NT4 Workstation SP/2, но хотелось бы подтвердить теоритически и узнать насчет кросс-платформенности) Рассмотрим ситуацию: секция экспорта находится где-то в середине файла. Как поведет себя loader, если AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals в IMAGE_EXPORT_DIRECTORY сылаются на другую секцию, скажем, в конце файла? Или правильнее будет поправить DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] в IMAGE_OPTIONAL_HEADER32, так, чтоб он целиком ссылался на модифицированную копию IMAGE_EXPORT_DIRECTORY где-нибудь в последней секции файла? И еще вопрос, какие размеры нужно править при увеличении объема файла (IMAGE_OPTIONAL_HEADER32.SizeOfImage, кратно IMAGE_OPTIONAL_HEADER32.SectionAlignment IMAGE_SECTION_HEADER.Misc.VirtualSize, кратно IMAGE_OPTIONAL_HEADER32.SectionAlignment IMAGE_SECTION_HEADER.PhysicalSize кратно IMAGE_OPTIONAL_HEADER32.FileAlignment), или что-то еще? И последнее: какая правильная формула пересчета RVA в File Offset?
Приятно, когда тебя считают спецом Но с того момента уже год прошел Я многое забыл и сосредоточен на другом. Кроме того, экспортом я вообще не занимался. Поэтому особо помочь не могу. Разве что, ответы на некоторые вопросы ты найдешь внутри LdrpSnapThunk. Вот так: Код (Text): NTSTATUS LdrpSnapThunk ( IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA OriginalThunk, IN OUT PIMAGE_THUNK_DATA Thunk, IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, IN ULONG ExportSize, IN BOOLEAN StaticSnap, IN PSZ DllName ) /*++ Routine Description: This function snaps a thunk using the specified Export Section data. If the section data does not support the thunk, then the thunk is partially snapped (Dll field is still non-null, but snap address is set). Arguments: DllBase - Base of Dll. ImageBase - Base of image that contains the thunks to snap. Thunk - On input, supplies the thunk to snap. When successfully snapped, the function field is set to point to the address in the DLL, and the DLL field is set to NULL. ExportDirectory - Supplies the Export Section data from a DLL. StaticSnap - If TRUE, then loader is attempting a static snap, and any ordinal/name lookup failure will be reported. Return Value: STATUS_SUCCESS or STATUS_PROCEDURE_NOT_FOUND --*/ { BOOLEAN Ordinal; USHORT OrdinalNumber; ULONG OriginalOrdinalNumber; PIMAGE_IMPORT_BY_NAME AddressOfData; PULONG NameTableBase; PUSHORT NameOrdinalTableBase; PULONG Addr; USHORT HintIndex; NTSTATUS st; PSZ ImportString; // // Determine if snap is by name, or by ordinal // Ordinal = (BOOLEAN)IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal); if (Ordinal) { OriginalOrdinalNumber = (ULONG)IMAGE_ORDINAL(OriginalThunk->u1.Ordinal); OrdinalNumber = (USHORT)(OriginalOrdinalNumber - ExportDirectory->Base); } else { // // Change AddressOfData from an RVA to a VA. // AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ImageBase + ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xffffffff)); ImportString = (PSZ)AddressOfData->Name; // // Lookup Name in NameTable // NameTableBase = (PULONG)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNames); NameOrdinalTableBase = (PUSHORT)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals); // // Before dropping into binary search, see if // the hint index results in a successful // match. If the hint index is zero, then // drop into binary search. // HintIndex = AddressOfData->Hint; if ((ULONG)HintIndex < ExportDirectory->NumberOfNames && !strcmp(ImportString, (PSZ)((ULONG_PTR)DllBase + NameTableBase[HintIndex]))) { OrdinalNumber = NameOrdinalTableBase[HintIndex]; #if LDRDBG if (ShowSnaps) { DbgPrint("LDR: Snapping %s\n", ImportString); } #endif } else { #if LDRDBG if (HintIndex) { DbgPrint("LDR: Warning HintIndex Failure. Name %s (%lx) Hint 0x%lx\n", ImportString, (ULONG)ImportString, (ULONG)HintIndex ); } #endif OrdinalNumber = LdrpNameToOrdinal( ImportString, ExportDirectory->NumberOfNames, DllBase, NameTableBase, NameOrdinalTableBase ); } } // // If OrdinalNumber is not within the Export Address Table, // then DLL does not implement function. Snap to LDRP_BAD_DLL. // if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) { baddllref: #if DBG if (StaticSnap) { if (Ordinal) { DbgPrint("LDR: Can't locate ordinal 0x%lx\n", OriginalOrdinalNumber); } else { DbgPrint("LDR: Can't locate %s\n", ImportString); } } #endif if ( StaticSnap ) { // // Hard Error Time // ULONG_PTR ErrorParameters[3]; UNICODE_STRING ErrorDllName, ErrorEntryPointName; ANSI_STRING AnsiScratch; ULONG ParameterStringMask; ULONG ErrorResponse; RtlInitAnsiString(&AnsiScratch,DllName ? DllName : "Unknown"); RtlAnsiStringToUnicodeString(&ErrorDllName,&AnsiScratch,TRUE); ErrorParameters[1] = (ULONG_PTR)&ErrorDllName; ParameterStringMask = 2; if ( Ordinal ) { ErrorParameters[0] = OriginalOrdinalNumber; } else { RtlInitAnsiString(&AnsiScratch,ImportString); RtlAnsiStringToUnicodeString(&ErrorEntryPointName,&AnsiScratch,TRUE); ErrorParameters[0] = (ULONG_PTR)&ErrorEntryPointName; ParameterStringMask = 3; } NtRaiseHardError( Ordinal ? STATUS_ORDINAL_NOT_FOUND : STATUS_ENTRYPOINT_NOT_FOUND, 2, ParameterStringMask, ErrorParameters, OptionOk, &ErrorResponse ); if ( LdrpInLdrInit ) { LdrpFatalHardErrorCount++; } RtlFreeUnicodeString(&ErrorDllName); if ( !Ordinal ) { RtlFreeUnicodeString(&ErrorEntryPointName); RtlRaiseStatus(STATUS_ENTRYPOINT_NOT_FOUND); } RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND); } Thunk->u1.Function = (ULONG_PTR)LDRP_BAD_DLL; st = Ordinal ? STATUS_ORDINAL_NOT_FOUND : STATUS_ENTRYPOINT_NOT_FOUND; } else { Addr = (PULONG)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions); Thunk->u1.Function = ((ULONG_PTR)DllBase + Addr[OrdinalNumber]); if (Thunk->u1.Function > (ULONG_PTR)ExportDirectory && Thunk->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize) ) { UNICODE_STRING UnicodeString; ANSI_STRING ForwardDllName; PVOID ForwardDllHandle; PUNICODE_STRING ForwardProcName; ULONG ForwardProcOrdinal; ImportString = (PSZ)Thunk->u1.Function; ForwardDllName.Buffer = ImportString, ForwardDllName.Length = (USHORT)(strchr(ImportString, '.') - ImportString); ForwardDllName.MaximumLength = ForwardDllName.Length; st = RtlAnsiStringToUnicodeString(&UnicodeString, &ForwardDllName, TRUE); if (NT_SUCCESS(st)) { #if defined (WX86) if (Wx86ProcessInit) { NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = RtlImageNtHeader(DllBase)->FileHeader.Machine == IMAGE_FILE_MACHINE_I386; } #endif st = LdrpLoadDll(NULL, NULL, &UnicodeString, &ForwardDllHandle,FALSE); RtlFreeUnicodeString(&UnicodeString); } if (!NT_SUCCESS(st)) { goto baddllref; } RtlInitAnsiString( &ForwardDllName, ImportString + ForwardDllName.Length + 1 ); if (ForwardDllName.Length > 1 && *ForwardDllName.Buffer == '#' ) { ForwardProcName = NULL; st = RtlCharToInteger( ForwardDllName.Buffer+1, 0, &ForwardProcOrdinal ); if (!NT_SUCCESS(st)) { goto baddllref; } } else { ForwardProcName = (PUNICODE_STRING)&ForwardDllName; // // Following line is not needed since this is a by name lookup // // //ForwardProcOrdinal = (ULONG)&ForwardDllName; // } st = LdrpGetProcedureAddress( ForwardDllHandle, (PANSI_STRING )ForwardProcName, ForwardProcOrdinal, &(PVOID)Thunk->u1.Function, FALSE ); if (!NT_SUCCESS(st)) { goto baddllref; } } else { if ( !Addr[OrdinalNumber] ) { goto baddllref; } #if defined (_ALPHA_) && defined (WX86) else { PIMAGE_NT_HEADERS ExportNtHeaders = RtlImageNtHeader(DllBase); if ((ExportNtHeaders->OptionalHeader.SectionAlignment < PAGE_SIZE) && (ExportNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)) { Thunk->u1.Function += LdrpWx86RelocatedFixupDiff(DllBase, Addr[OrdinalNumber]); } } #endif // defined (_ALPHA_) && defined (WX86) } st = STATUS_SUCCESS; } return st; }