26

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

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

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

我们怎样才能做到这一点,以便我们的 EXE 仍然自动找到 DLL?

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

一般来说,我们不想将这种混淆应用于 DLL 的所有用途,因此我们希望保持当前 DLL 项目输出文件的原样。

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


更新:我发现延迟加载不起作用,因为我的 DLL 包含导出的 C++ 类。见这篇文章

有没有其他选择?

4

6 回答 6

19

使用 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 时生成一个新的 libfile。

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

于 2008-11-11T10:45:06.707 回答
19

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

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

然后,您根据客户的要求部署重命名的 DLL。

您的 EXE 将尝试使用原始名称而不是重命名的版本来定位 DLL,因此会失败,但是通过延迟加载,您可以拦截此失败并自己加载重命名的版本,然后让本机 Windows 加载器解决所有问题,就好像没有任何改变一样。

阅读文章Linker Support for Delay-Loaded DLLs并查看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;
}
于 2008-11-11T14:25:49.460 回答
7

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

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

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

于 2018-02-25T00:52:16.103 回答
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);
    }
  }
}
于 2008-11-12T23:55:29.840 回答
0
  1. 使用 LoadLibrary(从注册表中读取新名称)是一种选择。
  2. 您可以将您的 Visual Studio 项目重命名为具有通用名称(您的客户不反对)。
  3. DLL 本身需要重命名。但是 lib 仍然带有旧名称?您是否使用 DUMPBIN /ALL *.lib > 文件进行了交叉验证。grep 获取旧的 DLL 名称。它还在吗?检查项目中的 *.def 文件。您是否将 LIBRARY 重命名为“OLDNAME”

否则,LIB 没有理由携带旧的 DLL 名称。

于 2010-03-05T12:22:05.317 回答
-2

您必须使用 Assembly.Load 并将混淆的程序集名称保存在 app.config 中。

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

于 2008-11-11T10:23:57.327 回答