十六进制编辑 dll 以更改依赖项名称?
Posted
技术标签:
【中文标题】十六进制编辑 dll 以更改依赖项名称?【英文标题】:Hex edit a dll to change a dependency name? 【发布时间】:2010-08-05 23:41:38 【问题描述】:我有一个依赖于 OPENGL.DLL 的 dll。但是,Windows 附带 OpenGL32.dll 。我想在 dll 二进制文件中更改此依赖项名称,以便它改为查找 OpenGL32.dll。我尝试在 VS 的二进制编辑器中打开它,但我似乎无法使名称更长。例如,我可以将其更改为 OpenDD.dll,但无法添加。我怎么能这样做?
如果我将其编辑为 OpenGLAA 或 OpenGLJU,则可以,但更改为 OpenGL32 会导致它说找不到 .dll
【问题讨论】:
OPENGL.DLL 和 OpenGL32.dll 似乎不太可能互换。它们可能是不同的版本。 不,我试过了,效果很好 你似乎在自相矛盾。听起来您是在说您可以编辑二进制文件以将“OPENGL.DLL”(10 个字节)更改为例如“OpenDD.dll”(10 个字节),但您不能将其更改为“OpenGL32.dll” "(12 个字节)。但是你会说:“如果我把它编辑成像 OpenGLAA 或 OpenGLJU 这样就可以了”。那么它是什么? 【参考方案1】:在PE中如何更改导入的dll名称有点难用英文解释 (有相当多的间接和 RVA 级别),但是 意外地,我有一个可以用于此类内容的库。 不过,仅限 PE32。
所以这是您可以使用的实用程序:http://nishi.dreamhosters.com/dllrepl_v0.rar (有来源)。 它是这样工作的: (UpdateImports() 做这件事)
struct PE_Hdr1 : PE_Hdr
void UpdateImports( char* s1, char* s2 )
int c,i,j;
int p = 0;
uint ofs = 0x50;
printf( "Redirecting <%s> to <%s>\n", s1, s2 );
// store the target dll name to some place in MZ header
memcpy( &exedata[ofs], s2, strlen(s2)+1 );
uint idtrva = tbl[1].VA;
PE_IDRec* idt = (PE_IDRec*)&exedata[ RVA2Ofs(idtrva) ];
for( i=0; i<nIDRec; i++ )
char* dllname = (char*)&exedata[ RVA2Ofs( idt[i].DLLName ) ];
printf( "dllname=<%s>", dllname );
if( stricmp( dllname, s1 )==0 )
printf( " -> <%s>", s2 );
idt[i].DLLName = ofs;
printf( "\n" );
;
// Usage: dllrepl file.exe file_out.exe msvcrt.dll msvcrt32.dll
int main( int argc, char** argv )
if( argc<5 ) return 1;
FILE* f = fopen( argv[1], "rb" ); if( f==0 ) return 1;
FILE* g = fopen( argv[2], "wb" ); if( g==0 ) return 1;
MZ_Hdr mz; PE_Hdr pe;
PE_Open( mz, pe, f );
((PE_Hdr1&)pe).UpdateImports( argv[3], argv[4] );
fwrite( pe.exedata, 1,pe.exesize, g );
dll 名称的新位置有点骇人听闻,但分配了 PE 中的安全区域会变得更加复杂。
【讨论】:
下载链接暂时不可用,您提供的demo源码无法编译。请修复下载链接。谢谢。 嗨。优秀的工具。我刚刚注意到,在第二次通过时,您存储的条目(s2)被覆盖(可能是因为您提到的“hackish”方式)。你能看出你的做法有什么潜在的问题吗? (我还没有尝试在生成的 .exe 中运行 UPX 或类似工具,现在我正在尝试了解如何调整您的代码以交换多个名称) 它在可执行文件的 DOS 头中使用固定位置 0x50(这几天基本上没用)。如果您想替换多个 dll 名称,我想您可以在第一个之后继续编写它们 - 至少在 0xC0 左右之前仍有“未使用”空间。正确的做法是在 exe 中添加一个新部分。【参考方案2】:您可能想尝试创建一个名为 OPENGL.DLL 的“转发 DLL”,它只是转发到 OpenGL32.dll:
Raymond Chen 的“真正是转发器的导出函数”文章:http://blogs.msdn.com/b/oldnewthing/archive/2006/07/19/671238.aspx
MSDN 杂志,2002 年 3 月,“深入了解 Win32 可移植可执行文件格式,第 2 部分”:http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
Microsoft 系统日志,1996 年 9 月:http://www.microsoft.com/msj/archive/S202B.aspx
http://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx
当然,这假设 API 具有相同的签名。如果没有,那么您可以编写一个具有正确 API 签名的包装 OPENGL.DLL,然后转而调用 OpenGL32.dll 函数。如果有很多函数,这可能是一项乏味的任务,但如果 API 存在差异,则需要有一些东西来处理这些差异。
【讨论】:
【参考方案3】:您可以尝试制作 OpenGL32.DLL 的副本,将其命名为 OPENGL.DLL,而不是编辑引用它的二进制文件。
看来 OPENGL.DLL 和 OpenGL32.DLL 可能是不同的版本,因此您无法将一个换成另一个。
【讨论】:
不,它可以工作,我想将其更改为 Opengl32 以避免将 OPENGL.dll 与我的应用一起发送【参考方案4】:不要十六进制编辑您的 .dll,只需链接到正确版本的 opengl。来自http://www.opengl.org/resources/faq/technical/gettingstarted.htm#0010:
如果您看到诸如 opengl.lib 之类的文件 和 glut.lib,这些是 SGI 的 Microsoft 不受支持的库 视窗。不应使用它们。到 使用硬件加速, 建议使用 Microsoft 库。 More info on the SGI libraries can be found here。 始终与 要么所有 Microsoft 库(例如, glu32.lib、glut32.lib 和 opengl32.lib) 或所有 SGI 库 (例如,glu.lib、glut.lib 和 opengl.lib)。你不能使用 微软的结合 libarires 和 SGI 库。 但是, 您可以安装两组库 在同一个系统上。如果您使用 SGI .lib 文件,你需要 相应的 .dll 文件安装在 你的系统文件夹。 (即,链接 针对 opengl.lib 要求 opengl.dll 在运行时安装)。
【讨论】:
我的问题是 glu32 崩溃而 glu 没有 @Jex,什么是崩溃?调用栈等?【参考方案5】:您可以将依赖项设置为某个合适的名称,然后使用该名称创建另一个 DLL,将所有相关名称转发到 opengl32.dll。从将调用定向到 OpenGL32.DLL 的纯技术角度来看,应该没有问题(除了它继续需要您可能更愿意避免的外部 DLL 的事实之外)。如果您确实需要将依赖项直接更改为 OpenGL32.dll,这将是非常重要的。对于大多数实际目的,您首先需要复制链接器为生成可执行文件所做的大部分工作——这在理论上是可能的,但称其为非平凡是一种严重的轻描淡写。
【讨论】:
但它正在工作,这个解决方案涉及创建另一个 dll 依赖项并避免依赖项是我这样做的目的:p @Jex:见编辑。真正的问题是你如何以及为什么要生产首先取决于opengl.dll
的东西。【参考方案6】:
嗯,永远不要为你的目的重命名系统 DLL。
如果您执行任何操作,请将其复制到您的 .EXE 文件夹并将其重命名为 OpenGLMYHACKEDVERSION.dll 之类的名称。这样,另一个寻找真实系统 .dll 的应用程序就不可能使用它的“您的”版本。
【讨论】:
以上是关于十六进制编辑 dll 以更改依赖项名称?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 NuGet 包及其依赖项安装 PowerShell 二进制 cmdlet (C#)