Как я могу получить инструкции PE-файла, используя Python?
Поэтому я пытаюсь написать базовый дизассемблер для школьного проекта с использованием Python. Я использую библиотеки pydasm и capstone. Чего я не понимаю, так это как я могу получить доступ к инструкциям по сборке программы с использованием Python. Эти библиотеки позволяют мне разбирать инструкции, но я не могу понять, как получить доступ к инструкциям программы в Python. Кто-нибудь может дать мне какое-то направление?
Благодарю.
3 ответа
Вы должны быть осторожны с разделом кода, так как основание раздела кода может не содержать только код (в этом месте могут присутствовать данные импорта или только для чтения).
Лучший способ начать разборку, глядя на AddressOfEntryPoint
поле в IMAGE_OPTIONAL_HEADER
который указывает первый исполняемый байт в файле PE (за исключением того, что присутствует TLS, но это уже другая тема).
Очень хорошая библиотека для просмотра PE файлов в python - это pefile.
Вот пример, чтобы получить первые 10 байтов в точке входа в программу:
#!/usr/local/bin/python2
# -*- coding: utf8 -*-
from __future__ import print_function
import sys
import os.path
import pefile
def find_entry_point_section(pe, eop_rva):
for section in pe.sections:
if section.contains_rva(eop_rva):
return section
return None
def main(file_path):
print("Opening {}".format(file_path))
try:
pe = pefile.PE(file_path, fast_load=True)
# AddressOfEntryPoint if guaranteed to be the first byte executed.
eop = pe.OPTIONAL_HEADER.AddressOfEntryPoint
code_section = find_entry_point_section(pe, eop)
if not code_section:
return
print("[+] Code section found at offset: "
"{:#x} [size: {:#x}]".format(code_section.PointerToRawData,
code_section.SizeOfRawData))
# get first 10 bytes at entry point and dump them
code_at_oep = code_section.get_data(eop, 10)
print("[*] Code at EOP:\n{}".
format(" ".join("{:02x}".format(ord(c)) for c in code_at_oep)))
except pefile.PEFormatError as pe_err:
print("[-] error while parsing file {}:\n\t{}".format(file_path,
pe_err))
if __name__ == '__main__':
if len(sys.argv) < 2:
print("[*] {} <PE_Filename>".format(sys.argv[0]))
else:
file_path = sys.argv[1]
if os.path.isfile(file_path):
main(file_path)
else:
print("[-] {} is not a file".format(file_path))
Просто передайте имя вашего PE-файла в качестве первого аргумента.
В приведенном выше коде code_at_oep
переменная содержит первые несколько байтов точки входа. Оттуда вы можете передать эти байты двигателю Capstone.
Обратите внимание, что эти первые байты могут быть просто jmp
или же call
инструкции, так что вам придется следить за выполнением кода, чтобы правильно разобрать. Правильная разборка программы - все еще открытая проблема в информатике...
Это зависит от того, какую ОС вы используете. У вас есть еще вопросы о Linux, так что я предполагаю, что вы используете это. В Linux исполняемые файлы обычно имеют формат ELF, поэтому вам понадобится библиотека python для чтения этого или другой инструмент для извлечения части файла ELF, которую вы хотите.
Фактические инструкции хранятся в .text
раздел, так что если вы извлекаете содержимое этого раздела, это должны быть необработанные байты, которые вы хотите разобрать.
так вот мой код , который разбирает свой исполняемый файл и дает выход на языке x86 сборки я использовал pefile и дипломную библиотеку
#!/usr/bin/python
import pefile
from capstone import *
# load the target PE file
pe = pefile.PE("/file/path/code.exe")
# get the address of the program entry point from the program header
entrypoint = pe.OPTIONAL_HEADER.AddressOfEntryPoint
# compute memory address where the entry code will be loaded into memory
entrypoint_address = entrypoint+pe.OPTIONAL_HEADER.ImageBase
# get the binary code from the PE file object
binary_code = pe.get_memory_mapped_image()[entrypoint:entrypoint+100]
# initialize disassembler to disassemble 32 bit x86 binary code
disassembler = Cs(CS_ARCH_X86, CS_MODE_32)
# disassemble the code
for instruction in disassembler.disasm(binary_code, entrypoint_address):
print("%s\t%s" %(instruction.mnemonic, instruction.op_str))
не забудьте изменить и указать правильный путь к вашему exe-файлу, также вам необходимо указать, сколько инструкций вы хотите распечатать в строке номер 15 здесь.
[entrypoint:entrypoint+100]
Я указываю только 100 инструкций, но вы можете это изменить.