BumbleCrypt
一个受 Bumblebee 启发的 Crypter
背景
BumbleCrypt 的灵感源自 Bumblebee 的 crypter。在 Bumblebee 的案例中,主 Bumblebee DLL 被加载到内存中,并按以下方式执行:
- 解密并将 payload 写入 Heap(堆)中
- Hook 三个 NtApi —— NtOpenFile、NtCreateSection 和 NtMapViewOfSection
- 调用 LoadLibraryW("gdiplus.dll"),这会触发 inline hooks,因为上述三个 API 会被 LoadLibrary() 用来加载任何库。
- 随后,inline hooks 和 LoadLibrary 本身会加载主 Bumblebee DLL,以代替 "gdiplus.dll"
- 最后,控制权被转移到主 Bumblebee DLL 的导出函数 "SetPath"
BumbleCrypt 的工作原理
在分析 BumbleBee 的 crypter 时,我意识到,只需在 "NtMapViewOfSection" 上设置一个 inline hook,就能加载解密后的 DLL,而不需要 Bumblebee 的 Crypter 中使用的三个 inline hooks。
因此,我开发了 "BumbleCrypt"。
BumbleCrypt:
-
BumbleCrypt 首先从 .rsrc 节加载一个加密资源,然后解密最终的 DLL payload:加密资源 -> Base64 解码 -> Rc4 解密 -> xor 解密
-
该 Crypter 利用 Heap(堆)来存储解密后的 DLL payload,与 Bumblebee 的 crypter 一样
-
一旦最终 payload 被解密,BumbleCrypt 就会 hook NtApi "NtMapViewOfSection",该 API 用于将节的视图映射到虚拟地址空间中。
-
然后 BumbleCrypt 调用 LoadLibraryW("msimg32.dll")。现在让我们了解 inline hook 是如何被触发的:
- LoadLibraryW() 首先调用 NtOpenFile 来获取作为参数传入的模块的句柄
- 然后它使用 NtCreateSection 通过该模块句柄创建一个 section 对象
- 一旦 section 创建完成,LoadLibrary 就会调用 NtMapViewOfSection,以便将 section 的视图映射到内存中
- 此时,我们对 NtMapViewOfSection 的 hook 被触发,代理函数执行以下操作:
- 首先取消对 NtMapViewOfSection 的 hook
- 使用 NtCreateSection() 创建一个所需大小的 section
- 然后使用 NtMapViewOfSection(之前已取消 hook)将所创建 section 的视图映射到虚拟地址空间中
- 最后,它手动将之前解密好的最终 DLL 映射到内存映射 section 的基址上,然后向 LoadLibraryW 返回 NTSTATUS_SUCCESS,并从代理函数退出
- 然后,LoadLibraryW 收到作为 NtMapViewOfSection 响应的 NTSTATUS_SUCCESS,以及内存映射 section 的基址,解密后的恶意 DLL 就位于该内存中。随后,LoadLibrary 根据返回值加载该 DLL,最终结果是:在已加载模块中可以看到 msimg32.dll,但其指向的是解密后的 payload。此外,该 Crypter 通过执行导出函数 "CallPath" 将控制权转移到解密后的 DLL。
-
现在,如果我们查看 BumbleCrypt 已加载模块的截图,可以看到其中包含 "msimg32.dll",但其基址指向解密后的恶意 payload。
截图


PoC - BumbleCrypter

非常感谢!希望你喜欢 =D
Ciao.
如果你有任何反馈或评论,可以在 Twitter 上联系我
Twitter: https://twitter.com/knight0x07
注意
仅供教育用途。这只是个人周末项目 =)