Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从内存地址重构Python函数?_Python - Fatal编程技术网

如何从内存地址重构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>]