03 - De todo un poco (para poder hacer el lab02)

En linux, los archivos ELF se utilizan para los object files y los ejecutables

Vamos a usar el siguiente ejemplo para ilustrar el proceso.

main.c:

#include <stdio.h>

#define MYCONST 15
// The function prototype of foo, which
// will be implemented elsewhere
int foo(char *input);

static int i = 100;

int aGlobal = 10;
long long int anotherGlobal = 20;

int main(void) {
    int a = MYCONST;
    int b = 6;
    int c = 7;
    int d = (a + b)*4 + c;
    int ret = d + foo("Hello") + foo("World");
    return ret;
}

foo.c:

#include <stdio.h>

static int i = 100;

/* Declared as extern since defined in hello.c */
extern int aGlobal;

int foo(char *input) {
    printf("In foo: %s\n", input);
    return aGlobal;
}

Dentro de los object files y los ejecutables están representados (entre muchas otras cosas) las instrucciones del programa, los datos que usa el programa (los valores de las variables globales, los literales, etc) y los nombres símbolos del programa (e.g. nombres de las funciones, nombre de las variables globales)

El loader

Cuando mandamos a correr un ejecutable, el shell de linux invoca a una función del sistema operativo llamada loader que copia el código y datos del ejecutable a memoria y transfiere el control al starting point del programa. En linux, las partes del proceso (como se llama a una instancia del programa en memoria) tienden a organizarse así:

Algo que aprenderás en el lab es que las direcciones adonde se copian cada uno de los segmentos del proceso varían de ejecución en ejecución pues se utilizan técnicas como PIE (Position Indendent Executable) y ASLR (Address Space Layout Randomization). Esto para no estar expuestos a vulnerabilidades como las que aprovechan los buffer-overflow y otros ataques.

Curiosidad: gdb desactiva el ASLR por default (al proceso que estás haciendo debugging). Si deseas activar el ASLR debes usar:

set disable-randomization off

Interrupts

A request for the processor to interrupt currently executing code (when permitted), so that the event can be processed in a timely manner. If the request is accepted, the processor will suspend its current activities, save its state, and execute a function called an interrupt handler (or an interrupt service routine, ISR) to deal with the event. This interruption is often temporary, allowing the software to resume[a] normal activities after the interrupt handler finishes, although the interrupt could instead indicate a fatal error. [Wikipedia]

Los interrupts puedes ser causados por eventos del hardware o instrucciones en assembly que explicitamente causan el interrupt.

¿Por qué son importantes (para este lab)?

Porque en 32-bits la forma más común de llamar a los system functions de linux desde assembly es usando INT 0x80

En 64-bit x86-64 instrucción en assembly es: syscall, un mecanismo que permite que el programa solicite servicios del kernel (que es donde viven las system functions como read, write, open, close, execve, mmap, etc..)

Cómo se especifican cuál de las system functions se desea invocar

A través de los registros. En esta página puedes ver los valores que debemos dar a los registros para invocar diferentes funciones del sistema operativo en 64 y 32 bits.

Invocando las funciones de sistema desde assembly

(Tomado de https://gist.github.com/yellowbyte/d91da3c3b0bc3ee6d1d1ac5327b1b4b2)

32-bit ELF binary

to assemble and link:

nasm -f elf32 -o <filename>.o <filename>.asm
ld -m elf_i386 -o <filename> <filename>.o

template code (hello world):

; Prints Hello World and exits honorably
section .text
global _start

_start:
    mov ebx, 0x1
    mov ecx, hello
    mov edx, helloLen
    mov eax, 0x4
    int 0x80

    xor ebx, ebx
    mov eax, 0x1
    int 0x80

section .data
    hello db "Hello World", 0xa
    helloLen equ $-hello

64-bit ELF binary

To assemble and link:

nasm -f elf64 -o <filename>.o <filename>.asm
ld -o <filename> <filename>.o

template code (hello world):

; Prints Hello World and exits honorably
section .text
global _start

_start:
    mov rdi, 0x1
    mov rsi, hello
    mov rdx, helloLen
    mov rax, 0x1
    syscall

    xor rdi, rdi
    mov rax, 0x3c
    syscall

section .data
    hello db "Hello World", 0xa
    helloLen equ $-hello