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 c0000005 (!!! second chance !!!)
eax=60dad396 ebx=00000000 ecx=00000000 edx=00000000 esi=000000a0 edi=000000a0
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:00000044=??????
??
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 00000000 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  fffffffe 8fe8008b c20000a2 90900004
75469b13  90909090 fffffe90 000000ff ffffd400
75469b23  000000ff fffffe00 49d901ff 49d92575
75469b33  06f76875 b2e80000 8b000161 47c7e845
75469b43  0000003c 50478900 00a661e9 09be0f00
75469b53  00a649e9 06f76800 8ee80000 68000161
75469b63  000006e6 016184e8 90909000 499e5190
0:000> !address 0x75469AF3


Usage:                  Image
Base Address:           75451000
End Address:            754fa000
Region Size:            000a9000
State:                  00001000        MEM_COMMIT
Protect:                00000020        PAGE_EXECUTE_READ
Type:                   01000000        MEM_IMAGE
Allocation Base:        75450000
Allocation Protect:     00000080        PAGE_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 0x75450000

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.

----------

_______________________________________
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

Reply via email to