Python中的邪恶ctypes黑客技巧

3 投票
1 回答
986 浏览
提问于 2025-04-18 08:43

我想先说,这个问题纯粹是出于好奇,我绝对不打算在任何严肃的项目中使用这么邪恶的东西。(没错,就是那种问题)

我一直在尝试了解CPython的内部工作原理,经过我的努力,我发现应该可以操控小整数的实际值,比如说1 + 2可以算出其他的结果,而不是3。我对这种低级的黑客技术并不是很在行,迄今为止我只得到了一些崩溃的结果。这是我目前的尝试:

import ctypes
ctypes.c_int8.from_address(id(1) + 8).value = 2

我原以为这样就能解决问题,但结果是任何试图计算1的语句都会崩溃。虽然这个结果让我觉得有点好笑,但这并不是我想要的。我是不是漏掉了什么?是不是那行代码里的c_int8和+ 8只在某些平台上有效?如果我知道该查找什么,我很乐意去查一下,不过我想答案可能藏在CPython的源代码里。

1 个回答

3

在一个32位的平台上,8 是“正确的”,因为 ob_refcntob_type 每个占用4个字节;而在64位的平台上,这个情况就会不同。简单来说,你是在尝试越过 PyObject_HEAD 去访问整数对象的其他部分,所以你可以在编译器或调试器中检查一下 PyObject 的大小。

显然,在Python 3中情况会有所不同,因为只有 long 类型,所以即使是小整数也是可变长度的;在这种情况下,你需要使用 PyObject_VAR_HEAD(和 PyVarObject),而不是 PyObject_HEAD

一个很好的起点是查看 object.h 里的文档,你也可以在C API参考手册中找到,地址是 https://docs.python.org/2/c-api/structures.html,然后再看看 intobject.h,或者对于Python 3,可以查看 longintrepr.h


注意:改变 1 的值仍然会导致程序崩溃,但原因不同。不过,改变一个较大的小整数,比如 10,应该是安全的。

撰写回答