Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.compilers > #987 > unrolled thread

Executing from dynamically allocated memory

Started by"news" <news@fx32.iad.highwinds-media.com>
First post2013-10-12 00:05 +0000
Last post2013-10-13 10:44 +0200
Articles 7 — 7 participants

Back to article view | Back to comp.compilers


Contents

  Executing from dynamically allocated memory "news" <news@fx32.iad.highwinds-media.com> - 2013-10-12 00:05 +0000
    Re: Executing from dynamically allocated memory "James Harris" <james.harris.1@gmail.com> - 2013-10-12 10:10 +0100
    Re: Executing from dynamically allocated memory Sébastien Fricker <sebastien.fricker@gmail.com> - 2013-10-12 11:52 +0200
    Re: Executing from dynamically allocated memory chakaram@auth.gr - 2013-10-12 19:20 +0300
    Re: Executing from dynamically allocated memory Alex McDonald <blog@rivadpm.com> - 2013-10-12 11:12 -0700
    Re: Executing from dynamically allocated memory sandmann@cs.au.dk (Søren Sandmann) - 2013-10-12 20:58 +0200
    Re: Executing from dynamically allocated memory Jens Kallup <jkallup@web.de> - 2013-10-13 10:44 +0200

#987 — Executing from dynamically allocated memory

From"news" <news@fx32.iad.highwinds-media.com>
Date2013-10-12 00:05 +0000
SubjectExecuting from dynamically allocated memory
Message-ID<13-10-004@comp.compilers>
In the past, I've malloc'd memory, written machine instructions into it,
and called the function I built there.

All this on a 32-bit intel instruction set, on a Debian system.

This appears no longer too work.  My program gives a segmentation fault.
The debugger tells me that the segmentation fault occurs on the first
instruction of the called function, a
	push   %ebp
residing in malloced memory.

Now it was a year or three ago that this worked.  Has Linux changed in
this respect?  Is there something new I have to do to allocate executable
writable memory for this purpose?

Or might there be something even weirder going on?

-- hendrik

[ Sounds like the NX bit.  See http://en.wikipedia.org/wiki/NX_bit#Linux -John]

[toc] | [next] | [standalone]


#988

From"James Harris" <james.harris.1@gmail.com>
Date2013-10-12 10:10 +0100
Message-ID<13-10-005@comp.compilers>
In reply to#987
"news" <news@fx32.iad.highwinds-media.com> wrote in message
> In the past, I've malloc'd memory, written machine instructions into it,
> and called the function I built there.
>
> All this on a 32-bit intel instruction set, on a Debian system.
>
> This appears no longer too work.  My program gives a segmentation fault.
> The debugger tells me that the segmentation fault occurs on the first
> instruction of the called function, a
> push   %ebp
> residing in malloced memory.
>
> Now it was a year or three ago that this worked.  Has Linux changed in
> this respect?  Is there something new I have to do to allocate executable
> writable memory for this purpose?

Possibly. As John says, this could be caused by current Linux setting the NX
bit for malloced pages. The dump may/should show if that is the case, if you
can decipher the dump.

Instead of malloc you may need to use mmap. It allows permissions to be
specified.

James

[toc] | [prev] | [next] | [standalone]


#989

FromSébastien Fricker <sebastien.fricker@gmail.com>
Date2013-10-12 11:52 +0200
Message-ID<13-10-006@comp.compilers>
In reply to#987
On 12.10.13 02:05, news wrote:
> In the past, I've malloc'd memory, written machine instructions into it,
> and called the function I built there. ...

> Now it was a year or three ago that this worked.  Has Linux changed in
> this respect?  Is there something new I have to do to allocate executable
> writable memory for this purpose?
>
> Or might there be something even weirder going on?
>
> -- hendrik
>
> [ Sounds like the NX bit.  See http://en.wikipedia.org/wiki/NX_bit#Linux -John]

Hendrik,
this does not wonder me that it does not work anymore.
In 2003, I was working on the ARM-Linux kernel and I could see that more
and more the MMU protection bit get used principally to avoid the
possibility to misuse buffer-overflow.

But did you have a look on mmap()? (man mmap)
There is a flag PROT_EXEC. I guess this should permit to create a memory
area on which you can execute code.

SC)bastien

[toc] | [prev] | [next] | [standalone]


#990

Fromchakaram@auth.gr
Date2013-10-12 19:20 +0300
Message-ID<13-10-007@comp.compilers>
In reply to#987
As our moderator pointed out, sounds like NX. Use mmap() with
PROT_READ|PROT_WRITE|PROT_EXEC or just PROT_WRITE and then mprotect()
your region to PROT_READ|PROT_EXEC.

If you're on an i386, then it's probably some kernel hardening patch
that makes the heap non executable.
./ck
--
Chariton Karamitas
Electrical and Computer Engineering Department
Fuculty of Engineering
Aristotle University of Thessaloniki, Greece

[toc] | [prev] | [next] | [standalone]


#991

FromAlex McDonald <blog@rivadpm.com>
Date2013-10-12 11:12 -0700
Message-ID<13-10-008@comp.compilers>
In reply to#987
On Saturday, 12 October 2013 01:05:39 UTC+1, news  wrote:
> In the past, I've malloc'd memory, written machine instructions into it,
> and called the function I built there.
> All this on a 32-bit intel instruction set, on a Debian system. ...

> Now it was a year or three ago that this worked.  Has Linux changed in
> this respect?  Is there something new I have to do to allocate executable
> writable memory for this purpose?
>
> Or might there be something even weirder going on?
> [ Sounds like the NX bit.  See http://en.wikipedia.org/wiki/NX_bit#Linux -John]

mprotect(2) - Linux man page
Name

mprotect - set protection on a region of memory
Synopsis

#include <sys/mman.h>

int mprotect(void *addr, size_t len, int prot);

Description

mprotect() changes protection for the calling process's memory page(s)
containing any part of the address range in the interval [addr,
addr+len-1]. addr must be aligned to a page boundary.

If the calling process tries to access memory in a manner that
violates the protection, then the kernel generates a SIGSEGV signal
for the process.

prot is either PROT_NONE or a bitwise-or of the other values in the
following list:

...

PROT_EXEC

The memory can be executed.

...

[toc] | [prev] | [next] | [standalone]


#992

Fromsandmann@cs.au.dk (Søren Sandmann)
Date2013-10-12 20:58 +0200
Message-ID<13-10-009@comp.compilers>
In reply to#987
"news" <news@fx32.iad.highwinds-media.com> writes:

> In the past, I've malloc'd memory, written machine instructions into it,
> and called the function I built there.
>
> All this on a 32-bit intel instruction set, on a Debian system.
>
> This appears no longer too work.  My program gives a segmentation fault.
> The debugger tells me that the segmentation fault occurs on the first
> instruction of the called function, a
> 	push   %ebp
> residing in malloced memory.
>
> Now it was a year or three ago that this worked.  Has Linux changed in
> this respect?  Is there something new I have to do to allocate executable
> writable memory for this purpose?
>
> Or might there be something even weirder going on?

It's probably just that anonymous memory is not executable by default
anymore. Take a look at this:

    http://www.akkadia.org/drepper/selinux-mem.html

in particular the execmem case. There is also example code.

SC8ren

[toc] | [prev] | [next] | [standalone]


#993

FromJens Kallup <jkallup@web.de>
Date2013-10-13 10:44 +0200
Message-ID<13-10-010@comp.compilers>
In reply to#987
Hello,

this should be work:


#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

extern int errno;
static volatile sig_atomic_t sflag;
static sigset_t signal_neu, signal_alt, signal_leer;
void sigfunc1(int);
void sigfunc2(int);

void signale_mmap(void)
{
   if(signal(SIGSEGV, sigfunc1) == SIG_ERR)
    {
      fprintf(stderr, "Konnte signalhandler fC<r SIGSEGV nicht
einrichten\n");
      exit(0);
     }
   if(signal(SIGBUS, sigfunc2) == SIG_ERR)
     {
       fprintf(stderr, "Konnte signalhandler fC<r SIGBUS nicht
einrichten\n");
       exit(0);
     }

   sigemptyset(&signal_leer);
   sigemptyset(&signal_neu);

   sigaddset(&signal_neu, SIGSEGV);
   sigaddset(&signal_neu, SIGBUS);

   if(sigprocmask(SIG_BLOCK, &signal_neu, &signal_alt) < 0)
      exit(0);
}

void sigfunc1(int sig)
{
   printf("SIGSEGV: Versuch auf einen unerlaubten Speicherbereich zu
schreiben\n");
   exit(0);
}

void sigfunc2(int sig)
{
   printf("SIGBUS: Der Speicherbereich ist nicht mehr gC<ltig\n");
   exit(0);
}

void fun1(int v)
{
   printf("value --> 0x%x\n",v);
}

int main(int argc, char **argv)
{
   int fd,fd1;

   void (*callback1)(int);

   printf("exit-> 0x%x\n",exit);
   printf("puts-> 0x%x\n",puts);
   printf("fun1-> 0x%x\n",fun1);


   struct stat attr;

   signale_mmap();

   if((fd1=open(argv[1],O_RDONLY)) < 0)
   {
       fprintf(stderr,"%s : Konnte %s nicht
C6ffnen\n",strerror(errno),argv[2]);
       exit(0);
   }

   if(fstat(fd1, &attr) == -1)
   {
       fprintf(stderr,"Fehler bei fstat.......\n");
       exit(0);
   }

   callback1 = mmap(0, attr.st_size, PROT_READ | PROT_EXEC, MAP_SHARED,
fd1, 0);
   printf("val: 0x%x\n",callback1);

   if((callback1 == ((caddr_t) -1)) )
     {
       fprintf(stderr, "%s: Fehler bei mmap ...........\n",strerror(errno));
       exit(0);
     }
   close(fd1);

   printf("start...\n");
   callback1((int)callback1);
   printf("ende...\n");

   exit(0);
}

// the following code is compiled with nasm 32 bit

bits 32
org 0x0

;-----------------------------------
; Version 1.0
;-----------------------------------
%define FuncPuts	1
%define FuncFun1	2

segment .text
start:
	push	ebp
	mov	ebp, esp

	mov	eax, [ebp + 8]
	add	eax, LC1
	push	eax

	mov	eax,  [ebp + 8]
	call	dword [eax + func_entry + (FuncPuts * 4)]

	pop	eax

	leave
	ret

segment .data
LC1:	db "Hello You!", 10, 0


func_entry:
	dd 31102011	; version
	dd 0x4015d0	; puts

; cheers and good luck
; Jens

[toc] | [prev] | [standalone]


Back to top | Article view | comp.compilers


csiph-web