Self modifying code always segmentation faults on Linux

Asked
Active3 hr before
Viewed126 times

6 Answers

90%

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

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 */
}
88%

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.,Ignoring the world of grief you could be causing yourself via self-modifying code(!), it seems to me there are 3 options:,Of the three above, my initial choice (in the absence of requirements) would be to take a look at option 3. I suspect it's the least painful way to start. I've used all of the above - unfortunately I can't post links to client code.,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!)

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:
load more v
72%

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.,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.,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!),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.

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:
load more v
65%

Yep it’s basicaly a Segfault, the best way is to run the code in valgrind if you are on linux, and check memory alocation and size that you write. It could just be that you went too far in your,I’m no expert on windows, i m really more proeficient on linux. But i know that there are many security features for memory on currents OS. The only time i managed to play with self modifying code was on Fedora with all features deactivated to bypass adress randomization etc …,“The exception that is thrown when there is an attempt to read or write protected memory.”,Lol @ your lab. Whatever happened to debugging? I guess the errors are clearly stated during compile time, did you actually code this?.

Yep it’s basicaly a Segfault, the best way is to run the code in valgrind if you are on linux, and check memory alocation and size that you write. It could just be that you went too far in your

unsigned char buff[17];
load more v
75%

“On Linux it is always permissible to call mprotect() on any address in a process's address space (except for the kernel vsyscall area). In particular it can be used to change existing code mappings to be writable.”,The address in virtual memory space at runtime is different from the offset I add to the base address I obtain from the original elf file, therefore needs to be calculated at runtime.,I interpret this to mean I can call mprotect on the mapped memory region of the process.,Oh yes that’s exactly the purpose. And I am getting a zero return value from mprotect. I double checked the man page for mprotect to be sure I was correct, it states in the notes section:

I have been working on a small project on and off to further my understanding of Linux programming as well as practice x86_64 assembly. The purpose of the program is to load in an Elf-64 object file, encrypt the text section, and then inject a set of instructions into an empty pocket in the file. The injected codes purpose is to run mprotect on the text section that is currently loaded into memory and then run the decipher that section. A new copy with the injected code is then created and should simply run as it was intended before modification but sends a small message to stdout. The use would look like this on an elf I will call target:

$> ./hello_world | cat -e

$ > . / hello_world | cat - e
load more v
40%

I'm an expert-level C and C++ developer, with a specialty in memory management. I have experience writing memory-safe code with both the modern safe techniques and the ancient unsafe techniques. I've used malloc and free without killing myself. I love pointers. I've debugged more than my share of undefined behavior, and authored the canonical StackOverflow question on segfault debugging.,I have recently run into a few short comings with the compiler. First and foremost being that the routines I've written in C don't seem to load as fast onto the screen as compared to Assembly.,which is what I expected, but the apple clang assembler does not like this syntax because in 64 bit mode I have to use position independent addressing modes.,Built on Forem — the open source software that powers DEV and other inclusive communities.

[Thread 0x7ffff4ccc700(LWP 1735) exited]

Thread 2 "a.out"
received signal SIGABRT, Aborted.
   [Switching to Thread 0x7ffff54cd700(LWP 1734)]
__GI_raise(sig = sig @entry = 6) at.. / sysdeps / unix / sysv / linux / raise.c: 50
50.. / sysdeps / unix / sysv / linux / raise.c: No such file or directory.
load more v

Other "undefined-undefined" queries related to "Self modifying code always segmentation faults on Linux"