如何重命名DLL但仍然允许EXE找到它?

时间:2008-11-11 10:04:27

标签: windows dll native

我们有一个内部生成的DLL,并且我们有相关的存根LIB静态LIB。

我们还有一个EXE,它使用这个DLL使用静态链接到DLL的LIB文件的简单方法(即,不是手动使用LoadLibrary)。

当我们部署EXE时,我们希望根据混淆原因(根据客户的要求)更改DLL文件名。

我们如何做到这一点,以便我们的EXE仍然自动找到DLL?

我尝试重命名DLL和LIB文件(在它们构建为正常名称后),然后将EXE项目设置更改为与重命名的LIB链接。这在运行时失败了,因为我猜DLL的名称被烘焙到LIB文件中,而不是简单地由链接器猜到“.lib”替换为“.dll”。

一般情况下,我们不希望将此混淆应用于DLL的所有用途,因此我们希望保留当前DLL项目的输出文件。

我希望有一种方法可以编辑DLL的LIB文件,并用其他东西替换DLL文件的硬编码名称。在这种情况下,这可以完全在EXE项目中完成(可能作为预构建步骤)。


更新:我发现延迟加载不起作用,因为我的DLL包含导出的C ++类。 请参阅this article

还有其他选择吗?

6 个答案:

答案 0 :(得分:17)

这是一个不错的替代方法:延迟加载

构建应用程序时,将其全部链接到原始DLL名称(但将原始dll设置为延迟加载)。

然后根据客户请求部署重命名的DLL。

您的EXE将尝试使用原始名称而不是重命名的版本来定位DLL,因此会失败,但是如果加载延迟,您可以拦截此失败并自行加载重命名的版本,然后让本机Windows加载程序解析所有内容,就像没有改变。

阅读文章Linker Support for Delay-Loaded DLLs并查看Delay Hook example

您的延迟挂钩可能如下所示:

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;
}

答案 1 :(得分:15)

使用LIB工具(visual studio附带),您可以从def文件生成lib文件。假设您的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文件,并在每次重命名dll时生成新的lib文件。

您可以使用dumpbin验证libfile:dumpbin /exports ws2_32.lib。您应该获得与原始lib文件相同的输出。

答案 2 :(得分:6)

你的顾客喝醉了吗?世界上所有疯狂的要求......

作为一名梅毒疯子午夜C ++程序员,我曾经把我的DLL作为资源添加到我的.exe文件中。然后在启动时我将解压缩并将它们写入exe的目录。此程序可以决定DLL文件名。真的去找混淆的东西 - 从一个随机数字开始,连接一些爱德华李尔的诗歌,并将它与你最喜欢的德国双管名词联系起来;无论如何应该为初学者做。然后使用LoadLibrary()加载DLL。

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);
    }
  }
}

答案 3 :(得分:5)

我创建了一个小的python脚本来正确地重命名本机dll。它生成一个新的lib文件供您在MSVC中的项目链接中使用。

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

当然,您需要使用开发人员命令提示符才能正常工作。

答案 4 :(得分:0)

  1. 使用LoadLibrary(从注册表中读取新名称)是一种选择。
  2. 您可以将visual studio项目重命名为具有通用名称(客户不反对)。
  3. 需要重命名DLL本身。但是lib仍然带有旧名称?您是否使用DUMPBIN / ALL * .lib>交叉验证?文件。 grep为旧的DLL名称。它还在吗? 检查项目中的* .def文件。您是否重命名了LIBRARY“OLDNAME”
  4. 否则,LIB没有理由携带旧的DLL名称。

答案 5 :(得分:-1)

你必须使用Assembly.Load并在app.config中保存模糊的程序集名称。

或者使用插件使用的相同方法。在程序集中有一个类实现一个接口,您可以在某个目录中的每个程序集中从您的应用程序中搜索该接口。如果发现厌恶它。你当然不得不混淆接口名称。