繁体   English   中英

Changing Python integer in memory using ctypes module and GDB session

[英]Changing Python integer in memory using ctypes module and GDB session

我的问题是基于这个reddit 帖子。 此处的示例显示了如何使用ctypes模块中的cast function 更改 memory 中的 integer :

>>> import ctypes
>>> ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3] = 100
>>> 29
100

我对这里的低级内部感兴趣,我已经在 GDB session 中通过在CPython中的强制cast function 上设置断点来检查这个:

(gdb) break cast
Function "cast" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (cast) pending.
(gdb) run test.py 
Starting program: /root/.pyenv/versions/3.8.0-debug/bin/python test.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x7ffff00e7b40

Breakpoint 1, cast (ptr=0x9e6e40 <small_ints+1088>, src=10382912, ctype=<_ctypes.PyCPointerType at remote 0xa812a0>) at /root/.pyenv/sources/3.8.0-debug/Python-3.8.0/Modules/_ctypes/_ctypes.c:5540
5540        if (0 == cast_check_pointertype(ctype))
(gdb) p *(PyLongObject *) ptr
$38 = {
  ob_base = {
    ob_base = {
      ob_refcnt = 12, 
      ob_type = 0x9b8060 <PyLong_Type>
    }, 
    ob_size = 1
  }, 
  ob_digit = {100}
}
(gdb) p *((long *) ptr + 3)
$39 = 100
(gdb) p ((long *) ptr + 3)
$40 = (long *) 0x9e6e58 <small_ints+1112>
(gdb) p *((char *) ptr + 3 * 8)
$41 = 100 'd'
(gdb) p ((char *) ptr + 3 * 8)
$42 = 0x9e6e58 <small_ints+1112> "d"
(gdb) set *((long *) ptr + 3) = 29
(gdb) p *((long *) ptr + 3)
$46 = 29
(gdb) p *((char *) ptr + 3 * 8)
$47 = 29 '\035'

I would like to know if it's possible to get the memory address using Python in the GDB session because I couldn't access the returned addresses:

(gdb) python print("{:#x}".format(ctypes.addressof(ctypes.c_int(29))))
0x7f1053c947f0
(gdb) python print("{:#x}".format(id(29)))
0x22699d8
(gdb) p *0x7f1053c947f0
Cannot access memory at address 0x7f1053c947f0
(gdb) p *0x22699d8
Cannot access memory at address 0x22699d8

索引与 Python REPL 的竞争也不同,我想这与字节序有关?

(gdb) python print(ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3])
9
(gdb) python print (ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[2])
29

问题:

  1. Why memory addresses from Python in GDB session are not accessible, values are not in the the process memory range ( info proc mappings )?
  2. 为什么索引与 Python REPL 相比不同?
  3. (奖金问题)我希望CPython cast function 中的src参数包含 object 的地址,但它似乎是ptr而不是memcpy result->b_ptr指向&ptr不同的值? 这是实际的演员阵容吗?
  1. 您的 Python 进程不是真正的 python 进程,而是 GDB 正在为您运行 ZA7F5F35426B927417FC9231B5683 REPL。 把它想象成 GDB 内部的另一个线程。 当然,这是一个简化,您应该查看文档
  2. 我无法重现这种行为:
     (gdb) python >import ctypes >print(ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3]) >end 29
    我想不出这种行为会发生的任何原因(至少是字节序,在整个系统中都是一样的*)
  3. src参数似乎被用作原点类型,而不是原点 object。 作为参考,请参阅ctypes.hctypes/__init__.py (_SimpleCData 只是 CDataObject 与一些帮助,如索引和 repr)。 是的,在这种情况下,memcpy 是实际的转换,尽管如果您在两种数据类型之间进行转换,则需要事先进行额外的工作。

* 除了 ARM,您可以通过指令更改字节顺序

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM