[issue24201] _winreg PyHKEY Type Confusion
eryksun
report at bugs.python.org
Fri May 15 16:45:17 CEST 2015
eryksun added the comment:
> wherein pointers can be passed directly in place of PyHKEY
> instances e.g. _winreg.QueryValue(0x41414141, "")
If a debugger is attached you see the first-chance exception for the access violation. Normally the registry function simply returns ERROR_INVALID_HANDLE (6), which gets raised as an OSError in Python.
The call took the RPC path because the low bit (1) marks a remote handle, which is actually a pointer to a data structure. RPCRT4!NDRCContextBinding looks for a signature (0xFEDCBA98) to validate this structure.
In this case the attempt raised an access violation, which gets handled by raising another exception with the exception code set to ERROR_INVALID_HANDLE. The same exception gets raised if it can't validate the handle. Subsequently this exception is handled by calling RPCRT4!NdrClientMapCommFault to map the code to a return value.
For example (x64 ISA):
>>> _winreg.QueryInfoKey(0x41414141)
(a2c.828): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
RPCRT4!NDRCContextBinding+0x4:
000007fe`fefca6e4 81790898badcfe cmp dword ptr [rcx+8],0FEDCBA98h ds:00000000`41414148=????????
0:000> gN
(a2c.828): Unknown exception - code 00000006 (first chance)
Breakpoint 0 hit
RPCRT4!NdrClientMapCommFault:
000007fe`ff05f010 fff3 push rbx
0:000> kc 8
Call Site
RPCRT4!NdrClientMapCommFault
RPCRT4!NdrpClientCall3
RPCRT4!NdrClientCall3
ADVAPI32!SafeBaseRegQueryInfoKey
ADVAPI32!RemoteRegQueryInfoKeyWrapper
kernel32!TlsGetValue
ADVAPI32!RegQueryInfoKeyAStub
python27!PyQueryInfoKey
The exception code is passed in register r8 and gets assigned to the address in r9:
0:000> r r8, r9
r8=0000000000000006 r9=000000000021f1d8
0:000> dd 21f1d8 l1
00000000`0021f1d8 00000000
0:000> pt
RPCRT4!NdrClientMapCommFault+0x80:
000007fe`ff05f080 c3 ret
0:000> dd 21f1d8 l1
00000000`0021f1d8 00000006
This return value gets passed back up the call stack:
0:000> gu; pt; r rax
rax=0000000000000006
0:000> gu; pt; r rax
rax=0000000000000006
0:000> gu; pt; r rax
rax=0000000000000006
0:000> gu; pt; r rax
rax=0000000000000006
0:000> gu; pt; r rax
rax=0000000000000006
0:000> r
rax=0000000000000006 rbx=0000000000e1cda0 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000000 rdi=000000001e1027b0
rip=00000000779ba204 rsp=000000000021f9d8 rbp=0000000000eb61c8
r8=000000000021f1d8 r9=0000000000000000 r10=000000000021f1d8
r11=000000000021f8b0 r12=0000000000e1cda0 r13=0000000000807bb0
r14=000000001e2b3210 r15=0000000000eb7060
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
kernel32!RegQueryInfoKeyA+0x364:
00000000`779ba204 c3 ret
Until finally getting raised as a Python exception:
0:000> g
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
WindowsError: [Error 6] The handle is invalid
The odds are extremely low that someone will pass in an integer address that's flagged as a remote handle (ends in 1) and is a valid, mapped address that contains the RPC handle signature. Even then, it won't reference an actual proxy handle for a remote registry, so it'll just fail farther along the chain.
I'm sure if a feature exists that someone, somewhere depends on it, so I don't see a reason to change this unless there's a real problem here. Is there a specific technical or security problem that you see here?
----------
nosy: +eryksun
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue24201>
_______________________________________
More information about the Python-bugs-list
mailing list