Guarded
Memory Move (GMM) Home Page
The Guarded Memory Move tool gets
handy when you have to study buffer
overflows and you need to catch them together with a "good" stack
image.
When a stack overflow has been exploited, the back trace is already
gone
together with good information about parameters and local variables,
that are of vital importance when trying to understand how the attacker
is trying to work out the exploit. The GMM
library uses dynamic function call interception to catch the most
common
functions that are used by attackers to exploit stack buffers. The GMM library uses the LD_PRELOAD capability and offers
two
services to the user. First of all, it avoids buffer overflow to allow
the attacker to execute shell-code on your machine. Second, in case
where an exploit is detected, the stack content is saved and a
segmentation fault is triggered. The resulting core dump will then have
all the necessary information to debug the exploit and fix the
software.
Internally, the library insert itself between the application and the glibc library
and
intercept functions that might lead to buffer overflow exploits. Before
calling the glibc
core function, the GMM layer
saves part of the stack frame above the caller to a temporary location
in its frame. It also stores the previous three return addresses in its
local storage before calling the glibc core
function. When the core function returns, the GMM code samples again the
previously
recorded return addresses and, if they differ, it restores the
previously saved stack frame and issue a segmentation fault. This with
a clean
stack frame, so that
it can be
inspected with a debugger. While other solutions exist to detect buffer
overflow exploits, like for example StackGuard
and StackShield,
those
differs from GMM in many ways.
They live as gcc patches and do
require you to rebuild your application to use their functionalities.
The good of this approach is that every single function is protected
against buffer overflows. The bad of this solution is that every single
function is protected against buffer overflows. That is, performance
regression on the whole application, even if this is not really a huge
problem when hunting for buffer overflows. Another solution similar to GMM is LibSafe,
but it does not save and restore the stack frame by making it unusable
for debugging. But let's see how GMM
differs from the above listed solutions. First of all, GMM works everywhere there are stack
frames and the gcc
and glibc
duo. That
means that it is not limited to i386 only. And now the real reason for
the GMM existence. This is how
it will look like a stack frame when a buffer overflow is detected with
any debugger or the above solutions:
[davide@bigblue
test]$ gdb -c
core.14600 gmm-test
GNU gdb Red
Hat Linux
(5.3post-0.20021129.18rh)
Copyright
2003 Free Software
Foundation, Inc.
GDB is free
software, covered by the
GNU General Public License, and you are
welcome to
change it and/or
distribute copies of it under certain conditions.
Type "show
copying" to see the
conditions.
There is
absolutely no warranty for
GDB. Type "show warranty" for details.
This GDB was
configured as
"i386-redhat-linux-gnu"...
Core was
generated by `./gmm-test
uiyueiwyeowyreoywoeywoewoyrowuruowyeouwyeoqwyeowyeoyruowuoewueywewou'.
Program
terminated with signal 11,
Segmentation fault.
Reading
symbols from
/lib/libc.so.6...done.
Loaded
symbols for /lib/libc.so.6
Reading
symbols from
/lib/ld-linux.so.2...done.
Loaded
symbols for /lib/ld-linux.so.2
#0
0x776f6579 in ?? ()
(gdb) bt
#0
0x776f6579 in ?? ()
Cannot access
memory at address
0x77716f65
(gdb)
This buffer overflow is generated
using the test application available
inside the test directory of
the distribution package. No much of useful information are there and
no
debugging is basically possible with the above information. Let's look
at how the stack frame looks like when GMM
is on the loop:
[davide@bigblue
test]$ gdb -c
core.14604 gmm-test
GNU gdb Red
Hat Linux
(5.3post-0.20021129.18rh)
Copyright
2003 Free Software
Foundation, Inc.
GDB is free
software, covered by the
GNU General Public License, and you are
welcome to
change it and/or
distribute copies of it under certain conditions.
Type "show
copying" to see the
conditions.
There is
absolutely no warranty for
GDB. Type "show warranty" for details.
This GDB was
configured as
"i386-redhat-linux-gnu"...
Core was
generated by `./gmm-test
uiyueiwyeowyreoywoeywoewoyrowuruowyeouwyeoqwyeowyeoyruowuoewueywewou'.
Program
terminated with signal 11,
Segmentation fault.
Reading
symbols from
../gmm/.libs/libgmm.so...done.
Loaded
symbols for
../gmm/.libs/libgmm.so
Reading
symbols from
/lib/libc.so.6...done.
Loaded
symbols for /lib/libc.so.6
Reading
symbols from
/lib/libdl.so.2...done.
Loaded
symbols for /lib/libdl.so.2
Reading
symbols from
/lib/ld-linux.so.2...done.
Loaded
symbols for /lib/ld-linux.so.2
#0
0x400185d4 in sprintf
(str=0xbffff840 "юб", fmt=0x8048464 "%s") at gmm.c:243
243
WRAP_VFUNCTION(int, sprintf,
(char *str, const char *fmt, ...), fmt, (str, fmt, args))
(gdb) bt
#0
0x400185d4 in sprintf
(str=0xbffff840 "юб", fmt=0x8048464 "%s") at gmm.c:243
#1
0x08048376 in do_overflow
(str=0xbffffa44
"uiyueiwyeowyreoywoeywoewoyrowuruowyeouwyeoqwyeowyeoyruowuoewueywewouew")
at gmm-test.c:33
#2
0x08048396 in run_test
(str=0xbffffa44
"uiyueiwyeowyreoywoeywoewoyrowuruowyeouwyeoqwyeowyeoyruowuoewueywewouew")
at gmm-test.c:41
#3
0x080483b3 in main (argc=2,
argv=0x390d) at gmm-test.c:51
#4
0x40043ab7 in
__libc_start_main
() from /lib/libc.so.6
(gdb)
A lot better, isn't it? The whole
stack frame is preserved and
debugging and inspection of function parameters and local variables is
possible. This is the main reason that drove the GMM development. It is possible to
use the environment variable GMM_FAULT_EXEC
to specify the path of an executable to be run when a fault is
detected.
The executable will be run with only one parameter, that is the PID of
the monitored process. The monitored process will be waiting the
external process to complete before continuing the execution (that will
lead to a segmentation fault). The GMM_FAULT_EXEC
can be used for many purposes. From sending an email notification up to
for running a debugger to attach the faulting process. For the GMM library to work, the software
should be compiled with frame pointers (that is gcc default) and for the stack dump to
be useful, debugging information should be included inside the binary (gcc -g). There is a little performance
regression in using this library, but it should not impact at all the
normal use of the executable. And, when you are hunting for exploits,
you don't really care about performance. To use the library, you first
have to build it:
$ ./configure (put
eventual
configure parameters here)
$ make
# make install
To use the library you have to
add it to the LD_PRELOAD in
your enviroment (or
put it on the same command line you're using to run the binary).
Example:
$ LD_PRELOAD=/usr/local/lib/libgmm.so
XXXX ...
where XXXX is the path of the
binary you want to monitor. You might
want to be sure that your core dump limit is not set to zero by issuing:
$ ulimit -c NNNN
where NNNN is the maximum
size
of the core dump in Kb.
Software
The latest package source code is
available here:
GMM 0.6
GMM White Paper
GMM Home Page at FreshMeat
StackGuard
StackShield
LibSafe
Author
Home Page