GAS ассемблер: записать в секцию опкоды, затем выполнить их? Есть Linux и стандартный GNU ассемблер. Можно ли взять какую нибудь из секций, заполнить ее опкодами, а затем прыгнуть в нее для выполнения? Я умею только выделять память системным вызовом mmap, туда заполнять и потом это выполнять. Можно ли это делать без системных вызовов как то. Например, как либо писать в секцию .text или как то поставить разрешение для секции .data, что бы можно было ее выполнять.
В стандартной модели работы с исполняемыми файлами под Linux, секции кода (.text) и данных (.data) имеют разные атрибуты доступа. Секция .text обычно настроена как доступная только для чтения и исполняемая, а секция .data - как доступная для чтения и записи, но не исполняемая. Это сделано для обеспечения безопасности и защиты от выполнения неисполняемого кода.
К сожалению, вы не можете напрямую модифицировать содержание секций .text или изменить атрибуты секций .data без изменения самой структуры исполняемого файла и, соответственно, без низкоуровневых манипуляций с памятью. Системный вызов mmap для выделения исполняемой памяти является наиболее распространенным способом работы с исполняемым кодом в модулях или приложениях.
Тем не менее, если вы хотите, чтобы ваш код выполнялся без использования mmap, то можете рассмотреть возможность использования других подходов, например:
Использование mprotect: Вы можете выделить память с помощью malloc или другого метода и затем сделать эту память исполняемой с помощью системного вызова mprotect. Это позволяет вам писать в память, а затем изменять атрибуты памяти.
Использование .text в качестве временного хранилища: Хотя модификация секции .text практически невозможна без специализированного подхода (например, создание загрузчика), вы можете использовать .rodata или другие секции, чтобы создать данные, которые можно выполнить, но это может сталкиваться с проблемами безопасности.
Пример использования mprotect для изменения атрибутов памяти:
.section .data code: .byte 0xB8, 0x01, 0x00, 0x00, 0x00 # mov eax, 1 .byte 0xC3 # ret .section .text .global _start _start: # Выделяем память для кода mov $0x1000, %eax # размер памяти в 4096 байт xor %ebx, %ebx # ftruncate(0) == 0 syscall # Копируем код в выделенную память mov $code, %esi # указатель на код mov 0x1000,mov0x1000, %edi # адрес выделенной памяти mov 0x1000,mov0x40, %ecx # количество байт (64) rep movsb # Делаем память исполняемой mov 0x1000,mov0x1000, %ebx # адрес выделенной памяти mov 0x1000,mov7, %ecx # PROT_READ | PROT_WRITE | PROT_EXEC mov $0x1000, %edx # размер памяти syscall # Переходим к выполнению кода jmp *%edi # прыгаем в исполняемый код
Обратите внимание, что нужно правильно настроить секции, чтобы избежать аппаратных и программных исключений. Эксперименты с правами доступа тренеров могут привести к непредсказуемому поведению программы. Лучше всего рассматривать такие подходы в контексте изучения и понимания работы системного программирования, но не в конечных производственных системах.
В стандартной модели работы с исполняемыми файлами под Linux, секции кода (.text) и данных (.data) имеют разные атрибуты доступа. Секция .text обычно настроена как доступная только для чтения и исполняемая, а секция .data - как доступная для чтения и записи, но не исполняемая. Это сделано для обеспечения безопасности и защиты от выполнения неисполняемого кода.
К сожалению, вы не можете напрямую модифицировать содержание секций .text или изменить атрибуты секций .data без изменения самой структуры исполняемого файла и, соответственно, без низкоуровневых манипуляций с памятью. Системный вызов mmap для выделения исполняемой памяти является наиболее распространенным способом работы с исполняемым кодом в модулях или приложениях.
Тем не менее, если вы хотите, чтобы ваш код выполнялся без использования mmap, то можете рассмотреть возможность использования других подходов, например:
Использование mprotect:
Вы можете выделить память с помощью malloc или другого метода и затем сделать эту память исполняемой с помощью системного вызова mprotect. Это позволяет вам писать в память, а затем изменять атрибуты памяти.
Использование .text в качестве временного хранилища:
Хотя модификация секции .text практически невозможна без специализированного подхода (например, создание загрузчика), вы можете использовать .rodata или другие секции, чтобы создать данные, которые можно выполнить, но это может сталкиваться с проблемами безопасности.
Пример использования mprotect для изменения атрибутов памяти:
.section .datacode:
.byte 0xB8, 0x01, 0x00, 0x00, 0x00 # mov eax, 1
.byte 0xC3 # ret
.section .text
.global _start
_start:
# Выделяем память для кода
mov $0x1000, %eax # размер памяти в 4096 байт
xor %ebx, %ebx # ftruncate(0) == 0
syscall
# Копируем код в выделенную память
mov $code, %esi # указатель на код
mov 0x1000,mov0x1000, %edi # адрес выделенной памяти
mov 0x1000,mov0x40, %ecx # количество байт (64)
rep movsb
# Делаем память исполняемой
mov 0x1000,mov0x1000, %ebx # адрес выделенной памяти
mov 0x1000,mov7, %ecx # PROT_READ | PROT_WRITE | PROT_EXEC
mov $0x1000, %edx # размер памяти
syscall
# Переходим к выполнению кода
jmp *%edi # прыгаем в исполняемый код
Обратите внимание, что нужно правильно настроить секции, чтобы избежать аппаратных и программных исключений. Эксперименты с правами доступа тренеров могут привести к непредсказуемому поведению программы. Лучше всего рассматривать такие подходы в контексте изучения и понимания работы системного программирования, но не в конечных производственных системах.