"Восстановление" таблицы экспорта PE: ординалы->имена

Тема в разделе "WASM.WIN32", создана пользователем avalon, 14 авг 2004.

  1. avalon

    avalon New Member

    Публикаций:
    0
    Регистрация:
    14 авг 2004
    Сообщения:
    3
    Ищется программа, которая, получив на вход PE файл, и, скажем, def файл,

    выдаст на выход PE файл с таблицей экспорта по именам.



    Также, для полноты, хотелось бы иметь аналогичную утилиту для таблицы импорта.



    Буду признателен за любую конкретную информацию, особенно если будут еще и

    исходники.



    PS: Afaik, DLL forwarders не работают по ординалам, так что в данном случае,

    входной def файл может быть любым, например состоящим из имен типа f0, f1, ....

    PS/2: Прииенение DLL forwarders единственно приемлемо

    в данной ситуации, так что обсуждению <font size=5>не подлежит.</font><!--size-->
     
  2. Dr.Golova

    Dr.Golova New Member

    Публикаций:
    0
    Регистрация:
    7 сен 2002
    Сообщения:
    348
    > PS: Afaik, DLL forwarders не работают по ординалам, так что в данном случае



    Почему не работают? kernel.#10
     
  3. avalon

    avalon New Member

    Публикаций:
    0
    Регистрация:
    14 авг 2004
    Сообщения:
    3
    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?
     
  4. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Приятно, когда тебя считают спецом :) Но с того момента уже год прошел :) Я многое забыл и сосредоточен на другом. Кроме того, экспортом я вообще не занимался. Поэтому особо помочь не могу. Разве что, ответы на некоторые вопросы ты найдешь внутри LdrpSnapThunk. Вот так:


    Код (Text):
    1.  
    2. NTSTATUS
    3. LdrpSnapThunk (
    4.     IN PVOID DllBase,
    5.     IN PVOID ImageBase,
    6.     IN PIMAGE_THUNK_DATA OriginalThunk,
    7.     IN OUT PIMAGE_THUNK_DATA Thunk,
    8.     IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
    9.     IN ULONG ExportSize,
    10.     IN BOOLEAN StaticSnap,
    11.     IN PSZ DllName
    12.     )
    13.  
    14. /*++
    15.  
    16. Routine Description:
    17.  
    18.     This function snaps a thunk using the specified Export Section data.
    19.     If the section data does not support the thunk, then the thunk is
    20.     partially snapped (Dll field is still non-null, but snap address is
    21.     set).
    22.  
    23. Arguments:
    24.  
    25.     DllBase - Base of Dll.
    26.  
    27.     ImageBase - Base of image that contains the thunks to snap.
    28.  
    29.     Thunk - On input, supplies the thunk to snap.  When successfully
    30.         snapped, the function field is set to point to the address in
    31.         the DLL, and the DLL field is set to NULL.
    32.  
    33.     ExportDirectory - Supplies the Export Section data from a DLL.
    34.  
    35.     StaticSnap - If TRUE, then loader is attempting a static snap,
    36.                  and any ordinal/name lookup failure will be reported.
    37.  
    38. Return Value:
    39.  
    40.     STATUS_SUCCESS or STATUS_PROCEDURE_NOT_FOUND
    41.  
    42. --*/
    43.  
    44. {
    45.     BOOLEAN Ordinal;
    46.     USHORT OrdinalNumber;
    47.     ULONG OriginalOrdinalNumber;
    48.     PIMAGE_IMPORT_BY_NAME AddressOfData;
    49.     PULONG NameTableBase;
    50.     PUSHORT NameOrdinalTableBase;
    51.     PULONG Addr;
    52.     USHORT HintIndex;
    53.     NTSTATUS st;
    54.     PSZ ImportString;
    55.  
    56.     //
    57.     // Determine if snap is by name, or by ordinal
    58.     //
    59.  
    60.     Ordinal = (BOOLEAN)IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal);
    61.  
    62.     if (Ordinal) {
    63.         OriginalOrdinalNumber = (ULONG)IMAGE_ORDINAL(OriginalThunk->u1.Ordinal);
    64.         OrdinalNumber = (USHORT)(OriginalOrdinalNumber - ExportDirectory->Base);
    65.     } else {
    66.              //
    67.              // Change AddressOfData from an RVA to a VA.
    68.              //
    69.  
    70.              AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ImageBase + ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xffffffff));
    71.              ImportString = (PSZ)AddressOfData->Name;
    72.  
    73.              //
    74.              // Lookup Name in NameTable
    75.              //
    76.  
    77.              NameTableBase = (PULONG)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
    78.              NameOrdinalTableBase = (PUSHORT)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
    79.  
    80.              //
    81.              // Before dropping into binary search, see if
    82.              // the hint index results in a successful
    83.              // match. If the hint index is zero, then
    84.              // drop into binary search.
    85.              //
    86.  
    87.              HintIndex = AddressOfData->Hint;
    88.              if ((ULONG)HintIndex < ExportDirectory->NumberOfNames &&
    89.                  !strcmp(ImportString, (PSZ)((ULONG_PTR)DllBase + NameTableBase[HintIndex]))) {
    90.                  OrdinalNumber = NameOrdinalTableBase[HintIndex];
    91. #if LDRDBG
    92.                  if (ShowSnaps) {
    93.                      DbgPrint("LDR: Snapping %s\n", ImportString);
    94.                  }
    95. #endif
    96.              } else {
    97. #if LDRDBG
    98.                       if (HintIndex) {
    99.                           DbgPrint("LDR: Warning HintIndex Failure. Name %s (%lx) Hint 0x%lx\n",
    100.                               ImportString,
    101.                               (ULONG)ImportString,
    102.                               (ULONG)HintIndex
    103.                               );
    104.                       }
    105. #endif
    106.                       OrdinalNumber = LdrpNameToOrdinal(
    107.                                         ImportString,
    108.                                         ExportDirectory->NumberOfNames,
    109.                                         DllBase,
    110.                                         NameTableBase,
    111.                                         NameOrdinalTableBase
    112.                                         );
    113.                     }
    114.            }
    115.  
    116.     //
    117.     // If OrdinalNumber is not within the Export Address Table,
    118.     // then DLL does not implement function. Snap to LDRP_BAD_DLL.
    119.     //
    120.  
    121.     if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
    122. baddllref:
    123. #if DBG
    124.         if (StaticSnap) {
    125.             if (Ordinal) {
    126.                 DbgPrint("LDR: Can't locate ordinal 0x%lx\n", OriginalOrdinalNumber);
    127.                 }
    128.             else {
    129.                 DbgPrint("LDR: Can't locate %s\n", ImportString);
    130.                 }
    131.         }
    132. #endif
    133.         if ( StaticSnap ) {
    134.             //
    135.             // Hard Error Time
    136.             //
    137.  
    138.             ULONG_PTR ErrorParameters[3];
    139.             UNICODE_STRING ErrorDllName, ErrorEntryPointName;
    140.             ANSI_STRING AnsiScratch;
    141.             ULONG ParameterStringMask;
    142.             ULONG ErrorResponse;
    143.  
    144.             RtlInitAnsiString(&AnsiScratch,DllName ? DllName : "Unknown");
    145.             RtlAnsiStringToUnicodeString(&ErrorDllName,&AnsiScratch,TRUE);
    146.             ErrorParameters[1] = (ULONG_PTR)&ErrorDllName;
    147.             ParameterStringMask = 2;
    148.  
    149.             if ( Ordinal ) {
    150.                 ErrorParameters[0] = OriginalOrdinalNumber;
    151.                 }
    152.             else {
    153.                 RtlInitAnsiString(&AnsiScratch,ImportString);
    154.                 RtlAnsiStringToUnicodeString(&ErrorEntryPointName,&AnsiScratch,TRUE);
    155.                 ErrorParameters[0] = (ULONG_PTR)&ErrorEntryPointName;
    156.                 ParameterStringMask = 3;
    157.                 }
    158.  
    159.  
    160.             NtRaiseHardError(
    161.               Ordinal ? STATUS_ORDINAL_NOT_FOUND : STATUS_ENTRYPOINT_NOT_FOUND,
    162.               2,
    163.               ParameterStringMask,
    164.               ErrorParameters,
    165.               OptionOk,
    166.               &ErrorResponse
    167.               );
    168.  
    169.             if ( LdrpInLdrInit ) {
    170.                 LdrpFatalHardErrorCount++;
    171.                 }
    172.             RtlFreeUnicodeString(&ErrorDllName);
    173.             if ( !Ordinal ) {
    174.                 RtlFreeUnicodeString(&ErrorEntryPointName);
    175.                 RtlRaiseStatus(STATUS_ENTRYPOINT_NOT_FOUND);
    176.                 }
    177.             RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND);
    178.             }
    179.         Thunk->u1.Function = (ULONG_PTR)LDRP_BAD_DLL;
    180.         st = Ordinal ? STATUS_ORDINAL_NOT_FOUND : STATUS_ENTRYPOINT_NOT_FOUND;
    181.     } else {
    182.              Addr = (PULONG)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
    183.              Thunk->u1.Function = ((ULONG_PTR)DllBase + Addr[OrdinalNumber]);
    184.              if (Thunk->u1.Function > (ULONG_PTR)ExportDirectory &&
    185.                  Thunk->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)
    186.                 ) {
    187.                 UNICODE_STRING UnicodeString;
    188.                 ANSI_STRING ForwardDllName;
    189.                 PVOID ForwardDllHandle;
    190.                 PUNICODE_STRING ForwardProcName;
    191.                 ULONG ForwardProcOrdinal;
    192.  
    193.                 ImportString = (PSZ)Thunk->u1.Function;
    194.                 ForwardDllName.Buffer = ImportString,
    195.                 ForwardDllName.Length = (USHORT)(strchr(ImportString, '.') - ImportString);
    196.                 ForwardDllName.MaximumLength = ForwardDllName.Length;
    197.                 st = RtlAnsiStringToUnicodeString(&UnicodeString, &ForwardDllName, TRUE);
    198.  
    199.                 if (NT_SUCCESS(st)) {
    200. #if defined (WX86)
    201.                     if (Wx86ProcessInit) {
    202.                         NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = RtlImageNtHeader(DllBase)->FileHeader.Machine
    203.                                                    == IMAGE_FILE_MACHINE_I386;
    204.  
    205.                         }
    206. #endif
    207.  
    208.  
    209.                         st = LdrpLoadDll(NULL, NULL, &UnicodeString, &ForwardDllHandle,FALSE);
    210.                     RtlFreeUnicodeString(&UnicodeString);
    211.                     }
    212.  
    213.                 if (!NT_SUCCESS(st)) {
    214.                     goto baddllref;
    215.                     }
    216.  
    217.                 RtlInitAnsiString( &ForwardDllName,
    218.                                    ImportString + ForwardDllName.Length + 1
    219.                                  );
    220.                 if (ForwardDllName.Length > 1 &&
    221.                     *ForwardDllName.Buffer == '#'
    222.                    ) {
    223.                     ForwardProcName = NULL;
    224.                     st = RtlCharToInteger( ForwardDllName.Buffer+1,
    225.                                            0,
    226.                                            &ForwardProcOrdinal
    227.                                          );
    228.                     if (!NT_SUCCESS(st)) {
    229.                         goto baddllref;
    230.                         }
    231.                     }
    232.                 else {
    233.                     ForwardProcName = (PUNICODE_STRING)&ForwardDllName;
    234.  
    235.                     //
    236.                     // Following line is not needed since this is a by name lookup
    237.                     //
    238.                     //
    239.                     //ForwardProcOrdinal = (ULONG)&ForwardDllName;
    240.                     //
    241.                     }
    242.  
    243.                 st = LdrpGetProcedureAddress( ForwardDllHandle,
    244.                                               (PANSI_STRING )ForwardProcName,
    245.                                               ForwardProcOrdinal,
    246.                                               &(PVOID)Thunk->u1.Function,
    247.                                               FALSE
    248.                                             );
    249.                 if (!NT_SUCCESS(st)) {
    250.                     goto baddllref;
    251.                     }
    252.                 }
    253.              else {
    254.                 if ( !Addr[OrdinalNumber] ) {
    255.                     goto baddllref;
    256.                     }
    257. #if defined (_ALPHA_) && defined (WX86)
    258.                 else {
    259.                    PIMAGE_NT_HEADERS ExportNtHeaders = RtlImageNtHeader(DllBase);
    260.  
    261.                    if ((ExportNtHeaders->OptionalHeader.SectionAlignment < PAGE_SIZE) &&
    262.                        (ExportNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)) {
    263.                        Thunk->u1.Function += LdrpWx86RelocatedFixupDiff(DllBase, Addr[OrdinalNumber]);
    264.                     }
    265.                 }
    266. #endif //  defined (_ALPHA_) && defined (WX86)
    267.              }
    268.              st = STATUS_SUCCESS;
    269.            }
    270.     return st;
    271. }
    272.