Vous êtes sur la page 1sur 15

CI-1220, I-2017

Tarea para explotar vulnerabilidades de buffer overflow


Prof. Braulio Solano Rojas
Fecha entrega: 10 julio 2017

1 Introducción

Esta tarea permite desarrollar habilidades para entender la operacíon de la pila, las convenciones de llamados
a funciones en programas y otros aspectos importantes de seguridad de programas en la arquitectura de
procesadores de la familia Intel x86-64. La tarea incluye el desarrollo de una serie de ataques de buffer
overflow realizados a dos programas ejecutables especialmente construı́dos para usted, según se detalla más
adelante.
Mientras construye la soluci ón, usted adquirir á experiencia con mecanismos com únmente usados para ex-
plotar debilidades de seguridad en sistemas operativos y servidores de red. El objetivo es comprender cómo
se ejecutan a bajo nivel los programas en un computador y la naturaleza de algunas debilidades de seguridad
para que pueda prevenirlas al escribir sus programas, siempre dentro de un ambiente educativo controlado.
De ninguna forma se considera aceptable utilizar este tipo de ataques para obtener acceso indebido a los
recursos de un sistema, y existe legislación a nivel nacional e internacional para regular y penalizar este tipo
de actividades.
Especı́ficamente, el trabajo a realizar comprende la generaci ón de cinco ataques usando dos programas
binarios que contienen diferentes vulnerabilidades de seguridad. Al ejecutar esta tarea se espera que usted:

• Comprenda diferentes formas en que un atacante puede explotar vulnerabilidades de seguridad cuando
los programas de software no se protegen apropiadamente contra ataques de buffer overflow.

• Mejore su nivel técnico sobre cómo escribir programas de forma segura, y comprenda algunas carac-
terı́sticas disponibles en compiladores y sistemas operativos para mitigar las vulnerabilidades estudi-
adas.

• Adquiera un conocimiento detallado acerca de la operaci ón de la pila y los mecanismos de env ı́o de
parámetros entre funciones, en computadores de la familia Intel x86-64.

• Adquiera un conocimiento más detallado en relación con la codificación de instrucciones para equipos
x86-64.

1
• Mejore sus capacidades en el uso de herramientas de depuraci ón de programas tales como GDB y
OBJDUMP .

Nota: durante el desarrollo de la tarea usted obtendrá experiencia de primera mano acerca de cómo explotar
vulnerabilidades de seguridad en sistemas operativos y servidores de red. Entonces, el propósito es ayudarle
a aprender acerca de la operaci ón en tiempo de ejecuci ón de los programas de software y a entender la
naturaleza de estas debilidades, para que usted las evite en su c ódigo al escribir software. Las destrezas
adquiridas no deben ser usadas de forma alguna para atacar u obtener acceso no autorizado a cualquier otro
sistema o recurso y dicha acci ón puede ser sancionada por medio de la legislaci ón nacional vigente.
Como material de referencia se sugiere estudiar las secciones 3.10.3 and 3.10.4 de la 3era edici ón del libro
de referencia para el curso.

2 Aspectos Logı́sticos

Esta es una asignaci ón de carácter individual. Los ataques ser án realizados sobre programas objetivo espe-
cialmente generados para usted.

2.1 Entregables, documentación y calificación

Usted debe reportar los resultados de sus soluciones a trav és del servidor de la tarea, segn se describe en
este enunciado.
Adems, para cada fase usted debe generar una documentaci ón espec ı́fica donde muestre un diagrama o
dibujo detallado de la pila, indicando direcciones de memoria y sus contenidos, de forma tal que se pueda
apreciar el razonamiento realizado al ejecutar cada exploit. De igual forma debe documentar el contenido
de cada archivo exploit, segn se describe en el anexo B de este enunciado, y anexar el texto del exploit a la
documentacin. Incorpore el diagrama de la pila y el texto hexadecimal de cada exploit en un documento en
formato PDF que debe subir a la plataforma del curso, antes de la fecha de entrega de la tarea.
La calificación final de la tarea se compone de 90 puntos de los exploits y 10 puntos de la documentación.

2.2 Obtención de archivos de trabajo

Puede obtener sus archivos de la tarea por medio de su navegador, accediendo a la dirección:

http://orifaz.ecci.ucr.ac.cr:1220/

El servidor crear á sus archivos y se los entregar á por medio del navegador en un archivo con formato tar
con nombre targetk .tar, donde k es un número único para los programas que le sean asignados.
Nota: Usualmente toma algunos segundos construir y bajar su programa, por favor espere para obtener los
archivos.

2
Guarde el archivo targetk .tar en un directorio apropiadamente protegido de su computador y en el cual
vaya a desarrollar la tarea. Luego ejecute el comando: tar -xvf targetk .tar. para desempacar el
directorio targetk que contiene los archivos descritos a continuación.
Recuerde bajar solamente un juego de archivos. Si por alguna raz ón obtiene varios, seleccione uno de ellos
para trabajar e informe apropiadamente a su profesor acerca de la escogencia para efectos de la calificaci ón
correspondiente.
Advertencia: Si desempaca su targetk .tar en una PC, por ejemplo usando Winzip dentro de un sistema
Windows, o indicando al navegador que extraiga los archivos, posiblemente se alterar án los bits con los
permisos de los archivos ejecutables. Tenga este aspecto en mente para ajustar dichos bits apropiadamente,
por medio del comando chmod de Linux, en caso de ser requerido.
Los archivos contenidos en el directorio targetk son:

README.txt: describe el contenido del directorio.

ctarget: programa ejecutable para realizar ataques de code-injection.

rtarget: programa ejecutable para realizar ataques de return-oriented-programming.

cookie.txt: c ódigo hexadecimal de 8 dı́gitos que usted usará como identificador único en sus ataques.

farm.c: código fuente de su “gadget farm,” que usar á para generar los ataques de return-oriented pro-
gramming.
hex2raw: utilidad para convertir la versión texto de los ataques en su correspondiente versión en binario.

En las instrucciones siguientes se asume que usted ya ha copiado los archivos que le corresponden a un
directorio local en su computador de trabajo y que los está ejecutando desde ese directorio, con los permisos
correctamente asignados.

2.3 Puntos Importantes

A continuación algunas reglas importantes con respecto a las soluciones válidas para esta tarea. Las mismas
no tendr án mucho sentido al leer el documento la primera vez, pero se presentan aqu ı́ para una referencia
principal de reglas para cuando usted inicie con la soluci ón.

• Usted debe resolver la tarea en un computador similar al usado para generar los archivos de trabajo,
concretamente en una versi ón reciente de Linux, por raz ón de algunas configuraciones t écnicas que
deben estar disponibles.
• Sus soluciones no pueden usar los ataques para evadir el código de validaci ón de los programas.
Especı́ficamente, cualquier direcci ón que usted incluya en una hilera de ataque, para ser usada por
una instrucción RET, deberı́a estar dirigida a uno de los siguientes puntos:

– La direcci ón de las funciones touch1, touch2, o touch3.


– La direcci ón del código de su exploit.

3
– La direcci ón de uno de los gadgets de su gadget farm.

• Usted solo puede construir gadgets a partir del archivo rtarget con direcciones que var ı́an en el
rango de las funciones start_farm hasta end_farm.

3 Programas Objetivo

Tanto el programa CTARGET como RTARGET leen hileras por la entrada estándar, para ello utilizan la función
getbuf que se define ası́:

1 unsigned getbuf()
2 {
3 char buf[BUFFER_SIZE];
4 Gets(buf);
5 return 1;
6 }

La funci ón Gets es similar a la funci ón de biblioteca est ándar gets—que lee una hilera de la entrada
estándar (terminada por ‘ \n’ or end-of-file) y la guarda (junto con el caracter terminal) en el destino indi-
cado. En este c ódigo, se puede apreciar que el destino es un vector buf de tamaño BUFFER_SIZE bytes.
Al momento en que se generaron sus programas, BUFFER_SIZE fue compilado como una constante con
un valor especı́fico para los programas que le fueron entregados.
Las funciones Gets() y gets() no tienen forma de determinar si los buffers destino son suficientemente
grandes para almacenar cualquier hilera que vayan a ser le ı́das. Estas funciones copian una secuencia de
bytes, posiblemente sobrepasando los lı́mites del espacio en memoria que le fue asignado a los buffers.
Si la hilera digitada por el usuario y le ı́da por getbuf es suficientemente corta, getbuf devolverá un 1,
como se muestra en el siguiente ejemplo:

unix> ./ctarget
Cookie: 0x1a7dd803
Type string: Keep it short!
No exploit. Getbuf returned 0x1
Normal return

Pero usualmente se generará un error si usted escribe una hilera suficientemente grande:

unix> ./ctarget
Cookie: 0x1a7dd803
Type string: This is not a very interesting string, but it has the property ...
Ouch!: You caused a segmentation fault!
Better luck next time

Note que el valor del cookie mostrado en el ejemplo difiere del suyo. El program RTARGET tendrá un
comportamiento similar. Según se indica en el mensaje de error, al sobrepasar el buffer usualmente se

4
corrompe el estado del programa, produciendo un error de acceso a memoria. Su trabajo es ir un paso m ás
allá con el contenido de las hileras introducidas a CTARGET y RTARGET , de forma que logre hacer cosas
más interesantes y que denominaremos con el nombre de exploits.
Tanto CTARGET como RTARGET reciben varios parámetros por la lı́nea de comandos:

-h: Print list of possible command line arguments


-q: Don’t send results to the grading server
-i FILE: Supply input from a file, rather than from standard input

Sus hileras exploit deberán contener valores de bytes que t ı́picamente no corresponden con valores im-
primibles de la tabla ASCII. El programa HEX 2 RAW será el que facilite la generaci ón de estas hileras que
llamaremos hileras raw. Consulte el anexo A al final de la tarea para m ás indicaciones sobre c ómo usar
HEX 2 RAW .

Puntos importantes:

• Sus hileras exploit no deben contener el valor0x0a en ninguna posición intermedia, por cuanto dicho
caracter representa el cambio de l ı́nea (‘\n’). Cuando Gets encuentra este valor, asumirá que usted
intenta finalizar la hilera.
• HEX 2 RAW espera parejas de valores hexadecimales separadas entre s ı́ por uno o m ás espacios en
blanco. Si usted desea crear un byte con el valor hexadecimal de 0, debe escribirlo como 00. Para
crear la palabra de m áquina 0xdeadbeef deberı́a pasar la hilera “ ef be ad de” a HEX 2 RAW
(note el orden invertido debido el ordenamiento de bytes little-endian).

Cuando usted haya resuelto correctamente uno de los niveles de la tarea, el programa objetivo enviar á una
notificación al servidor de evaluación. Por ejemplo:
unix> ./hex2raw < ctarget.l2.txt | ./ctarget
Cookie: 0x1a7dd803
Type string:Touch2!: You called touch2(0x1a7dd803)
Valid solution for level 2 with target ctarget
PASSED: Sent exploit string to server to be validated.
NICE JOB!

El servidor verificar á su hilera exploit para asegurarse de que realmente funcione como se espera y actu-
alizará la página con el marcador, indicando que su Id de usuario ha completado la fase. Puede consultar la
página con el marcador a través del navegador, ingresando a la dirección:

http://orifaz.ecci.ucr.ac.cr:1221/scoreboard

A diferencia con la tarea de la bomba, en este caso no hay penalizaci ón por los errores durante la tarea, por
lo que puede probar con total libertad los programas CTARGET y RTARGET ingresando las hileras que desee.
La figura 1 resume las cinco fases de la tarea. Las primeras tres contienen ataques de inyecci ón de c ódigo
(CI) usando el programa CTARGET , y las dos últimas son de programación orientada a retorno (ROP) usando
el programa RTARGET . El puntaje obtenido en los exploits ser escalado a los 90 puntos definidos para
calcular la nota final, pues la documentación tiene un valor de 10 puntos.

5
Fase Programa Nivel Método Función Puntaje
1 CTARGET 1 CI touch1 10
2 CTARGET 2 CI touch2 25
3 CTARGET 3 CI touch3 25
4 RTARGET 2 ROP touch2 30
5 RTARGET 3 ROP touch3 10
CI: Code injection
ROP: Return-oriented programming

Figure 1: Resumen de fases de la tarea

4 Parte I: Ataques de Code Injection

En las primeras tres fases, sus hileras exploit serán usadas para atacar el programa CTARGET . Este programa
ha sido creado de forma tal que la ubicaci ón de la pila ser á consistente de una ejecuci ón a la siguiente, de
forma tal que los datos en la pila puedan ser interpretados como c ódigo ejecutable. Dichas caracterı́sticas,
junto a las deficiencias en la funci ón Gets, le hacen vulnerable a ataques cuando las hileras contengan
código ejecutable.

4.1 Fase 1

En la fase 1 no se inyectar á nuevo c ódigo. Por el contrario, la hilera exploit redirigir á el programa para
ejecutar una función ya existente en el programa.
La función getbuf es llamada en CTARGET por medio de la función test que contiene el siguiente código
fuente:

1 void test()
2 {
3 int val;
4 val = getbuf();
5 printf("No exploit. Getbuf returned 0x%x\n", val);
6 }

Cuando getbuf ejecuta su instrucci ón return (lı́nea 5 de getbuf), el programa en condiciones normales
retorna la ejecuci ón a la funci ón test (en la lı́nea 5 de dicha funci ón). Entonces, su objetivo es modificar
este comportamiento. En el archivo ctarget se puede ubicar el c ódigo de la funci ón touch1, según se
muestra a continuaci ón:

1 void touch1()
2 {
3 vlevel = 1; /* Part of validation protocol */
4 printf("Touch1!: You called touch1()\n");
5 validate(1);

6
6 exit(0);
7 }

Su trabajo consiste en lograr que CTARGET ejecute el c ódigo de touch1 cuando getbuf ejecuta la in-
strucción return, en lugar de volver a test. Note que su exploit podrı́a corromper partes de la pila que no
están directamente ligadas con el objetivo de esta fase, pero esto no deber ı́a ser un problema, por cuanto
touch1 hace que el programa finalize apropiadamente.
Sugerencias:

• Toda la información requerida para elaborar el exploit en esta fase puede ser determinada al examinar
el c ódigo desensamblado de su programa CTARGET . Utilice objdump -d para obtener la versi ón
desensamblada.

• La idea general de la soluci ón es colocar apropiadamente la representaci ón binaria de la direcci ón
inicial de la funci ón touch1, de forma tal que la instrucci ón ret al final de la funci ón getbuf le
transfiera el control a touch1.

• Sea cuidadoso/a con el tema del byte ordering (little-endian).

• Puede usar GDB para recorrer el programa a trav és de las instrucciones de getbuf y asegurar que
está realizando el procedimiento correcto.

• La ubicaci ón de buf en el marco de pila de getbuf depende del valor constante en tiempo de
compilación de BUFFER_SIZE, ası́ como de la estrategia de asignaci ón de memoria usada por el
compilador GCC . Usted debe examinar el código desensamblado para determinar la posición correcta
del buffer.

4.2 Fase 2

En la fase dos se debe inyectar una pequeña cantidad de código como parte de su hilera exploit.
En el archivo ctarget se encuentra el código de una función touch2 cuya versión en C es la siguiente:

1 void touch2(unsigned val)


2 {
3 vlevel = 2; /* Part of validation protocol */
4 if (val == cookie) {
5 printf("Touch2!: You called touch2(0x%.8x)\n", val);
6 validate(2);
7 } else {
8 printf("Misfire: You called touch2(0x%.8x)\n", val);
9 fail(2);
10 }
11 exit(0);
12 }

7
Su trabajo es lograr que CTARGET ejecute el c ódigo de touch2 en lugar de retornar a test. Sin em-
bargo, en este caso usted debe lograr que touch2 sea invocada como si le hubiera pasado su cookie como
parámetro.
Sugerencias:

• Usted va a necesitar que se coloque la direcci ón inicial de la representaci ón binaria de su exploit de
forma tal que la instrucci ón ret al final del código de getbuf le transfiera el control.
• Recuerde que el primer parámetro de una función es pasado en el registro %rdi.
• Su código a inyectar deber ı́a asignar el valor de su cookie al registro y usar la instrucci ón ret para
transferir el control a la primera instrucci ón de touch2.
• No intente usar las instrucciones jmp o call en su código exploit. La codificación de las direcciones
destino de estas instrucciones es difı́cil de formular. En cambio, use la instrucción ret para todas las
transferencias de control, a ún cuando usted no está retornando de un call.
• Revise la discusi ón en el anexo B, acerca de c ómo usar las herramientas para generar una repre-
sentación a nivel de bytes de una secuencia de instrucciones.

4.3 Fase 3

La fase 3 también involucra un ataque de inyección de código, pero enviando una hilera como parámetro.
En el archivo ctarget se encuentra el c ódigo de las funciones hexmatch y touch3, cuyas representa-
ciones en C son las siguientes:

1 /* Compare string to hex represention of unsigned value */


2 int hexmatch(unsigned val, char *sval)
3 {
4 char cbuf[110];
5 /* Make position of check string unpredictable */
6 char *s = cbuf + random() % 100;
7 sprintf(s, "%.8x", val);
8 return strncmp(sval, s, 9) == 0;
9 }
10
11 void touch3(char *sval)
12 {
13 vlevel = 3; /* Part of validation protocol */
14 if (hexmatch(cookie, sval)) {
15 printf("Touch3!: You called touch3(\"%s\")\n", sval);
16 validate(3);
17 } else {
18 printf("Misfire: You called touch3(\"%s\")\n", sval);
19 fail(3);
20 }
21 exit(0);
22 }

8
Su trabajo es lograr que CTARGET ejecute el c ódigo de touch3 en lugar de retornar a test. Usted debe
hacer parecer como si a touch3 se le pasara como par ámetro una representaci ón en hilera de texto de su
cookie.
Sugerencias:

• Usted necesitar á incluir una representaci ón de hilera de su cookie como parte del exploit. La hilera
deberı́a estar formada por los ocho dı́gitos hexadecimales (ordenados del menos al mas significativo)
precedidos por un “0x.”

• Recuerde que una hilera en C se representa como una secuencia de bytes seguida por el valor 0. Puede
usar el comando“ man ascii” en una m áquina Linux para obtener la representaci ón de caracteres
que necesita, o alguna otra representaci ón ASCII disponible en Internet.

• Su código a inyectar deberı́a asignar al registro %rdi la dirección de la hilera.

• Cuando las funciones hexmatch y strncmp son llamadas, colocan datos en la pila y sobreescriben
porciones de la memoria que contenı́an el buffer usado por getbuf. Como resultado, usted necesita
definir cuidadosamente dónde colocará la representaci ón en formato de hilera de su cookie.

5 Parte II: Ataques de Return-Oriented Programming

La ejecución de ataques de inyección de código en el programa RTARGET es más compleja que en CTARGET ,
porque utiliza dos técnicas para hacer fracasar los ataques:

• Aleatoriza las posiciones de la pila de una ejecuci ón a la siguiente, haciendo imposible localizar la
posición donde fue inyectado el código.

• Marca secciones de la pila como memoria no ejecutable de forma tal que, si se mueve el contador de
programa hacia una posición ubicada en la pila, el programa fallará con un error de segmentation
fault.

Afortunadamente, algunas personas con buen manejo de la tecnolog ı́a han ideado estrategias para lograr
ejecutar tareas fuera de los planeado, utilizando c ódigo ya existente en el software, en lugar de inyectar
código adicional. La forma m ás general de esta t écnica se conoce con el nombre de return-oriented pro-
gramming (ROP) [1, 2]. La estrategia con ROP es identificar secuencias de bytes en un programa existente
que consisten de una o más instrucciones seguidas por una instrucción ret. Un fragmento de c ódigo como
el mencionado se conoce con el nombre de gadget. La figura 2 muestra c ómo la pila puede ser organizada
para ejecutar una secuencia de n gadgets. En la figura, la pila contiene una secuencia de direcciones de
gadgets. Cada gadget consiste de una serie de bytes correspondiendo a instrucciones codificadas en bytes,
y que finalizan con un 0xc3, que es la codificaci ón de la instrucci ón ret. Cuando el programa ejecuta el
ret inicial de esta configuración, se inicia una cadena de ejecuciones de gadgets, en donde el ret al final
de cada gadget produce un salto al inicio del siguiente.
Un gadget hace uso de c ódigo en lenguaje ensamblador que ha sido generado por un compilador, espe-
cialmente el ubicado en la parte final de las funciones. En la pr áctica, es posible encontrar gadgets muy

9
Stack
Gadget n code c3

Ÿ
Ÿ
Ÿ
Gadget 2 code c3

%rsp
Gadget 1 code c3

Figure 2: Colocaci ón de la secuencia de gadgets para ejecuci ón. El byte 0xc3 codifica la instrucción ret.

útiles de esta forma, pero no suficiente para implementar muchas operaciones importantes. Por ejemplo, es
altamente improbable que una función compilada tendrá popq %rdi como su última instrucción antes del
ret. Afortunadamente, cuando contamos con un conjunto de instrucciones organizados por bytes, como es
el caso de la arquitectura x86-64, es posible encontrar gadgets al extraer patrones a partir de segmentos en
las secuencias de instrucciones.
Por ejemplo, una versión de rtarget contiene el código generado para la siguiente funci ón en C:

void setval_210(unsigned *p)


{
*p = 3347663060U;
}

La posibilidad de que esta funci ón sea útil para atacar un sistema parece bastante baja, pero el c ódigo de
máquina desensamblado correspondiente muestra una secuencia de bytes interesante:

0000000000400f15 <setval_210>:
400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi)
400f1b: c3 retq

La secuencia de bytes 48 89 c7 codifica la instrucci ón movq %rax, %rdi. (Ver figura 3A con cod-
ificaciones de instrucciones movq útiles.) Esta secuencia es sucedida por el valor c3 que codifica una
instrucción ret. La función inicia en la direcci ón 0x400f15, y la secuencia inicia en el cuarto byte de la
función. De esta forma el c ódigo contiene un gadget, que inicia en la direcci ón 0x400f18, que permitir á
copiar el valor de 64 bits del registro %rax hacia el registro %rdi.
Su código del programa RTARGET contiene una cantidad de funciones similares a la función setval_210
mostrada, y están alojadas en la region indicada como gadget farm. Su trabajo será identificar gadgets útiles
en el gadget farm y usarlos para realizar ataques similares a los realizados en las fases 2 y 3
Importante: El gadget farm est á delimitado por las funciones start_farm y end_farm en su copia de
rtarget. No intente construir gadgets a partir de otras porciones de c ódigo del programa.

10
A. Codificación de instrucciones movq

movq S , D
Source Destination D
S %rax %rcx %rdx %rbx %rsp %rbp %rsi %rdi
%rax 48 89 c0 48 89 c1 48 89 c2 48 89 c3 48 89 c4 48 89 c5 48 89 c6 48 89 c7
%rcx 48 89 c8 48 89 c9 48 89 ca 48 89 cb 48 89 cc 48 89 cd 48 89 ce 48 89 cf
%rdx 48 89 d0 48 89 d1 48 89 d2 48 89 d3 48 89 d4 48 89 d5 48 89 d6 48 89 d7
%rbx 48 89 d8 48 89 d9 48 89 da 48 89 db 48 89 dc 48 89 dd 48 89 de 48 89 df
%rsp 48 89 e0 48 89 e1 48 89 e2 48 89 e3 48 89 e4 48 89 e5 48 89 e6 48 89 e7
%rbp 48 89 e8 48 89 e9 48 89 ea 48 89 eb 48 89 ec 48 89 ed 48 89 ee 48 89 ef
%rsi 48 89 f0 48 89 f1 48 89 f2 48 89 f3 48 89 f4 48 89 f5 48 89 f6 48 89 f7
%rdi 48 89 f8 48 89 f9 48 89 fa 48 89 fb 48 89 fc 48 89 fd 48 89 fe 48 89 ff

B. Codificación de instrucciones popq


Operation Register R
%rax %rcx %rdx %rbx %rsp %rbp %rsi %rdi
popq R 58 59 5a 5b 5c 5d 5e 5f

C. Codificación de instrucciones movl


movl S , D
Source Destination D
S %eax %ecx %edx %ebx %esp %ebp %esi %edi
%eax 89 c0 89 c1 89 c2 89 c3 89 c4 89 c5 89 c6 89 c7
%ecx 89 c8 89 c9 89 ca 89 cb 89 cc 89 cd 89 ce 89 cf
%edx 89 d0 89 d1 89 d2 89 d3 89 d4 89 d5 89 d6 89 d7
%ebx 89 d8 89 d9 89 da 89 db 89 dc 89 dd 89 de 89 df
%esp 89 e0 89 e1 89 e2 89 e3 89 e4 89 e5 89 e6 89 e7
%ebp 89 e8 89 e9 89 ea 89 eb 89 ec 89 ed 89 ee 89 ef
%esi 89 f0 89 f1 89 f2 89 f3 89 f4 89 f5 89 f6 89 f7
%edi 89 f8 89 f9 89 fa 89 fb 89 fc 89 fd 89 fe 89 ff

D. Codificación de instrucciones nop funcionales de 2 bytes.


Operation Register R
%al %cl %dl %bl
andb R, R 20 c0 20 c9 20 d2 20 db
orb R, R 08 c0 08 c9 08 d2 08 db
cmpb R, R 38 c0 38 c9 38 d2 38 db
testb R, R 84 c0 84 c9 84 d2 84 db

Figure 3: Codificaciones en bytes de instrucciones. Todos los valores mostrados son hexadecimal.

11
5.1 Fase 4

En la fase 4, usted debe repetir el ataque de la fase 2, pero usando el programaRTARGET y los gadgets de su
gadget farm para implementar el ataque. Usted puede construir su soluci ón usando gadgets que consisten
de los siguientes tipos de instrucciones, y usando solamente los primeros ocho registros del x86-64 (%rax–
%rdi).

movq : Los c ódigos se muestran en la figura 3A.


popq : Los c ódigos se muestran en la figura 3B.
ret : Esta instrucci ón está codificada usando un solo byte 0xc3.
nop : Esta instrucci ón (que se pronuncia “no op,” que es un acr ónimo de “no operation”) est á codificada
usando un solo byte 0x90. Se utiliza solamente para incrementar el contador de programa en 1.

Sugerencias:

• Todos los gadgets que necesita para su soluci ón se encuentran en la regi ón de c ódigo de rtarget
que está delimitada por las funciones start_farm y mid_farm.
• El ataque se puede implementar usando solamente dos gadgets.
• Cuando un gadget utiliza la instrucci ón popq, extraer á datos de la pila. Como resultado, su exploit
será una combinación de direcciones de gadget y datos.

5.2 Fase 5

Antes de iniciar la fase 5 hagamos un recuento del trabajo realizado hasta este momento. En las fases 2
y 3, usted logr ó que un programa ejecutara c ódigo de m áquina de su propio dise ño. Si CTARGET hubiera
sido un servidor de red, usted habrı́a podido inyectar su código en una máquina distante. En la fase 4, usted
sobrepasó dos de los principales controles de seguridad que los sistemas modernos utilizan para frustrar
los ataques de buffer overflow. Aun cuando no inyect ó su propio c ódigo, usted fue capaz de inyectar una
especie de programa que opera dando saltos por secuencias de instrucciones del c ódigo existente.
En la fase 5 se requiere que usted implemente un ataque ROP usando RTARGET para invocar la funci ón
touch3 con un par ámetro que sea un puntero a una representaci ón como hilera de su cookie. Usted
puede usar gadgets en la regi ón de c ódigo de rtarget delimitadas por las funciones start_farm y
end_farm. Adicionalmente a los gadgets usados en la fase 4, el farm incluye codificaciones de diversas
instrucciones movl según se muestran en la figura 3C. Las secuencias de bytes en esta parte del farm
también contienen instrucciones de 2 bytes que sirven como nops funcionales, i.e., que no cambian ning ún
registro o valor de memoria. Esto incluye instrucciones tales como andb %al,%al, que se muestran en
la figura 3D, que operan en los bytes de menor orden de los registros pero no cambian su valor.
Sugerencias:

• Revise el efecto que genera la instrucci ón movl en los 4 bytes superiores de un registro, según se
describe en la página 183 del libro de texto, 3era edición.

12
• La solución oficial requiere ocho gadgets (no todos de los cuales son únicos, por lo cual puede haber
mltiples soluciones).

Buena suerte y divértase!

A Using H EX 2 RAW

H EX 2 RAW takes as input a hex-formatted string. In this format, each byte value is represented by two hex
digits. For example, the string “ 012345” could be entered in hex format as “ 30 31 32 33 34 35
00.” (Recall that the ASCII code for decimal digit x is 0x3x , and that the end of a string is indicated by a
null byte.)
The hex characters you pass to HEX 2 RAW should be separated by whitespace (blanks or newlines). We
recommend separating different parts of your exploit string with newlines while you’re working on it.
HEX 2 RAW supports C-style block comments, so you can mark off sections of your exploit string. For
example:

48 c7 c1 f0 11 40 00 /* mov $0x40011f0,%rcx */

Be sure to leave space around both the starting and ending comment strings (“ /*”, “*/”), so that the
comments will be properly ignored.
If you generate a hex-formatted exploit string in the file exploit.txt, you can apply the raw string to
CTARGET or RTARGET in several different ways:

1. You can set up a series of pipes to pass the string through HEX 2 RAW .

unix> cat exploit.txt | ./hex2raw | ./ctarget

2. You can store the raw string in a file and use I/O redirection:

unix> ./hex2raw < exploit.txt > exploit-raw.txt


unix> ./ctarget < exploit-raw.txt

This approach can also be used when running from within GDB :

unix> gdb ctarget


(gdb) run < exploit-raw.txt

3. You can store the raw string in a file and provide the file name as a command-line argument:

unix> ./hex2raw < exploit.txt > exploit-raw.txt


unix> ./ctarget -i exploit-raw.txt

This approach also can be used when running from within GDB .

13
B Generating Byte Codes
Using GCC as an assembler and OBJDUMP as a disassembler makes it convenient to generate the byte codes
for instruction sequences. For example, suppose you write a file example.s containing the following
assembly code:

# Example of hand-generated assembly code


pushq $0xabcdef # Push value onto stack
addq $17,%rax # Add 17 to %rax
movl %eax,%edx # Copy lower 32 bits to %edx

The code can contain a mixture of instructions and data. Anything to the right of a ‘ #’ character is a
comment.
You can now assemble and disassemble this file:

unix> gcc -c example.s


unix> objdump -d example.o > example.d

The generated file example.d contains the following:

example.o: file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <.text>:
0: 68 ef cd ab 00 pushq $0xabcdef
5: 48 83 c0 11 add $0x11,%rax
9: 89 c2 mov %eax,%edx

The lines at the bottom show the machine code generated from the assembly language instructions. Each
line has a hexadecimal number on the left indicating the instruction’s starting address (starting with 0), while
the hex digits after the ‘ :’ character indicate the byte codes for the instruction. Thus, we can see that the
instruction push $0xABCDEF has hex-formatted byte code 68 ef cd ab 00.
From this file, you can get the byte sequence for the code:

68 ef cd ab 00 48 83 c0 11 89 c2

This string can then be passed through HEX 2 RAW to generate an input string for the target programs.. Alter-
natively, you can edit example.d to omit extraneous values and to contain C-style comments for readability,
yielding:

14
68 ef cd ab 00 /* pushq $0xabcdef */
48 83 c0 11 /* add $0x11,%rax */
89 c2 /* mov %eax,%edx */

This is also a valid input you can pass through HEX 2 RAW before sending to one of the target programs.

References

[1] R. Roemer, E. Buchanan, H. Shacham, and S. Savage. Return-oriented programming: Systems, lan-
guages, and applications. ACM Transactions on Information System Security, 15(1):2:1–2:34, March
2012.

[2] E. J. Schwartz, T. Avgerinos, and D. Brumley. Q: Exploit hardening made easy. In USENIX Security
Symposium, 2011.

15

Vous aimerez peut-être aussi