Search code examples
pythonvirtualalloc

VirtualAlloc and Python - Access Violation


Very simple python script is giving me an access violation and I just can't figure out why.

import ctypes

def Test():
     data = bytearray( "\xDE\xAD\xBE\xEF\x0B\xAD\xC0\xDE", 'utf-16' )
     dataLen = len( data )

     try :
        ptr = ctypes.windll.kernel32.VirtualAlloc( ctypes.c_int( 0 ),
                                                   ctypes.c_int( dataLen ),
                                                   ctypes.c_int( 0x3000 ),
                                                   ctypes.c_int( 0x40 ) )

        buf = ( ctypes.c_char * dataLen ).from_buffer( data )

        ctypes.windll.kernel32.RtlMoveMemory( ctypes.c_int( ptr ),
                                              buf,
                                              ctypes.c_int( dataLen ) )
     except Exception as e :
        print( e )
        exit(-1)

Error:

Traceback (most recent call last):
  File "c:\vs17\...\ptvsd_launcher.py", line 119, in <module>
    vspd.debug(filename, port_num, debug_id, debug_options, run_as)
  File "c:\vs17\...\ptvsd\debugger.py", line 37, in debug
    run(address, filename, *args, **kwargs)
  File "c:\vs17\...\ptvsd\_local.py", line 64, in run_file
    run(argv, addr, **kwargs)
  File "c:\vs17\...\ptvsd\_local.py", line 125, in _run
    _pydevd.main()
  File "c:\vs17\..\ptvsd\_vendored\pydevd\pydevd.py", line 1752, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "c:\vs17\...\ptvsd\_vendored\pydevd\pydevd.py", line 1099, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "c:\vs17\...\ptvsd\_vendored\pydevd\pydevd.py", line 1106, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "c:\vs17\...\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "D:\Dev\Python\VirtualAlloc_Testing\VirtualAlloc_Testing.py", line 31, in <module>
    main()
  File "D:\Dev\Python\VirtualAlloc_Testing\VirtualAlloc_Testing.py", line 29, in main
    Test()
  File "D:\Dev\Python\VirtualAlloc_Testing\VirtualAlloc_Testing.py", line 19, in Test
    ctypes.c_int( dataLen ) )
OSError: exception: access violation writing 0x00000000212F0000

Solution

  • Hit the same issue. For me the reason was wrong VirtualAlloc restype size, defined as 32-bit value.

    Indeed, ctypes functions are not prototyped and return C default type: c_int. On Windows, c_int is an alias for c_long which is a signed 32-bit integer. So when a system allocates a memory block above x32 limit the address returned by VirtualAlloc is cut.

    In your case VirtualAlloc could return 0000001A212F0000 for example, but then only lower part 0x212F0000 was used as value for ptr.

    Add the next line before use:

    ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
    

    The same stuff is about RtlCopyMemory.argtypes:

    ctypes.windll.kernel32.RtlCopyMemory.argtypes = ( ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t ) 
    

    works good