Is it possible to set a cond breakpoint which checks the value of eax every time any ret occurs?

I’m trying to debug a strange issue where a 3rd party piece of software fails to connect to a named pipe when our software is installed (our software can create security tokens). The software gets STATUS_ACCESS_DENIED when trying to attach to the pipe. The token we’ve provided is an admin token which looks almost identical to a normal admin token with the addition of one deny ACE. The DACLs on the named pipe appear to show that administrators can connect to it (and I have done so with our token and a test program despite the real software failing in NtCreateFile).

I initially thought that this STATUS_ACCESS_DENIED must be coming from SeAccessCheck or one of its new undocumented brothers like SeAccessCheckWithHint. However, I’ve investigated all the access checks which occur on the thread and found they all return TRUE despite NtCreateFile returning that status.

I’m now puzzled because I don’t know any other functions that use STATUS_ACCESS_DENIED so I can’t work out where it’s coming from. I wondered if it was possible to simply trace every function call and break if any function returns that NTSTATUS. Is that possible in WinDBG?

Well, sort of. You can do “step out” to break when the current function returns. I guess you can start doing that when you get into the last access check.

@Tim_Roberts Right, that’s basically what I was doing to check the results of the access checks. Stepping out and then checking eax. I was just thinking that in theory, I could check the return code of all the functions in that particular code path automatically to work out the origin of the failure (assuming it actually gets returned rather than passed out as an argument). I guess it’s not supported directly, but maybe I can come up with something in WinDBG/javascript or something.

It looks like you could do your investigation from user mode, in which case windbg has this functionality built in with the wt command’s -oR option.

-oR (User mode only) Displays the return register values of the called function, in the appropriate type for each return value.

0:007> bp USER32!GetWindowInfo
0:007> g
Breakpoint 0 hit
USER32!GetWindowInfo:
00007fff`831205c0 48895c2418      mov     qword ptr [rsp+18h],rbx ss:0000008a`d8e7ee60=0000008ad8e7f320
0:000> wt -l 3 -oR
Tracing USER32!GetWindowInfo to return address 00007fff`7debcdde
  172     0 [  0] USER32!GetWindowInfo
   26     0 [  1]   USER32!GetSystemMetricsForDpi
   11     0 [  2]     ntdll!LdrpDispatchUserCallTarget
   13     0 [  2]     uxtheme!ThemeGetSystemMetricsForDpi
   11     0 [  3]       ntdll!LdrpDispatchUserCallTarget
   22     0 [  3]       USER32!RealGetSystemMetricsForDpi rax = 6
   17    33 [  2]     uxtheme!ThemeGetSystemMetricsForDpi = int 0n6
   39    61 [  1]   USER32!GetSystemMetricsForDpi rax = 6
  203   100 [  0] USER32!GetWindowInfo
    6     0 [  1]   USER32!_security_check_cookie rax = 1
  213   106 [  0] USER32!GetWindowInfo

(P.S. This discussion better fits the https://community.osr.com/categories/windbg forum.)

Is the open making it to Npfs!NpFsdCreate?