14

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:
Raedwald
  • 46,613
  • 43
  • 151
  • 237
Fotinopoulos Giorgos
  • 1,027
  • 3
  • 17
  • 36
  • Not sure how it's done on linux, but you could either instruct your linker to use custom flags for .text section, either to be able to specify them in the source (default for .data is RW, for .text is RX) – ruslik Nov 12 '10 at 22:02
  • @ruslik can i specify from the source the permission of the code (text) segment by using rwx? – Fotinopoulos Giorgos Nov 12 '10 at 22:08

3 Answers3

15

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 */
}
osgx
  • 90,338
  • 53
  • 357
  • 513
  • can i use this function from assembly? Do i need any special privileges in order to use it? – Fotinopoulos Giorgos Nov 12 '10 at 22:04
  • 1
    Yes, you can. The easy way is to compile C code with mprotect to .S file (-S) and copy-paste the mprotect call to your code. Special privileges is not needed for memory, owned by your process, and there must be no super-security patches to the kernel – osgx Nov 12 '10 at 22:07
  • there is a good article (the only drawback - it is using intel syntax) http://asm.sourceforge.net/articles/smc.html – osgx Nov 12 '10 at 22:11
5

Modern CPUs have a feature called DEP which prevents execution of code on the stack. Previously, this was possible; now, it is not. The binary is loaded into read-only memory by default.

With that out of the way, you can use the mprotect system call to mark your binary's location in memory as executable - SO LONG AS YOUR CODE IS NOT DEP-PROTECTED. So don't try to put code and the stack and then jump into it.

Borealid
  • 95,191
  • 9
  • 106
  • 122
  • 1
    `mprotect PROT_READ | PROT_WRITE | PROT_EXEC` should disable DEP. Also, this called DEP only in MS world – osgx Nov 12 '10 at 22:00
  • But i don't try to manipulate the stack, i just try to change/generate instructions in the code segment. – Fotinopoulos Giorgos Nov 12 '10 at 22:03
  • @osgx: _"this called DEP only in MS world"_ [That is simply not true](http://oleb.net/blog/2012/07/ios-hackers-handbook/); DEP is a common term. – Lightness Races in Orbit Jul 08 '15 at 23:30
  • 1
    Some blogs may call every **executable space protection** "DEP", but when they use Wikipedia as primary source, we can do the same - page https://en.wikipedia.org/wiki/Executable_space_protection lists DEP only in MS OS section as "Under Windows XP or Server 2003, the feature is called Data Execution Prevention (abbreviated DEP)". As I understand, MS created the term "DEP" (in [2003-2004](https://scholar.google.com/scholar?q=%22Data+Execution+Prevention%22&hl=en&as_sdt=0%2C5&as_ylo=&as_yhi=2004)) and then it was used by some other vendors.. – osgx Jul 09 '15 at 01:39
  • Other operating systems call this “execution protection.” It's not a new feature by any means, even the 80286 had it. Microsoft just invented this acronym to make it sound like they invented something. – fuz Oct 21 '16 at 09:26
3

You can also disable write-protection for the entire program by passing the switch -N to the linker. If you are invoking the linker from gcc, pass Wl,-N. If you invoke ld directly, pass -N.

fuz
  • 88,405
  • 25
  • 200
  • 352