我找到了一篇有关自我修改代码的文章,并尝试做一些示例,但是我总是遇到分段错误。据我所了解,fas违反了内存权限。代码段是(r)ead / e(x)ecute,因此尝试将结果写入此错误。是否可以通过在运行时或之前更改内存许可来测试程序?我使用的是linux,示例是用GAS汇编编写的。
.extern memcpy .section .data string: .asciz "whatever" string_end: .section .bss .lcomm buf, string_end-string .section .text .globl main main: call changer mov $string, %edx label: push string_end-string push $buf push $string call memcpy changer: mov $offset_to_write, %esi mov $label, %edi mov $0xb, %ecx loop1: lodsb stosb loop loop1 ret offset_to_write: push 0 call exit end:
因此,在osgx建议的修改之后,这是一个有效的代码(实际上,如果您汇编并链接并运行它会崩溃,但是如果您使用gdb观看它会修改其代码!)
.extern memcpy .section .data string: .asciz "Giorgos" string_end: .section .bss .lcomm buf, string_end-string .section .text .globl main main: lea (main), %esi # get the start of memory region to # change its permissions (smc-enabled) andl $0xFFFFF000, %esi # align to start of a pagesize pushl $7 # permissions==r|w|x pushl $4096 # page size pushl %esi # computed start address call mprotect call changer # function that does smc mov $string, %edx label: push string_end-string # this code will be overridden push $buf # and never be executed! push $string call memcpy changer: mov $offset_to_write, %esi # simple copy bytes algorithm mov $label, %edi mov $0xb, %ecx loop1: lodsb stosb loop loop1 ret offset_to_write: # these instructions will be push $0 # executed eventually call exit end:
您应该在运行时更改内存访问权限。
#include <sys/mman.h> void *addr = get_address_of_instruction_pointer(); int length = 4096; /* size of a page */ if (mprotect(addr, length, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) { /* current code page is now writable and code from it is allowed for execution */ }