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