One day while happily working away on my liquid cooled Windows Developer Preview beast I came across this error when launching regedit:

Pretty quickly I found every program that tried to elevate to Administrative privileges had this problem. The UAC prompt to click Yes/No appeared very briefly then was rapidly replaced with this error message. Unfortunately this also applied to my beloved ProcMon.

So what to do?

First to find out to whom the dialog box belonged. Using Process Explorer (http://live.sysinternals.com/ProcExp.exe) and the feature to drag a target over a Windows to identify the process I found out the message box belonged to cmd.exe if run from Command Prompt, or Explorer.exe if launched from Explorer.

As WinDbg doesn’t require admin privilege (for limited user mode debugging of non-elevated processes) it was my debugging tool of choice. WinDbg is included in Windows SDK, which is available for free download here http://www.microsoft.com/download/en/details.aspx?id=8279

I first opened C:\windows\system32\cmd.exe using File –> Open Executable

I wanted to ensure any child processes got debugged as well so ran command

.childdbg 1

I then hit g to make the debugger go. Each time a new process starts you will see message like

ntdll!RtlUserThreadStart:

000007fb`a5323c64 4883ec48 sub rsp,48h

You will need to hit g again to continue further. I then launched regedit from my debugged cmd.exe. Now there are a few potential types of message boxes in Windows, so to make it easy to find out which one was being used, when I got the error message dialog box I hit ‘Break’ on the debugger and typed

!analyse –v –hang

In the stack trace I found the function that generated the message box, so I set a breakpoint for it:

bp SHELL32!SHSysErrorMessageBox

(don’t worry about could not resolve error message here)

and typed

.restart on my process

Which showed me the following:

<modules loading etc here>

Breakpoint 0 hit

SHELL32!SHSysErrorMessageBox:

000007fb`a342fb60 fff3 push rbx

0:000> kv <- stack trace, find what functions got called before message box

Child-SP RetAddr : Args to Child : Call Site

00000056`e904dfe8 000007fb`a349fe8d : 00000000`0000104c 00000000`0000007f 00000056`e92b74c0 00000000`000000ff : SHELL32!SHSysErrorMessageBox

00000056`e904dff0 000007fb`a33d216e : 00000056`e927fea0 00000000`00230e74 00000000`000000ff 00000000`00000000 : SHELL32!_ExecErrorMsgBox+0x23d

00000056`e904f0b0 000007fb`a32ee389 : 00000056`e904f1f0 00000056`e904f1f0 00000000`00000000 00000000`00000000 : SHELL32!CShellExecute::_DoExecute+0x33f

00000056`e904f130 000007fb`a32ee29d : 00000056`e927fea0 00000000`00008140 00000000`00000000 00000056`e904f1f0 : SHELL32!CShellExecute::ExecuteNormal+0x95

00000056`e904f160 000007fb`a32ee214 : 00000056`e904f1f0 000007fb`a37743e0 00000056`e904f1f0 00000056`e904f080 : SHELL32!ShellExecuteNormal+0x4d

00000056`e904f190 000007fb`99322faa : 00000000`00000000 00000000`00000000 00000000`00000000 00000056`e904f080 : SHELL32!ShellExecuteExW+0x54

00000056`e904f1c0 000007f6`ca0e5429 : 00000056`e9277b30 00000056`e927a300 00000056`e92755f0 000007f6`ca12d360 : fsutilext!ShellExecuteWorker+0x7e

00000056`e904f270 000007f6`ca0e5a3b : 00000056`e927bd50 00000000`00000000 00000056`e9261820 00000056`e92755f0 : cmd!ExecPgm+0x5b0

00000056`e904f530 000007f6`ca0e8158 : 00000000`00000000 00000056`e9261820 00000000`00000000 00000056`e9261820 : cmd!ECWork+0xd7

00000056`e904f790 000007f6`ca0e1306 : 00000000`0000de5c 00000056`e9261820 00000000`00000000 000007f6`ca0e16a1 : cmd!FindFixAndRun+0x54e

00000056`e904fc30 000007f6`ca10beb0 : 00000056`e9261820 000007f6`ca113890 00000056`e9261820 00000000`000000ff : cmd!Dispatch+0xab

00000056`e904fce0 000007f6`ca0f3a68 : 00000000`00000001 00000000`00000000 00000000`00000000 00000000`00000000 : cmd!_chkstk+0x50c6

00000056`e904fd40 000007fb`a2f23cdc : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : cmd!Handler+0x291

00000056`e904fd80 000007fb`a5323c85 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x18

00000056`e904fdb0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d

0:000> !gle <- get last error

TRIAGER: Could not open triage file : C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\triage\oca.ini, error 2

TRIAGER: Could not open triage file : C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\winxp\triage.ini, error 2

TRIAGER: Could not open triage file : C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\triage\user.ini, error 2

LastErrorValue: (Win32) 0x7f (127) – The specified procedure could not be found.

LastStatusValue: (NTSTATUS) 0xc0000139 – {Entry Point Not Found} The procedure entry point %hs could not be located in the dynamic link library %hs.

While this was all well an interesting there was some important information missing: Primarily nothing from consent.exe. Unfortunately no way I was going to be able to debug that as standard user because I was not admin…D’oh!

So I restarted the PC and pressed F8 to enter safe mode. I then logged in with a local administrator account and as safe mode is free of UAC prompts could happily set User Account Control Settings to Never Notify

Warning! Using this setting is not recommended and will increase risk of nasty software doing bad things to your PC.

Restarting back into regular Windows I could now launch programs as admin. I launched a command prompt as Admin and reset UAC back to the previous setting.

I then went back to my comfort zone of ProcMon (http://live.sysinternals.com/ProcMon.exe)

I set a filter to include the following processes:

cmd.exe

consent.exe

regedit.exe

I also set a filter on Operation is Load Image as I wanted to look for 3rd party code being loaded.

Sure enough we find some perfect suspects. 3rd party codecs were being loaded. These codecs had been installed a few days before from an open source program Audacity and the separate download Lame MP3 Encoder Pack

I then brought out the tool that must not be left at home. Ever. AutoRuns (http://live.sysinternals.com/AutoRuns.exe) AutoRuns can disable/enable pretty much any possible location for code to startup within Windows – from drivers, services, codecs, etc, it has it all. You can also analyse offline systems such as a mounted WIM, or an unbootable partition from within Windows PE.

I disabled all codecs at first, then enabled one-by-one to find the culprit. I found two caused the issue:

msacm.avis

msacm.lameacm

Disabling these and UAC was back in all its glory.



But why is Windows loading codecs for the UAC consent dialog?

The codecs are loaded because consent.exe plays a sound effect, which required a codec to decode the audio file.

In fact I found I can also re-enable all my codecs and disable Windows Sounds, and UAC prompt will still work. Peace at last.