推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
penguinWWY
V2EX  ›  Python

发一个看起来没啥用的字节码编辑库

  •  
  •   penguinWWY · Aug 1, 2022 · 2932 views
    This topic created in 1524 days ago, the information mentioned may be changed or developed.

    先贴一下 README


    Pyasmer 是一个 Python 字节码编辑库。它可以用来修改现有的二进制代码(例如, func.code)。

    Pyasmer 可以帮助开发者在 python 代码中执行一些动态地在已有代码中插桩、代理、指令生成,

    使用它需要你具备一定的 Python 字节码和 CPython 虚拟机执行机制,你可以从官方文档获取这些知识: https://docs.python.org/3/library/dis.html。Pyasmer 也会提供一些易于使用的接口,降低使用难度。

    举个例子:

    import sys
    
    from pyasmer.asm_instruction import asm_global_var, asm_fast_var
    from pyasmer.code_writer import CodeWriter
    
    if __name__ == '__main__':
        _frozen_importlib = sys.modules['_frozen_importlib']
        # _find_and_load_unlocked 函数会在 import 模块的时候被调用
        _find_and_load_unlocked = getattr(_frozen_importlib, '_find_and_load_unlocked')
        cw = CodeWriter(_find_and_load_unlocked.__code__)()
        # 在_find_and_load_unlocked 函数开头添加一个 print ,将要被 import 的模块名称打印出来
        #
        # 更新插入位置到函数开头(第 0 条指令)
        cw.update_position(offset=0)
        # None: 忽略返回值
        # asm_global_var('print'): 调用的函数为 print
        # asm_fast_var('name'): 将局部变量`name`传给 print
        cw.call_function(None, asm_global_var('print'), asm_fast_var('name'))
        cw.gen_code()
        # 执行 import 命令
        import ast
    

    输出显示有两个模块在 import 命令过程中被引用。

    output:
        ast
        _ast
    

    目前功能还比较简单,支持插入函数调用、获取属性等功能。

    此外支持通过表达式匹配定位要修改的位置,比如:

    @asm_viewer
    def binary_ops(a, b):
        return [a + b, a - b, a * b, a / b, a + b]
    
    
    def test_match_binary_op():
        cv: CodeViewer = binary_ops.viewer
        # 匹配到两处 a + b 的位置
        binary_add = [x for x in cv.find_snippet_by_expression("a + b", local_vars=["a", "b"])]
        assert len(binary_add) == 2
        # 第 0-2 条指令和第 12-14 条指令
        # LOAD_FAST a
        # LOAD_FAST b
        # BINARY_ADD
        assert binary_add == [(0, 2), (12, 14)]
    

    总之,想要更多的功能欢迎来手搓,使用场景请各自脑补,over~~~

    4 replies  •  2022-08-01 17:53:04 +08:00
    penguinWWY
        1
    penguinWWY  
    OP
       Aug 1, 2022
    penguinWWY
        2
    penguinWWY  
    OP
       Aug 1, 2022
    yyzq007
        3
    yyzq007  
       Aug 1, 2022
    支持支持
    joApioVVx4M4X6Rf
        4
    joApioVVx4M4X6Rf  
       Aug 1, 2022
    大佬!
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   767 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 19:41 · PVG 03:41 · LAX 12:41 · JFK 15:41
    ♥ Do have faith in what you're doing.