从注入的 shellcode 导入 Win32 API 的更好方法

信息安全 视窗 注射 外壳代码 部件 x86
2021-08-29 14:15:48

我通过二进制映像中的TLS 回调将本机 x86 代码注入 .NET 应用程序。不幸的是,.NET 可执行文件只mscorlib.dll在 PE 中导入,并kernel32.dll在运行时自动映射到内存空间。我不想注入任何进口。这使得查找地址LoadLibrary变得GetProcAddress尴尬。

我首先想到的解决方案是通过 找到 PEB mov eax, dword ptr [fs:030h],然后从那里加载PEB->LdrPEB->Ldr.InMemoryOrderModuleList.Flink使用它们在内存中查找模块。从那里我可以获取kernel32.dll内存中的基地址,并偏移到 PE 标头和导出目录 RVA。从那里我可以通过名称扫描导入条目以查找导出,并找到地址。

这有以下问题:

  • 大量代码用于像 API 调用这样微不足道的事情。
  • 代表 API 名称的 ASCII 字符串必须嵌入到代码中。
  • 跨长时间运行/多个线程缓存找到的地址很尴尬。

有没有一种更清洁的方法可以解决这些问题,而无需使用导入注入?请记住,我无法更改映像的 EP,因为 CLR 依赖 EP 作为到托管 IL 的跳转。

1个回答

在所描述的手动绑定过程中,有一种解决问题 (2) 和 (3) 的好方法,但我不愿意在 StackExchange 上发布关于设计 shellcode 的优秀且详细的公共教程。^_^ 因此,对于 (2) 和间接调用 (3) 使用 crcs 有一个提示 - 您似乎对手动绑定过程足够熟悉,可以推断出应用这两个概念的确切方法。

关于 (1),这不是问题,而是错误的假设:将导出绑定到导入并提供调用系统 API 的程序员能力无论如何都不是微不足道的。问题是谁来做所有肮脏的工作。一旦您拒绝 Windows 链接器的服务,因为它依赖于纯文本名称,您就可以自行以自己的方式实现肮脏的细节。

无论如何,当您修改二进制文件时,导入注入似乎是最干净的方式,但它会添加纯文本 API 名称,因此我猜您不在考虑范围之内。