自修改code总是分割在Linux上的故障 [英] Self modifying code always segmentation faults on Linux

查看:157
本文介绍了自修改code总是分割在Linux上的故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了大约自修改code的文章,试图做一些例子,但我总是得到分割故障。由于FAS我能理解,有违反内存权限。在code段是读(r)/ E(X)ecute和书面方式,结果这种故障,所以尝试。有没有一种方法来在运行时或之前,改变内存权限将测试程序?我使用Linux和的例子是写在GAS组装。

  .extern的memcpy
.section伪。数据
串:
        .asciz无所谓
STRING_END:
.section伪的.bss
        .lcomm BUF,STRING_END串
.section伪的.text
.globl主
主要:
        换电话
        MOV $字符串,EDX%
标签:
        推STRING_END串
        推$ BUF
        推$字符串
        调用的memcpy
换:
        MOV $ offset_to_write,ESI%
        MOV $标签,电子数据交换%
        MOV $ 0XB,ECX%
循环1:
        LODSB
        STOSB
        循环循环1
        RET
offset_to_write:
        推0
        调用exit
结束:

所以以后的修改由osgx建议这里是一个工作code。(实际上,如果你组装及功放;链接&安培;!运行它崩溃了,但如果你看用gdb它修改其code)

  .extern的memcpy
.section伪。数据
串:
        .ascizGiorgos
STRING_END:
.section伪的.bss
        .lcomm BUF,STRING_END串
.section伪的.text
.globl主
主要:
        LEA(主),ESI%#得到内存区域的开始
                                        #修改权限(SMC-启用)
        和L $ 0xFFFFF000,ESI%#对准开始页面大小的
        pushl $ 7#权限== - [R | W | X
        pushl $#4096个页面大小
        pushl%ESI#计算起始地址
        打电话的mprotect        电话换#函数,它SMC
        MOV $字符串,EDX%
标签:
        推STRING_END串#本code将被覆盖
        推$ BUF#和永远不会被执行!
        推$字符串
        调用的memcpy
换:
        MOV $ offset_to_write,ESI%#简单复制字节算法
        MOV $标签,电子数据交换%
        MOV $ 0XB,ECX%
循环1:
        LODSB
        STOSB
        循环循环1
        RET
offset_to_write:#这些说明会
        推$ 0#最终执行
        调用exit
结束:


解决方案

您应该改变在运行时内存的访问权限。

 的#include< SYS / mman.h>void *的地址= get_address_of_instruction_pointer();
INT长度= 4096; / *页面的大小* /如果(则mprotect(地址,长度,PROT_READ | PROT_WRITE | PROT_EXEC)== 0){
    / *当前code页现在是可写的,并从中code允许执行* /
}

i found an article about self modifying code and tried to do some examples, but i get always segmentation faults. As fas as i can understand, there is a violation in memory permissions. The code segment is (r)ead/e(x)ecute and so the attempt of writting results to this fault. Is there a way to test the program either by changing the memory permissions at runtime or before? I'm using linux and the example is written in GAS assembly.

.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:

so after modification suggested by osgx here is a working code.(Actually if you assemble&link&run it crashes but if you watch using gdb it does modifies its code!)

.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:

解决方案

You should to change memory access permissions in runtime.

#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 */
}

这篇关于自修改code总是分割在Linux上的故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆