如何从内存地址重建Python函数?

时间:2013-11-27 10:19:43

标签: python

>> def spam():
...   print("top secret function")
... 
>>> print(spam)
<function spam at 0x7feccc97fb78>
>>> spam = "spam"

所以我失去了对spam功能的引用。我可以从该内存地址取回它:0x7feccc97fb78?

>>> orig_spam_function = get_orig_func_from_memory_address("0x7feccc97fb78")

修改回应thefourtheye ):

对于这个糟糕的问题,请考虑一下这个案例:

>>> from collections import defaultdict
>>> d = defaultdict(spam)
>>> d
defaultdict(<function spam at 0x7f597572c270>, {})

因此该函数尚未被收集。我可以恢复吗?当然,在这种情况下,您可以使用default_factory属性。

>>> d.default_factory
<function spam at 0x7f597572c270>

但请设想defaultdict没有default_factory属性。

3 个答案:

答案 0 :(得分:3)

分配时

spam = "spam"

spam函数的最后一次引用消失了,引用计数变为0,稍后将对其进行垃圾回收。所以,没有办法,我们可以把它拿回来。我们可以通过这个程序来检查

def spam():
    print("top secret function")
import sys
print id(spam), sys.getrefcount(spam)
spam = "spam"
print id(spam), sys.getrefcount(spam)

我机器上的输出

140068817052928 2
140068817075440 12

spam的实际地址与我们在赋值语句后看到的地址不同。所以,它现在指向一个不同的对象。但是,最初,引用计数为1(getrefcount始终为one higher than the actual count)。当我们重新分配spam时,现在没有人真正指向该功能。因此,它将为垃圾收集做好准备。

答案 1 :(得分:3)

@thefourtheye提出了关于垃圾收集功能的一个好点。

但是如果该函数没有被垃圾收集,你可以在所有现有对象中查找它:

def spam():
    pass

spam2 = spam  # keep a reference
print spam
=> <function spam at 0x56d69b0>

import gc
[ obj for obj in gc.get_objects() if id(obj) == 0x56d69b0 ]
=> [<function __main__.spam>]

这不是一种有效的方法(扫描内存中的所有对象),但它是 a 方式。

答案 2 :(得分:0)

从取证的角度来看,你可能会在分配操作后直接冻结执行,然后在内存中检查该位置,(如果你知道如何解析python内存结构)如果你小心你可能能够爬上你的方法回到一些操作代码指令,从那些你可能可以手工重写函数或类似的东西。