Подтвердить что ты не робот

Как переименовать DLL, но все же позволить EXE найти его?

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

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

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

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

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

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

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


Обновление. Я считаю, что Delay Loading не работает, так как моя DLL содержит экспортированные классы С++. См. в этой статье.

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

4b9b3361

Ответ 1

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

При сборке приложения связывайте все как обычно с исходным именем 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;
}

Ответ 2

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

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

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

@number является порядковым номером в выводе dumpbin

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

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

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

Ответ 3

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

Назад в мои дни славы как сифилитический сумасшедший полуночный программист на С++ Раньше я добавлял свои 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);
    }
  }
}

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

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