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