Как переименовать DLL, но все же разрешить EXE найти ее? - PullRequest
19 голосов
/ 11 ноября 2008

У нас есть DLL, которая создается самостоятельно, и для которой у нас есть связанная статическая LIB-заглушка.

У нас также есть EXE, который использует эту DLL, используя простой метод статического связывания с файлом LIB библиотеки DLL (т. Е. Не используя LoadLibrary вручную).

При развертывании EXE мы хотим, чтобы имя файла DLL было изменено по причинам запутывания (по запросу клиента).

Как мы можем сделать это, чтобы наш EXE-файл все еще находил DLL автоматически?

Я попытался переименовать файлы DLL и LIB (после того, как они были собраны в их обычное имя), затем изменил настройки проекта EXE, чтобы связать их с переименованной LIB. Это терпит неудачу во время выполнения, поскольку я предполагаю, что имя DLL запекается в файле LIB, а не просто угадывается компоновщиком, заменяющим «.lib» на «.dll».

В общем, мы не хотим применять эту обфускацию ко всем видам использования DLL, поэтому мы хотели бы сохранить текущие выходные файлы проекта DLL, если они есть.

Я надеюсь, что найдется метод, с помощью которого мы сможем отредактировать LIB-файл DLL и заменить жестко запрограммированное имя DLL-файла чем-то другим. В этом случае это можно сделать полностью в рамках проекта EXE (возможно, в качестве этапа предварительной сборки).


Обновление : Я считаю, что отложенная загрузка не работает, так как моя DLL содержит экспортированные классы C ++. См. эту статью .

Есть ли альтернативы?

Ответы [ 6 ]

17 голосов
/ 11 ноября 2008

Вот хороший альтернативный подход: задержка загрузки .

При сборке приложения свяжите все это так же, как если бы вы использовали оригинальное имя DLL (но установите исходную dll для загрузки с задержкой).

Затем вы развертываете DLL, переименованную в соответствии с запросом ваших клиентов.

Ваш EXE попытается найти DLL, используя оригинальное имя, а не переименованную версию, поэтому произойдет сбой, однако при задержке загрузки вы можете перехватить этот сбой и загрузить переименованную версию самостоятельно, а затем собственный загрузчик Windows разрешит все, как ничего не изменилось.

Прочтите статью Поддержка компоновщика DLL-библиотек с задержкой и посмотрите пример Delay Hook .

Ваш крюк задержки может выглядеть примерно так:

FARPROC WINAPI delayHook( unsigned dliNotify, PDelayLoadInfo pdli )
{
    switch( dliNotify )
    {
        case dliNotePreLoadLibrary:
            if( strcmp( pdli->szDll, "origional.dll" ) == 0 )
                return (FARPROC)LoadLibrary( "renamed.dll" );
            break;
        default:
            return NULL;
    }

    return NULL;
}
15 голосов
/ 11 ноября 2008

Используя инструмент LIB (входит в Visual Studio), вы можете создать файл lib из файла def. Предполагая, что ваш источник DLL не содержит файл def, вы должны сначала создать его. Вы можете использовать свалку, чтобы помочь вам. Например: dumpbin /exports ws2_32.dll

В выводе вы видите имена экспортируемых функций. Теперь создайте файл def следующим образом:

LIBRARY WS2_32
EXPORTS
    accept      @1
    bind        @2
    closesocket @3
    connect     @4

Номер @ - это порядковый номер в выводе дампа

Используйте LIB /MACHINE:x86 /def:ws2_32.def для генерации файла lib.

Теперь вы можете легко изменять файл def и генерировать новый libfile каждый раз, когда вы переименовываете свою dll.

вы можете проверить libfile, используя dumpbin: dumpbin /exports ws2_32.lib. Вы должны получить тот же вывод, что и исходный файл lib.

6 голосов
/ 13 ноября 2008

Ваш клиент пьян? Из всех безумных требований во всем мире ...

В свои славные времена, когда я был сифилитическим безумным полуночным программистом на C ++, я использовал для добавления своих DLL в файл .exe в качестве ресурсов. Затем при запуске я распаковываю их и записываю в каталог exe. Ваша программа может выбрать имя файла DLL на этом этапе. На самом деле выбирайте запутывание - начните со случайного числа, объедините некоторые стихи Эдварда Лира и добавьте их в список своих любимых немецких двуствольных существительных; все равно надо делать для начала. Затем загрузите DLL, используя LoadLibrary ().

enum ukOverwrite {dontOverwriteAnything = 0, overwriteWhateverPresent = 1};
void unpackResource (ukOverwrite param1, int resourceID, const char* basePath,  
const char* endFilename)
{
  char* lpName = 0;
  lpName += resourceID;
  HRSRC MrResource = FindResource (0, lpName, "file");

  if (MrResource)
  {
    HGLOBAL loadedResource = LoadResource (0, MrResource);
    if (loadedResource)
    {
      void* lockedResource = LockResource (loadedResource);
      if (lockedResource)
      {
        DWORD size = SizeofResource (0, MrResource);
        if (size)
        {
          unsigned long creationDisposition = CREATE_NEW;
          if (param1 == overwriteWhateverPresent)
            creationDisposition = CREATE_ALWAYS;

          char filepath [MAX_PATH];
          strcpy (filepath, basePath);
          strcat (filepath, endFilename);
          HANDLE rabbit = CreateFile (filepath, GENERIC_WRITE, 0, 0,  
creationDisposition, 0, 0);
          if (rabbit != INVALID_HANDLE_VALUE)
          {
            DWORD numBytesWritten = 0;
            int wf = WriteFile (rabbit, lockedResource, size, &numBytesWritten,  
0);
            CloseHandle (rabbit);
          }
        }
      }
      FreeResource (loadedResource);
    }
  }
}
5 голосов
/ 25 февраля 2018

Я создал небольшой скрипт на Python для правильного переименования нативных библиотек. Он генерирует новый файл lib для использования в компоновке проекта в MSVC.

https://github.com/cmberryau/rename_dll/blob/master/rename_dll.py.

Вам, конечно, нужно использовать командную строку разработчика.

0 голосов
/ 05 марта 2010
  1. Использовать LoadLibrary (чтение нового имени из реестра) - один из вариантов.
  2. Вы можете переименовать ваш проект Visual Studio, чтобы иметь обобщенное имя (которое ваш клиент не имеет возражений).
  3. Сама DLL должна быть переименована. Но библиотека все еще носит старое имя? Вы перепроверяли, используя файл DUMPBIN / ALL * .lib>. grep для старого имени DLL. Это все еще там? Проверьте файл * .def в проекте. Вы переименовали БИБЛИОТЕКУ "OLDNAME"

В противном случае у LIB нет оснований для переноса старого имени DLL.

0 голосов
/ 11 ноября 2008

вам нужно будет использовать Assembly.Load и сохранить запутанное имя сборки в app.config.

Либо это, либо используйте тот же подход, который используют плагины. Пусть класс в вашей сборке реализует интерфейс, который вы ищете из своего приложения в каждой сборке в определенном каталоге. если найден, посмотри на это. вам, конечно, не придется запутывать имя интерфейса.

...