Дизассемблирование в Python

Статьи

Введение

В данной статье поговорим про дизассемблирование байт-кода в Python.

Байт-код Python, дизассемблирование и ассемблирование

После запуска программы на Python, первым делом она компилируется в байт-код, который в последствии исполняется виртуальной машиной Python.

Байт-код — это набор инструкций, которые понимает виртуальная машина Python.

Дизассемблирование — это процесс преобразования этого байт-кода обратно в читаемый для человека формат или в форму, более близкую к исходному коду, что является обратным процессом от ассемблирования.

Ассемблирование — это процесс преобразования человекочитаемого ассемблерного кода в машинный код, который может быть выполнен процессором.

Модуль dis

Для дизассемблирования в Python есть встроенный модуль dis, позволяющий разбирать байт-код Python и выводить его в удобочитаемом формате.

Функция dis() используется для дизассемблирования байт-кода. Она позволяет просмотреть инструкции байт-кода, которые выполняются Python интерпретатором для определенной функции или метода.

Функции модуля dis

Функция dis()

Функция dis.dis() дизассемблирует объект. Это может быть строка исходного кода, функция, метод, класс или сам модуль.

Пример использования функции dis()
import dis


def my_function():
    x = 10
    y = x * 2
    return y


dis.dis(my_function)

# Вывод:
#   4           0 LOAD_CONST               1 (10)
#               2 STORE_FAST               0 (x)
# 
#   5           4 LOAD_FAST                0 (x)
#               6 LOAD_CONST               2 (2)
#               8 BINARY_MULTIPLY
#              10 STORE_FAST               1 (y)
# 
#   6          12 LOAD_FAST                1 (y)
#              14 RETURN_VALUE

Выполнение этого кода выводит дизассемблированный байт-код функции my_function(). Таким образом мы можем увидеть, как Python обрабатывает каждую инструкцию в коде.

Интерпретация дизассемблированного кода

Код из примера показывает инструкции байт-кода, которые выполняются Python’ом для выполнения функции.

  • LOAD_CONST — загружает константу на вершину стека.
  • STORE_FAST — сохраняет верхний элемент стека в локальную переменную.
  • LOAD_FAST — загружает содержимое локальной переменной на вершину стека.
  • BINARY_MULTIPLY — выполнение умножения двух элементов стека
  • RETURN_VALUE — возвращает верхний элемент стека.

Функция code_info()

Функция dis.code_info() возвращает строку с подробной информацией о коде, включая имя функции, файл, количество аргументов и другие детали.

Пример использования функции code_info()
import dis


def my_function():
    x = 10
    y = x * 2
    return y


print(dis.code_info(my_function))

# Вывод:
# Name:              my_function
# Filename:          C:\Users\lfybk\pythonProject\Lesson\main.py
# Argument count:    0
# Positional-only arguments: 0
# Kw-only arguments: 0
# Number of locals:  2
# Stack size:        2
# Flags:             OPTIMIZED, NEWLOCALS, NOFREE
# Constants:
#    0: None
#    1: 10
#    2: 2
# Variable names:
#    0: x
#    1: y

Таким образом мы смогли получить информацию о байт-коде функции my_function().

Функция show_code()

Функция dis.show_code() выводит ту же информацию, что и dis.code_info(), но непосредственно на экран, используя функцию print().

Пример использования функции show_code()
import dis


def my_function():
    x = 10
    y = x * 2
    return y


dis.show_code(my_function)

# Вывод:
# Name:              my_function
# Filename:          C:\Users\lfybk\pythonProject\Lesson\main.py
# Argument count:    0
# Positional-only arguments: 0
# Kw-only arguments: 0
# Number of locals:  2
# Stack size:        2
# Flags:             OPTIMIZED, NEWLOCALS, NOFREE
# Constants:
#    0: None
#    1: 10
#    2: 2
# Variable names:
#    0: x
#    1: y

Функция get_instructions()

Функция dis.get_instructions() возвращает генератор, который производит объекты, представляющие собой инструкции байт-кода для указанного объекта кода (функции, метода, строки кода и т.д.). Эти объекты имеют подробную информацию о каждой инструкции, включая её оператор, аргументы и смещения.

Пример использования функции get_instructions()
import dis


def my_function():
    x = 10
    y = x * 2
    return y


instructions = dis.get_instructions(my_function)

for instruction in instructions:
    print(instruction)

# Вывод:
# Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=0, starts_line=5, is_jump_target=False)
# Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='x', argrepr='x', offset=2, starts_line=None, is_jump_target=False)
# Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='x', argrepr='x', offset=4, starts_line=6, is_jump_target=False)
# Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=2, argrepr='2', offset=6, starts_line=None, is_jump_target=False)
# Instruction(opname='BINARY_MULTIPLY', opcode=20, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False)
# Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='y', argrepr='y', offset=10, starts_line=None, is_jump_target=False)
# Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='y', argrepr='y', offset=12, starts_line=7, is_jump_target=False)
# Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=14, starts_line=None, is_jump_target=False)

Применение дизассемблирования

Дизассемблирование может быть полезно в следующих случаях:

  1. Отладка и анализ кода: Дизассемблирование позволяет понять, как Python интерпретирует и выполняет код на низком уровне. Это может помочь в отладке сложных проблем или лучшем понимании внутренней работы Python.
  2. Обратная разработка: Дизассемблирование исполняемых файлов может помочь в обратной разработке и понимании, как работает программа, даже если исходный код недоступен.
  3. Безопасность и взлом: Дизассемблирование может использоваться для анализа вредоносного кода, поиска уязвимостей и разработки методов защиты.
  4. Оптимизация производительности: Анализ дизассемблированного кода может помочь в выявлении и оптимизации узких мест в производительности программы.

Заключение

В ходе статьи мы с Вами узнали, что такое дизассемблирования в Python и как с ним работать. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂

Admin
Admin
IT Start