Antes de empezar tengo que aclarar que voy a estar trabajando con una máquina de 32 bits y que por lo tanto las direcciones que aparecerán serán de 32 bits, pero toda la teoría es aplicable (al menos hasta donde yo sé) a máquinas de 64 bits... sólo que con direcciones más largas :P.
A la hora de jugar con exploits e intentar desarrollarlos, una de las principales cosas que uno debe saber es el entorno donde se ejecuta el proceso a explotar.
Durante la ejecución, un proceso no es más que una secuencia de bytes en memoria, pero esa memoria tiene ciertas características y orden.
Antes de explicar cómo se organiza la memoria durante la ejecución de un proceso introduzcamos algunos conceptos:
Sección: Un programa está dividido en secciones. Estas secciones puede que se carguen o no en memoria cuando el programa este en ejecución. Veamos un ejemplo de esto:
$ objdump -h /bin/bash
/bin/bash: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048154 08048154 00000154 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048168 08048168 00000168 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 08048188 08048188 00000188 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 0000364c 080481ac 080481ac 000001ac 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 000084b0 0804b7f8 0804b7f8 000037f8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 000080d1 08053ca8 08053ca8 0000bca8 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 00001096 0805bd7a 0805bd7a 00013d7a 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 000000b0 0805ce10 0805ce10 00014e10 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.dyn 00000040 0805cec0 0805cec0 00014ec0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rel.plt 00000618 0805cf00 0805cf00 00014f00 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 00000030 0805d518 0805d518 00015518 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 00000c40 0805d548 0805d548 00015548 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .text 0008e9cc 0805e190 0805e190 00016190 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 0000001c 080ecb5c 080ecb5c 000a4b5c 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00019ef8 080ecb80 080ecb80 000a4b80 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame_hdr 0000002c 08106a78 08106a78 000bea78 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame 0000009c 08106aa4 08106aa4 000beaa4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .ctors 00000008 08107f04 08107f04 000bef04 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .dtors 00000008 08107f0c 08107f0c 000bef0c 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .jcr 00000004 08107f14 08107f14 000bef14 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 000000d8 08107f18 08107f18 000bef18 2**2
CONTENTS, ALLOC, LOAD, DATA
21 .got 00000004 08107ff0 08107ff0 000beff0 2**2
CONTENTS, ALLOC, LOAD, DATA
22 .got.plt 00000318 08107ff4 08107ff4 000beff4 2**2
CONTENTS, ALLOC, LOAD, DATA
23 .data 00004390 08108320 08108320 000bf320 2**5
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00004f0c 0810c6c0 0810c6c0 000c36b0 2**5
ALLOC
25 .gnu_debuglink 0000000c 00000000 00000000 000c36b0 2**0
CONTENTS, READONLY
/bin/bash: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048154 08048154 00000154 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048168 08048168 00000168 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 08048188 08048188 00000188 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 0000364c 080481ac 080481ac 000001ac 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 000084b0 0804b7f8 0804b7f8 000037f8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 000080d1 08053ca8 08053ca8 0000bca8 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 00001096 0805bd7a 0805bd7a 00013d7a 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 000000b0 0805ce10 0805ce10 00014e10 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.dyn 00000040 0805cec0 0805cec0 00014ec0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rel.plt 00000618 0805cf00 0805cf00 00014f00 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 00000030 0805d518 0805d518 00015518 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 00000c40 0805d548 0805d548 00015548 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .text 0008e9cc 0805e190 0805e190 00016190 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 0000001c 080ecb5c 080ecb5c 000a4b5c 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00019ef8 080ecb80 080ecb80 000a4b80 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame_hdr 0000002c 08106a78 08106a78 000bea78 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame 0000009c 08106aa4 08106aa4 000beaa4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .ctors 00000008 08107f04 08107f04 000bef04 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .dtors 00000008 08107f0c 08107f0c 000bef0c 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .jcr 00000004 08107f14 08107f14 000bef14 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 000000d8 08107f18 08107f18 000bef18 2**2
CONTENTS, ALLOC, LOAD, DATA
21 .got 00000004 08107ff0 08107ff0 000beff0 2**2
CONTENTS, ALLOC, LOAD, DATA
22 .got.plt 00000318 08107ff4 08107ff4 000beff4 2**2
CONTENTS, ALLOC, LOAD, DATA
23 .data 00004390 08108320 08108320 000bf320 2**5
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00004f0c 0810c6c0 0810c6c0 000c36b0 2**5
ALLOC
25 .gnu_debuglink 0000000c 00000000 00000000 000c36b0 2**0
CONTENTS, READONLY
Estas son las secciones que contiene el binario de bash, como ya dijimos algunas se cargarán en el proceso en memoria y otras no. Pero las secciones aquí mostradas no son las únicas que va a tener el proceso. Cuando ejecutemos un programa "aparecen" secciones adicionales como la pila o el heap. Realmente no me gusta llamarlas secciones pero muchísima gente las llama de tal forma. Al final lo que hay que tener claro es que los datos (¡los bytes, vaya!) que hay en esas secciones se cargan en la memoria del proceso.
Región: Se le llama "región de memoria" o "región" a un trozo de la memoria del proceso contigua en direcciones y con los mismos permisos para todos sus bytes. A veces también se le llama "segmento". Veamos las regiones de un proceso ejecutando el bash anterior:
$ ps | egrep "bash"
2406 pts/1 00:00:00 bash
$ cat /proc/2406/maps
001d2000-00208000 r-xp 00000000 fc:03 382867 /lib/libncurses.so.5.7
00208000-0020a000 r--p 00035000 fc:03 382867 /lib/libncurses.so.5.7
0020a000-0020b000 rw-p 00037000 fc:03 382867 /lib/libncurses.so.5.7
0020b000-00362000 r-xp 00000000 fc:03 382855 /lib/libc-2.12.1.so
00362000-00364000 r--p 00157000 fc:03 382855 /lib/libc-2.12.1.so
00364000-00365000 rw-p 00159000 fc:03 382855 /lib/libc-2.12.1.so
00365000-00368000 rw-p 00000000 00:00 0
0058a000-00594000 r-xp 00000000 fc:03 383014 /lib/libnss_files-2.12.1.so
00594000-00595000 r--p 00009000 fc:03 383014 /lib/libnss_files-2.12.1.so
00595000-00596000 rw-p 0000a000 fc:03 383014 /lib/libnss_files-2.12.1.so
00b3f000-00b40000 r-xp 00000000 00:00 0 [vdso]
00d1f000-00d28000 r-xp 00000000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d28000-00d29000 r--p 00008000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d29000-00d2a000 rw-p 00009000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d9c000-00db8000 r-xp 00000000 fc:03 382771 /lib/ld-2.12.1.so
00db8000-00db9000 r--p 0001b000 fc:03 382771 /lib/ld-2.12.1.so
00db9000-00dba000 rw-p 0001c000 fc:03 382771 /lib/ld-2.12.1.so
00dd0000-00dd2000 r-xp 00000000 fc:03 383008 /lib/libdl-2.12.1.so
00dd2000-00dd3000 r--p 00001000 fc:03 383008 /lib/libdl-2.12.1.so
00dd3000-00dd4000 rw-p 00002000 fc:03 383008 /lib/libdl-2.12.1.so
00f29000-00f2f000 r-xp 00000000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f2f000-00f30000 r--p 00006000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f30000-00f31000 rw-p 00007000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f9a000-00fad000 r-xp 00000000 fc:03 383011 /lib/libnsl-2.12.1.so
00fad000-00fae000 r--p 00012000 fc:03 383011 /lib/libnsl-2.12.1.so
00fae000-00faf000 rw-p 00013000 fc:03 383011 /lib/libnsl-2.12.1.so
00faf000-00fb1000 rw-p 00000000 00:00 0
08048000-08107000 r-xp 00000000 fc:03 342053 /bin/bash
08107000-08108000 r--p 000be000 fc:03 342053 /bin/bash
08108000-0810d000 rw-p 000bf000 fc:03 342053 /bin/bash
0810d000-08112000 rw-p 00000000 00:00 0
089ef000-08c04000 rw-p 00000000 00:00 0 [heap]
b741c000-b7443000 r--p 00000000 fc:03 18415 /usr/share/locale-langpack/es/LC_MESSAGES/bash.mo
b7443000-b744a000 r--s 00000000 fc:03 408043 /usr/lib/gconv/gconv-modules.cache
b744a000-b744b000 r--p 004e7000 fc:03 408807 /usr/lib/locale/locale-archive
b744b000-b756a000 r--p 002a3000 fc:03 408807 /usr/lib/locale/locale-archive
b756a000-b776a000 r--p 00000000 fc:03 408807 /usr/lib/locale/locale-archive
b776a000-b776c000 rw-p 00000000 00:00 0
b777e000-b7780000 rw-p 00000000 00:00 0
bf8b1000-bf8d2000 rw-p 00000000 00:00 0 [stack]
2406 pts/1 00:00:00 bash
$ cat /proc/2406/maps
001d2000-00208000 r-xp 00000000 fc:03 382867 /lib/libncurses.so.5.7
00208000-0020a000 r--p 00035000 fc:03 382867 /lib/libncurses.so.5.7
0020a000-0020b000 rw-p 00037000 fc:03 382867 /lib/libncurses.so.5.7
0020b000-00362000 r-xp 00000000 fc:03 382855 /lib/libc-2.12.1.so
00362000-00364000 r--p 00157000 fc:03 382855 /lib/libc-2.12.1.so
00364000-00365000 rw-p 00159000 fc:03 382855 /lib/libc-2.12.1.so
00365000-00368000 rw-p 00000000 00:00 0
0058a000-00594000 r-xp 00000000 fc:03 383014 /lib/libnss_files-2.12.1.so
00594000-00595000 r--p 00009000 fc:03 383014 /lib/libnss_files-2.12.1.so
00595000-00596000 rw-p 0000a000 fc:03 383014 /lib/libnss_files-2.12.1.so
00b3f000-00b40000 r-xp 00000000 00:00 0 [vdso]
00d1f000-00d28000 r-xp 00000000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d28000-00d29000 r--p 00008000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d29000-00d2a000 rw-p 00009000 fc:03 383016 /lib/libnss_nis-2.12.1.so
00d9c000-00db8000 r-xp 00000000 fc:03 382771 /lib/ld-2.12.1.so
00db8000-00db9000 r--p 0001b000 fc:03 382771 /lib/ld-2.12.1.so
00db9000-00dba000 rw-p 0001c000 fc:03 382771 /lib/ld-2.12.1.so
00dd0000-00dd2000 r-xp 00000000 fc:03 383008 /lib/libdl-2.12.1.so
00dd2000-00dd3000 r--p 00001000 fc:03 383008 /lib/libdl-2.12.1.so
00dd3000-00dd4000 rw-p 00002000 fc:03 383008 /lib/libdl-2.12.1.so
00f29000-00f2f000 r-xp 00000000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f2f000-00f30000 r--p 00006000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f30000-00f31000 rw-p 00007000 fc:03 383012 /lib/libnss_compat-2.12.1.so
00f9a000-00fad000 r-xp 00000000 fc:03 383011 /lib/libnsl-2.12.1.so
00fad000-00fae000 r--p 00012000 fc:03 383011 /lib/libnsl-2.12.1.so
00fae000-00faf000 rw-p 00013000 fc:03 383011 /lib/libnsl-2.12.1.so
00faf000-00fb1000 rw-p 00000000 00:00 0
08048000-08107000 r-xp 00000000 fc:03 342053 /bin/bash
08107000-08108000 r--p 000be000 fc:03 342053 /bin/bash
08108000-0810d000 rw-p 000bf000 fc:03 342053 /bin/bash
0810d000-08112000 rw-p 00000000 00:00 0
089ef000-08c04000 rw-p 00000000 00:00 0 [heap]
b741c000-b7443000 r--p 00000000 fc:03 18415 /usr/share/locale-langpack/es/LC_MESSAGES/bash.mo
b7443000-b744a000 r--s 00000000 fc:03 408043 /usr/lib/gconv/gconv-modules.cache
b744a000-b744b000 r--p 004e7000 fc:03 408807 /usr/lib/locale/locale-archive
b744b000-b756a000 r--p 002a3000 fc:03 408807 /usr/lib/locale/locale-archive
b756a000-b776a000 r--p 00000000 fc:03 408807 /usr/lib/locale/locale-archive
b776a000-b776c000 rw-p 00000000 00:00 0
b777e000-b7780000 rw-p 00000000 00:00 0
bf8b1000-bf8d2000 rw-p 00000000 00:00 0 [stack]
Vemos que tiene un montón de regiones y cuyos nombres no tienen nada que ver con las secciones del programa. Aún así las secciones del programa estarán en algunas de estas regiones. Fijémonos por ejemplo en las direcciones de comienzo y fin de la fila en negrita, comienza en 0x08048000, que corresponde al comienzo de la sección .text con dirección 0x0805e190 y offset 0x00016190 (0x0805e190 - 0x00016190 = 0x08048000). Pero en esa región tenemos más de una sección del programa.
Siendo un poco más genéricos y simplificando todo esto tenemos que tener claro que un proceso tiene varias de las secciones que trae el programa original y algunas más (heap, stack por ejemplo). En general siempre se nos suele mostrar algo parecido a lo siguiente:
Aunque hay que tener cuidado ya que este esquema puede inducir a error. Como ya hemos dicho, la memoria de un proceso no se divide en secciones, sino en regiones y pueden englobar más de una sección.
Como vemos en la imagen anterior, existen unas secciones llamadas stack y heap que seguro hemos oido hablar de ellas anteriormente, ya que tienen mucha relevancia.
En la pila (stack) suelen ir las variables locales a las funciones además de cierta información de control, en otra entrada hablaremos más profundamente de lo que hay en la pila y con ejemplos. Por ahora baste decir que la pila suele estar en direcciones bastante altas de memoria y que crece hacia direcciones más bajas, esto siempre cuesta verlo al principio pero con la experiencia lo iremos interiorizando.
El heap es otra sección con bastante importancia, allí residen los datos de toda la memoria que el proceso va pidiendo dinámicamente (con malloc() hablando rápido y mal). A diferencia de la pila ésta crece hacia direcciones más grandes de memoria. Esto significa que si un proceso empieza a pedir mucha memoria y a enlazar llamadas a funciones una tras otras sin retornar habrá un punto en el que dichas secciones "chocarán".
Y con esto ya es suficiente teoría de ejecución de procesos por ahora.
Saludos.
No hay comentarios:
Publicar un comentario