如何从内存地址重构Python函数?
编辑(响应四个选项): 对不起,对于这个糟糕的问题,请考虑以下情况:如何从内存地址重构Python函数?,python,Python,编辑(响应四个选项): 对不起,对于这个糟糕的问题,请考虑以下情况: >>> orig_spam_function = get_orig_func_from_memory_address("0x7feccc97fb78") 但是想象一下,当您分配时,defaultdict没有default\u factory属性 >>> from collections import defaultdict >>> d = defaultdict(spam
>>> orig_spam_function = get_orig_func_from_memory_address("0x7feccc97fb78")
但是想象一下,当您分配时,defaultdict
没有default\u factory
属性
>>> from collections import defaultdict
>>> d = defaultdict(spam)
>>> d
defaultdict(<function spam at 0x7f597572c270>, {})
>>> d.default_factory
<function spam at 0x7f597572c270>
对spam
函数的最后一次引用消失,引用计数变为0,稍后将被垃圾收集。所以,没有办法,我们可以把它拿回来。我们可以用这个程序检查一下
spam = "spam"
我的机器上的输出
def spam():
print("top secret function")
import sys
print id(spam), sys.getrefcount(spam)
spam = "spam"
print id(spam), sys.getrefcount(spam)
spam
的实际地址与我们在赋值语句后看到的地址不同。所以,它现在指向一个不同的对象。但是,最初,引用计数为1(getrefcount
将始终为)。当我们重新分配垃圾邮件时,现在实际上没有人指向该函数。因此,它将准备好进行垃圾收集。从取证的角度来看,如果您在赋值操作后直接冻结执行,然后检查内存中的位置,您可能会这样做(obv知道如何解析python内存结构)如果你小心的话,你可能会爬回一些操作码指令,从这些指令中你可能会手工重写函数或类似的东西。@thefourtheye提出了一个关于函数被垃圾收集的好观点
但是,如果函数没有被垃圾收集,您可以在所有现有对象中查找它:
140068817052928 2
140068817075440 12
def spam():
通过
spam2=垃圾邮件#保留一个参考
打印垃圾邮件
=>
导入gc
[如果id(obj)=0x56d69b0,则gc.get_objects()中obj的obj为obj]
=> []
这不是一种有效的方法(扫描内存中的所有对象),但这是一种方法。理论上,您可以尝试破解一些本机代码来恢复它。但是,不能保证在执行本机代码时,该地址仍然具有函数的含义。您好,谢谢您的快速回复。如果函数还没有被垃圾收集呢?我更新了我的问题。@vajrasky:CPython使用引用计数;0时,它消失了。没有单独的GC运行来获取它,GC只起到破坏循环引用的作用。如果我们保留一个引用,我们总是可以将它取回:)通过重新分配一些东西来尝试同样的方法else@thefourtheye不难举出事实并非如此的例子。例如,参考资料由某人保存(例如,另一个模块),但不一定很容易确定此人是谁
140068817052928 2
140068817075440 12
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>]