The VPN component in Windscribe 1.81 uses the OpenVPN client for connections. Also, it creates a WindScribeService.exe system process that establishes a \\.\pipe\WindscribeService named pipe endpoint that allows the Windscribe VPN process to connect and execute an OpenVPN process or other processes (like taskkill, etc.). There is no validation of the program name before constructing the lpCommandLine argument for a CreateProcess call. An attacker can run any malicious process with SYSTEM privileges through this named pipe.
Named Pipe function:
Main function for creating NamedPipe:
There are multiple conditions in sendLog_and_CreateProcess functions and in this functions there is validation for COMMAND_EXECUTE(to run openvpn.exe process) in which attacker should sent a byte to buffer.Named Pipe function:
HANDLE createNamedPipe()
{
HANDLE result; // rax@2
struct _SECURITY_ATTRIBUTES SecurityAttributes; // [sp+40h] [bp-28h]@1
SecurityAttributes.lpSecurityDescriptor = malloc(0x28ui64);
if ( InitializeSecurityDescriptor(SecurityAttributes.lpSecurityDescriptor, 1u)
&& SetSecurityDescriptorDacl(SecurityAttributes.lpSecurityDescriptor, 1, 0i64, 0) )
{
SecurityAttributes.nLength = 24;
SecurityAttributes.bInheritHandle = 1;
result = CreateNamedPipeW(
L"\\\\.\\pipe\\WindscribeService",
0x40000003u,
6u,
0xFFu,
0x7D05u,
0x7D05u,
0,
&SecurityAttributes);
}
else
{
result = (HANDLE)-1;
}
return result;
}
First NamedPipe is created and then information is waited in WindscribeService (Running in SYSTEM Privilege) from WindScribe to execute openvpn client or other commands.Main function for creating NamedPipe:
v5 = createNamedPipe(); < === NamedPipe is created by this function.
if ( v5 != (HANDLE)-1 )
{
v6 = CreateEventW(0i64, 1, 1, 0i64);
if ( v6 )
{
ServiceStatus.dwControlsAccepted = 5;
ServiceStatus.dwCurrentState = 4;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
SetServiceStatus(hServiceStatus, &ServiceStatus);
Overlapped.InternalHigh = (ULONG_PTR)v6;
Handles = hEvent;
v19 = v6;
ConnectNamedPipe(v5, &Overlapped);
for ( i = WaitForMultipleObjects(2u, &Handles, 0, 0xFFFFFFFF);
i;
i = WaitForMultipleObjects(2u, &Handles, 0, 0xFFFFFFFF) )
{
if ( i == 1 )
{
v8 = 32005;
v9 = (char *)&Overlapped.hEvent;
LODWORD(v17) = 0;
while ( ReadFile(v5, v9, v8, (LPDWORD)&v17, 0i64) ) // Information (shellcode) sent by attacker is read and written to buffer.
{
v9 += (unsigned int)v17;
v8 -= (unsigned int)v17;
if ( !v8 ) < If data sent by attacker is 32005 byte, sendLog_and_CreateProcess functions are called and data is sent to this function.
{
v11 = 1;
goto LABEL_21;
}
}
v11 = 0;
LABEL_21:
if ( v11 )
{
sendLog_and_CreateProcess(
(__int64)&Buffer,
(__int64)&Overlapped.hEvent,
v10,
&Uuid,
(__int64)engineHandle,
(__int64)&v26);
Then this command line parameter(which has been sent to create process) is sent to send_log_file function for logging.
sendLog_and_CreateProcess function:
send_log_file(&File, L"AA_COMMAND_EXECUTE, blocking=%d, cmd=%s"); < === is sent to log file
if ( *(_BYTE *)(v7 + 4) )
{
sub_13FF6E7C0(v13, v12, v14);
v16 = create_priviliged_process(v15, (__int64)&Memory, v7); < == Information recieved by buffer is sent to CreateProcess function.
}
Then attacker information which has been sent to buffer by Named Pipe, is sent to CreateProcess function in create_priviliged_process and process is executed.MSDN CreateProcess documentation:
CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine, < ===== "calc.exe"
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
create_priviliged_process function:
if ( CreatePipe(&hReadPipe, &hWritePipe, &PipeAttributes, 0) )
{
sub_13FF78490(&StartupInfo, 0i64, 104i64);
StartupInfo.cb = 104;
StartupInfo.dwFlags |= 0x100u;
StartupInfo.hStdInput = 0i64;
StartupInfo.hStdError = hWritePipe;
StartupInfo.hStdOutput = hWritePipe;
hWritePipe = 0i64;
hObject = 0i64;
v15 = 0i64;
if ( CreateProcessW(
0i64,
(LPWSTR)(v3 + 261), < ==== commandline parameter is sent by attacker.
0i64,
0i64,
1,
0x8000020u,
0i64,
0i64,
&StartupInfo,
(LPPROCESS_INFORMATION)&hWritePipe) )
{
WaitForSingleObject(hWritePipe, 0xFFFFFFFF);
GetExitCodeProcess(hWritePipe, (LPDWORD)&hReadPipe);
CloseHandle(hWritePipe);
sub_13FF6E370(&Memory, hReadPipe);
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hObject);
v11[8] = 1;
*(_DWORD *)&v11[9] = (_DWORD)hReadPipe;
*(_DWORD *)&v11[18] = Size;
if ( Size )
{
v8 = operator new(Size);
*(_QWORD *)&v11[22] = v8;
v9 = &Memory;
if ( v21 >= 0x10 )
v9 = Memory;
sub_13FF700B0(v8, v9, Size);
}
if ( v21 >= 0x10 )
j_free(Memory);
}
Exploit code:
https://pastebin.com/eLG3dpYK
CVE Assigned:
CVE-2018-11479
No comments:
Post a Comment