Oz1*_*123 5 python ctypes ipython
我试图从内存中删除密码字符串,就像在这里建议的那样.
我写了那个小片段:
import ctypes, sys
def zerome(string):
location = id(string) + 20
size = sys.getsizeof(string) - 20
#memset = ctypes.cdll.msvcrt.memset
# For Linux, use the following. Change the 6 to whatever it is on your computer.
print ctypes.string_at(location, size)
memset = ctypes.CDLL("libc.so.6").memset
memset(location, 0, size)
print "Clearing 0x%08x size %i bytes" % (location, size)
print ctypes.string_at(location, size)
a = "asdasd"
zerome(a)
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这段代码可以和IPython一起使用,
[7] oz123@yenitiny:~ $ ipython a.py
Clearing 0x02275b84 size 23 bytes
Run Code Online (Sandbox Code Playgroud)
但崩溃与Python:
[8] oz123@yenitiny:~ $ python a.py
Segmentation fault
[9] oz123@yenitiny:~ $
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?
我使用Python 2.7.3在Debian Wheezy上测试过.
该代码适用于使用Python 2.6.6的CentOS 6.2.代码在Debian上用Python 2.6.8崩溃了.我试过想为什么它在CentOS上运行,而不是在Debian上运行.唯一不同的原因是,我的Debian是multiarch,CentOS在我的旧笔记本电脑上使用i686 CPU运行.
因此,我重新启动了我的CentOS latop并加载了Debian Wheezy.该代码适用于Debian Wheezy,它不是多拱的.因此,我怀疑我在Debian上的配置有些问题......
ctypes已经有了一个memset函数,所以你不必为libc/msvcrt函数创建一个函数指针.此外,20个字节用于常见的32位平台.在64位系统上,它可能是36个字节.这是一个布局PyStringObject:
typedef struct {
Py_ssize_t ob_refcnt; // 4|8 bytes
struct _typeobject *ob_type; // 4|8 bytes
Py_ssize_t ob_size; // 4|8 bytes
long ob_shash; // 4|8 bytes (4 on 64-bit Windows)
int ob_sstate; // 4 bytes
char ob_sval[1];
} PyStringObject;
Run Code Online (Sandbox Code Playgroud)
因此,在32位系统上可能是5*4 = 20个字节,在64位Linux上可能是8*4 + 4 = 36个字节,或者在64位Windows上是8*3 + 4*2 = 32个字节.由于未使用垃圾收集头跟踪字符串,因此您可以使用sys.getsizeof.通常,如果您不希望包含GC头大小(在内存中它实际上是在您获得的对象的基址之前id),那么使用对象的__sizeof__方法.至少这是我经验中的一般规律.
你想要的是简单地从对象大小中减去缓冲区大小.CPython中的字符串以空值终止,因此只需在其长度上加1即可获得缓冲区大小.例如:
>>> a = 'abcdef'
>>> bufsize = len(a) + 1
>>> offset = sys.getsizeof(a) - bufsize
>>> ctypes.memset(id(a) + offset, 0, bufsize)
3074822964L
>>> a
'\x00\x00\x00\x00\x00\x00'
Run Code Online (Sandbox Code Playgroud)
编辑
更好的选择是定义PyStringObject结构.这样便于检查ob_sstate.如果它大于0,那意味着字符串被实现,而理智的事情是引发异常.单字符字符串以及仅由ASCII字母和下划线组成的代码对象中的字符串常量,以及解释器内部用于名称(变量名称,属性)的字符串.
from ctypes import *
class PyStringObject(Structure):
_fields_ = [
('ob_refcnt', c_ssize_t),
('ob_type', py_object),
('ob_size', c_ssize_t),
('ob_shash', c_long),
('ob_sstate', c_int),
# ob_sval varies in size
# zero with memset is simpler
]
def zerostr(s):
"""zero a non-interned string"""
if not isinstance(s, str):
raise TypeError(
"expected str object, not %s" % type(s).__name__)
s_obj = PyStringObject.from_address(id(s))
if s_obj.ob_sstate > 0:
raise RuntimeError("cannot zero interned string")
s_obj.ob_shash = -1 # not hashed yet
offset = sizeof(PyStringObject)
memset(id(s) + offset, 0, len(s))
Run Code Online (Sandbox Code Playgroud)
例如:
>>> s = 'abcd' # interned by code object
>>> zerostr(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 10, in zerostr
RuntimeError: cannot zero interned string
>>> s = raw_input() # not interned
abcd
>>> zerostr(s)
>>> s
'\x00\x00\x00\x00'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2762 次 |
| 最近记录: |