超级任天堂娱乐系统(SNES,SuperNintendoEntertainmentSystem)是任天堂全球知名主机NES(国内通称小霸王)的后续主机。当时很棒。作为当时的主机霸主,任天堂SNES主机上出现了很多经典游戏,现在也有不少热门游戏系列在SNES上发家致富。像勇者斗恶龙系列、传奇系列、最终幻想系列、时空之轮系列等等。当时,超级任天堂一直以全球数千万台的销量占据游戏机市场的头把交椅。在这个优秀的平台上,诞生了无数优秀的优质游戏。现在很多作品都是拿PS2、XBOX游戏来比的。它在游戏性方面并不逊色(实际上比它们要好得多)。如果你无法忘记那些刺激的游戏,Snes9x可以在你的电脑上模拟超级任天堂,让你再次回到童年。该软件可以根据不同的硬件轻松调整声音、图像等。上图的程序是许多游戏爱好者都使用过的SNES模拟器。网上不难找到这些东西,但我不会在文章中提及它们,因为这样做从技术上讲是在传播盗版。首先,我拿出我的旧外部硬盘驱动器,找到我的SNES9x模拟器的压缩副本,启动它,发现一个DLL劫持漏洞。Snes9x是一款SNES模拟器,可让您重温童年游戏。是一款可以在Windows平台上运行经典SNES/SFC游戏的模拟器软件。支持.smc、.sfc、.fig、.1格式的游戏,可以用键盘操作,也可以用手柄操作,支持按键修改。为x86和x64体系结构编写的程序利用动态链接库(DLL)在软件开发过程中提供灵活性和可移植性。DLL基本上是包含可重用代码、资源和变量的小程序。就其本质而言,它们没有入口点,需要父可执行文件才能在运行时调用它们。如果你只有一个DLL,你可以使用类似Rundll32.exe的东西来运行那个没有父程序的特定DLL的内容。否则,父可执行文件可以调用DLL中的函数,使用LoadLibraryAPI调用将它们动态导入到程序中。有时软件开发并没有完全按计划进行,您可能经常编写一个程序来调用加载一个不存在的DLL。或者,在SNES模拟器的情况下,你可能有一个路径洞的等价物,这基本上意味着程序试图从当前工作目录加载DLL,然后寻找其他地方。以下是我加载Procmon并运行SNES模拟器时发生的情况:在上图中,SNES模拟器已放置在我的FlareVM主机的桌面上。当程序尝试加载opengl32.dll时,它首先检查当前工作目录C:\Users\Husky\Desktop\SNES32bit\。当它在这里找不到指定的DLL时,它会转到SysWOW64目录并加载在那里成功存在的DLL。此SNES模拟器是一个32位应用程序,因此检查SysWOW64是否需要dll是有意义的。请注意,System32和SysWOW64有点像冰岛/格陵兰的情况。在标准的x64设备上,64位系统目录是System32,32位系统目录是SysWOW64。简而言之,这是一个漏洞。程序试图从可写目录加载DLL。这是因为程序已经被复制到桌面,而不是被安装在一个标准的程序目录下,比如“ProgramFiles”。共享软件很容易发生,即从硬盘驱动器共享它,然后将文件复制到他们自己的笔记本电脑。另外,这里需要注意的是,SNES模拟器有DEP但没有ASLR,以后可能会恢复到DEP。现在在某些攻击场景中,DLL劫持是通过简单地获取MSFVenomDLL负载并将其替换为程序试图加载4head的负载来实现的。直到程序崩溃或无法加载:DOS超出此范围,更好的是,进入DLL代理。DLLProxyDLLProxy具有较高的DLL劫持成功率。您可能能够从DLL劫持中执行shellcode,但该程序仍然需要解析它打算从原始DLL进行的函数调用。并且您的MSFVenom生成的DLL不知道如何处理这些请求的函数,因此calc.exe运行并且程序崩溃。在DLL代理中,您创建一个新的DLL,其中包含指向从原始DLL导入的函数的指针。有效负载隐藏在此DLL的一部分中,并使用剩余空间将可执行文件指向它要加载的原始DLL。该程序以其最初的预期功能执行,从而导致负载执行。使用Procmon,筛选以下内容:打开可执行文件或10并识别尝试加载到DLL中但未成功的程序。在本文的示例中,我重点关注OpenGL32.dll:Reconfigure筛选器,以查看此DLL是否在程序执行的任何时刻成功加载。因此,通过简单的过滤来扩展您的搜索:如果您找到了一个好的DLL代理候选者,您可能会看到类似这样的内容:如您所见,成功加载的DLL从主机复制到攻击者的设备,并将其命名为[dllName]_original.dll。幸运的是,这个DLL可能在所有Windows系统上都是本机的,因此您甚至可能不需要从目标主机复制它,只需从您自己的Windows主机复制即可。在攻击者的设备上,使用这个简单的Python脚本从原始DLL中获取导出的函数并将它们写入模块定义文件(.def):注意引用原始DLL的两个地方,并确保相应地更改这些值。编译程序时,模块定义文件向编译器提供有关链接导出的信息。在本文的示例中,我们将告诉编译器创建一个代理DLL并将其链接到原始DLL以指向它导出的所有函数。因此,每当可执行文件询问“嘿DLL,函数在哪里?”时。代理DLL回复:“哦,是的,去检查[dllName]_original.dll,它应该在那里。”现在,我们制作代理DLL。这是一个用C编写的非常简单的程序,它导出一个DLLMain函数作为DLL的入口点。在DLLMain方法中,我们偷偷调用了Payload函数。此函数执行,然后所有其他请求的函数调用传递给[dllName]_original.dll:创建此C文件并将其命名为[dllName].c:到目前为止一切顺利。最后,我们需要创建这个代理DLL并将它与我们的模块定义文件链接起来。这可以通过mingw-w64完成,它具有编译DLL所需的必要工具链。注意这里的架构:我代理了32位SNES模拟器,所以我需要为32位架构编译它。如果你的攻击设备上没有mingw-w64,只需键入:然后,编译我们的DLL:当DLL编译时,你现在应该有四个文件可供使用:[dllName]_original.dll:我们从主机中提取,重命名为“_original”[dllName].c:包含我们有效负载的代理DLL的C代码。[dllName].def:通过使用Python脚本从原始dll中提取导出的函数调用而创建的模块定义文件。[dllName].dll:新编译的代理DLL。最后一步是将原DLL和代理DLL登陆到目标主机的程序目录下,这两个DLL必须和原程序在同一个目录下。找到这两个DLL后,启动程序!此时,您已将一个功能齐全的程序加载到代理DLL中。没有崩溃,没有段错误,只是计算。本文翻译自:https://huskyhacks.dev/2021/08/29/dll-hijacking-dll-proxying-an-snes-emulator/
