我发现了一篇关于自修改代码的文章,并试图做一些例子,但我总是得到分段错误 . 就像我能理解的那样,内存权限存在违规行为 . 代码段是(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:
3 回答
您应该在运行时更改内存访问权限 .
现代CPU具有一个名为DEP的功能,可防止在堆栈上执行代码 . 以前,这是可能的;现在,事实并非如此 . 默认情况下,二进制文件被加载到只读内存中 .
除此之外,您可以使用mprotect系统调用将内存中的二进制文件位置标记为可执行文件 - 因为您的代码不受保护 . 所以不要试图把代码和堆栈然后跳进去 .
您还可以通过将开关
-N
传递给链接器来禁用整个程序的写保护 . 如果从gcc调用链接器,则传递Wl,-N
. 如果直接调用ld
,则传递-N
.