Cool 3 assembly para linux

34
Oficina Assembly para Linux Por Luiz Vieira @HackProofing

description

Presented in BSIDES Conf COOL in Garoa Hacker Clube

Transcript of Cool 3 assembly para linux

Page 1: Cool 3   assembly para linux

Oficina

Assembly para Linux

Por Luiz Vieira

@HackProofing

Page 2: Cool 3   assembly para linux

Quem sou eu?

Page 3: Cool 3   assembly para linux
Page 4: Cool 3   assembly para linux

Organização do Sistema

I/O Memória Barramentos

Execução Controle

Registradores

Flags

CPU

Page 5: Cool 3   assembly para linux

Registradores

• Uso geral: – EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP

• Segmento: – CS, DS, ES, SS, FS, GS

• Instrução: – EIP

• Controle: – CR0, CR1, CR2, CR3, CR4

Page 6: Cool 3   assembly para linux

Registradores

• EAX = Extended Acumullator (registrador acumulador extendido)

• EBX = Extended Base (registrador de base extendido)

• ECX = Extended Couter (registrador contador extendido)

• EDX = Extended Data (registrador de dados extendido)

• ESI = Extended Source Index (registrador de índice de origem extendido)

• EDI = Extended Destination Index (registrador de índice de destino extendido)

• Em adição aos registradores de uso geral, temos os registradores especiais, que são: – EBP = Extended Base Pointer (Ponteiro de Base)

– ESP = Extended Stack Pointer (Ponteiro de Stack/Pilha)

– EIP = Extended Instruction Pointer (Ponteiro de Instrução)

– EFLAGS

Page 7: Cool 3   assembly para linux

Registradores

• Uma coisa que precisamos ter sempre em mente, é que tanto como o EIP quanto o EFLAGS, só poderão ser acessados através de instruções especiais e bem específicas, diferente dos demais registradores.

• O EBP sempre aponta para a base da pilha, e também é utilizado para acessar essa mesma pilha, apesar de também poder ser utilizado como um registrador comum (de uso geral). Já o ESP, aponta para a posição atual da stack (pilha) e é o 'offset' do SS (Stack Segment).

Page 8: Cool 3   assembly para linux

Organização de um registrador

para uso geral

EAX

AX

AH AL

0

0

0

31

31 16 15

15 8 7

•EAX armazenaria, por exemplo, um valor fictício de 0x00000000.

•AX, que é a parte alta de EAX, armazenaria 0x0000.

•AH, é a parte alta de AX, enquanto AL é a parte baixa de AX (ambos são

de arquitetura 8bits), e armazenam apenas 0x00 cada um.

Page 9: Cool 3   assembly para linux

AT&T x Intel

• Intel =

• AT&T =

Page 10: Cool 3   assembly para linux

AT&T x Intel

• Na sintaxe Intel, uma instrução comum ficaria assim: – instrução destino, origem

• Em AT&T é: – instrução origem, destino

• Uma questão importante de se lembrar, é que na sintaxe AT&T, todos os registradores devem ser prefixados pelo símbolo %, enquanto que o valores literais, pelo símbolo $. Portanto, 100 é diferente de $100, onde o primeiro é um endereço de memória, e o segundo é um valor numeral.

• Outro símbolo importante, é o '$0x' utilizado para referenciar hexadecimais.

Page 11: Cool 3   assembly para linux

Primeiro programa

#OBJETIVO: Programa simples que executa um exit e retorna um código de status para o kernel Linux

#ENTRADA: nenhuma

#OUTPUT: retorna um status código de status, que pode ser visto executando no terminal o comando:

# echo $?

# após a execução do programa

#VARIÁVEIS:

# %eax armazena o número da syscall

# %ebx armazena o status retornado

.section .data

.section .text

.globl _start

_start:

movl $1, %eax # esta é a syscall do kernel Linux para sair de um programa

movl $0, %ebx # este é o status que retornaremos para o SO. # altere esse valor, e verá coisas diferentes ao executar

# echo $?

int $0x80 # isso chama o kernel para executar a syscall 1

Page 12: Cool 3   assembly para linux

Execução

• Salve este código como 'exemplo1.s', compile e

linkedite-o:

# as exemplo1.s -o exemplo1.o

# ld exemplo1.o -o exemplo1

Após este processo, para executar nosso

primeiro programa, basta digitar no terminal:

# ./exemplo1

Page 13: Cool 3   assembly para linux

Explicação

• .section .data = cria a seção "data", onde listamos quaisquer containers de memória.

• .section .text = seção onde inserimos as instruções a serem executadas.

• .globl _start = '.globl' é uma instrução que diz que o símbolo '_start' não deve ser descartado após a compilação e linkedição do código.

• _start: = é onde definimos o valor do label '_start', que terá vinculado à si, o conjunto de instruções que seguem logo abaixo.

• movl $1, %eax = aqui temos a instrução 'movl', seguido de dois operadores. Nesse caso, inserimos o valor 1 no registrador EAX. Esse número é o valor de uma syscall específica (exit - para conhecer os valores das demais 'syscall', execute o comando "cat /usr/include/asm-i386/unistd.h" no terminal Linux*).

• movl $0, %ebx = inserimos o valor "0" no registrador EBX. Isso é o que dirá para o kernel que está tudo ok para o 'exit' ser executado.

• int $0x80 = 'int' é o mesmo que 'interrupt'. Uma interrupção corta o fluxo de funcionamento de um programa e passa o comando para o Linux, o que em nosso caso, fará com que o kernel execute a 'syscall 1 '(exit). E o valor '$0x80' é o número de interrupção utilizado para que essa passagem de controle para o Linux aconteça.

* No Ubuntu, o arquivo está em: /usr/include/asm/unistd.h

Page 14: Cool 3   assembly para linux

Segundo programa

.data

HelloWorldString:

.ascii "Hello World\n"

.text

.globl _start

_start:

movl $4, %eax # syscall write()*

movl $1, %ebx # parâmetro da syscall para definir STDOUT (fd)

movl $HelloWorldString, %ecx # local da mem. onde se encontra o container com a string (Buf)

movl $12, %edx # tamanho da string (count)

int $0x80

movl $1, %eax # syscall exit()

movl $0, %ebx

int $0x80

* Syscall write() = ssize_t write(int fd, const void *Buf, size_t count);

Page 15: Cool 3   assembly para linux

Passagem de syscalls e

argumentos

• De que maneira podemos passar os valores de syscall e seus argumentos?

– EAX – número da system call

– EBX – primeiro argumento

– ECX – segundo argumento

– EDX – terceiro argumento

– ESI – quarto argumento

– EDI – quinto argumento

Page 16: Cool 3   assembly para linux

Execução

• Salve este código como 'exemplo2.s', compile e

linkedite-o:

# as exemplo2.s -o exemplo2.o

# ld exemplo2.o -o exemplo2

Após este processo, para executar nosso

primeiro programa, basta digitar no terminal:

# ./exemplo2

Page 17: Cool 3   assembly para linux

Tipos de dados

• Espaço reservado em tempo de compilação (em .data): – .byte = 1 byte

– .ascii = string

– .asciz = string terminada em null

– .int = integer de 32 bits

– .short = integer de 16 bits

– .float = número single com ponto flutuante

– .double = número double com ponto flutuante

• Espaço criado em tempo de execução (em .bss): – .comm = declara área comum da memória

– .lcomm = declara área local comum da memória

Page 18: Cool 3   assembly para linux

Terceiro programa .data

HelloWorld:

.ascii "Hello World!"

ByteLocation:

.byte 10

Int32:

.int 2

Int16:

.short 3

Float:

.float 10.23

IntegerArray:

.int 10,20,30,40,50

.bss

.comm LargeBuffer, 10000

.text

.globl _start

_start:

nop

movl $1, %eax

movl $0, %ebx

int $0x80

Page 19: Cool 3   assembly para linux

Execução

• Salve este código como 'exemplo3.s', compile e linkedite-o: # as –gstabs exemplo3.s -o exemplo3.o # ld exemplo3.o -o exemplo3 Após este processo, para executar nosso primeiro programa, basta digitar no terminal: # ./exemplo3

• # gdb ./exemplo3

Page 20: Cool 3   assembly para linux

Execução

• (gdb) list

• (gdb) break *_start+1

• (gdb) run

• (gdb) info variables

• (gdb) help x

• (gdb) x/12cb [endereço de HelloWorld]

• (gdb) x/1db [endereço de ByteLocation]

• (gdb) x/1dw [endereço de Int32]

• (gdb) x/1dh [endereço de Int16]

• (gdb) x/1fw [endereço de Float]

• (gdb) x/5dw [endereço de IntegerArray]

• (gdb) x/10db [endereço de LargeBuffer]

• (gdb) x/100db [endereço de LargeBuffer]

Page 21: Cool 3   assembly para linux

MOVx

• É uma das instruções mais utilizadas em Assembly

• Sua utilização é basicamente a seguinte: – movx origem, destino

– movl movimenta valores de 32bits

movl %eax,%ebx

– movw movimenta valores de 16bits

movl %ax,%bx

– movb movimenta valores de 8bits

movl %ah,%bh

Page 22: Cool 3   assembly para linux

Movendo dados

• Entre registradores:

movl %eax, %ebx

• Entre registradores e memória:

local:

.int 10

movl %eax, local

movl local, %ebx

Page 23: Cool 3   assembly para linux

Movendo dados

• Valor direto no registrador:

movl $10, %ebx

• Valor direto na memória:

local:

.byte 0

movl $10, local

Page 24: Cool 3   assembly para linux

Movendo dados

• Em um endereço indexado da memória:

IntegerArray:

.int 10, 20, 30, 40, 50

• Para selecionar o 3º valor da integer (30)

– BaseAddres(offset, index, size) =

– IntegerArray(0, 2, 4)

movl %eax, IntegerArray(0, 2, 4)

Page 25: Cool 3   assembly para linux

Quarto programa .section .data

string: .string "Digite algo:\n"

tam: .long . - string

.section .text

.globl _start

_start:

movl $4, %eax # insere o valor 4, para a chamada da syscall write no EAX

movl $1, %ebx # passa o parâmetro da syscall 4 para que algo seja exibido

leal string, %ecx # carrega o endereço de memória do ECX e exibe o conteúdo de string

movl tam, %edx # armazena o valor de tam no EDX

int $0x80

movl %esp, %ecx # Salva o Stack Pointer em %ecx

subl $10, %esp # Reserva 10 bytes para o usuario digitar no stack

movl $3, %eax # insere o valor da syscall read (3) no EAX

movl $9, %edx # Tamanho do que vai ser lido para EDX

int $0x80

movl %eax, %edx # Move o que foi digitado para EDX.

movl $4, %eax # syscall write

movl $1, %ebx

int $0x80

movl $0x1, %eax

movl $0x0, %ebx

int $0x80

Page 26: Cool 3   assembly para linux

Execução

• Salve como 'leia.s'.

• Compile, linkedite e execute:

# as leia.s -o leia.o

# lf leia.o -o leia

# ./leia

Page 27: Cool 3   assembly para linux

Quinto programa .section .data

string1: .string "Criar um arquivo e inserir conteúdo \n"

tam1: .long . - string1

string2: .string “Viva o Linux\n"

tam2: .long . - string2

arq: .string "/tmp/arquivo.txt"

.section .text

.globl _start

_start:

movl $4, %eax # syscall write

movl $1, %ebx

leal string1, %ecx

movl tam1, %edx

int $0x80

movl $5, %eax # syscall open (5)

movl $arq, %ebx # arquivo que será aberto

movl $03101, %ecx # modo do arquivo

movl $0, %edx # Permissão 0

int $0x80

Page 28: Cool 3   assembly para linux

Quinto programa

movl %eax, %esi # Move o retorno da funcao open para ESI

movl $4, %eax # syscall write, para efetuar a escrita no arquivo

movl %esi, %ebx # local de escrita, arquivo.txt

leal string2, %ecx # escrita do conteúdo de string2 para dentro do arquivo

movl tam2, %edx # O tamanho da variavel

int $0x80

movl $6, %eax # syscall close (6)

movl %esi, %ebx # Fecha o arquivo

int $0x80

movl $1, %eax

movl $0, %ebx

int $0x80

Page 29: Cool 3   assembly para linux

Execução

• Salve como ‘escreva.s'.

• Compile, linkedite e execute:

# as escreva.s -o escreva.o

# lf escreva.o -o escreva

# ./escreva

Page 30: Cool 3   assembly para linux

Comparação – Sexto programa .section .data

data_items: .long 3,67,34,222,45,75,54,34,44,33,22,11,66,0

.section .text

.globl _start

_start: movl $0, %edi # insere 0 no registrador índice movl data_items(,%edi,4), %eax # carrega o primeiro byte de dados movl %eax, %ebx # como este é o primeiro item, %eax é o maior start_loop: cmpl $0, %eax # verifica se alcançamos o final je loop_exit incl %edi # carrega o próximo valor movl data_items(,%edi,4), %eax cmpl %ebx, %eax # compara valores jle start_loop # pula para o loop se o novo valor não for o maior movl %eax, %ebx # grava o valor como o maior jmp start_loop # pula para o início do loop loop_exit: # %ebx é o código de status para a syscall exit # e já possui o valor mais alto movl $1, %eax

int $0x80

Page 31: Cool 3   assembly para linux

Execução

• Salve como ‘maximo.s'.

• Compile, linkedite e execute:

# as maximo.s -o maximo.o

# lf maximo.o -o maximo

# ./maximo

# echo $?

Page 32: Cool 3   assembly para linux

Condicionais • je

– Pula (Jump) se os valores são iguais

• jg – Pula se o segundo valor for maior que o primeiro

• jge – Pula se o segundo valor for maior ou igual ao primeiro

• jl – Pula se o segundo valor for menor que o primeiro

• jle – Pula se o segundo valor for menor ou igual ao primeiro

• jmp – Pula não importa o resultado da comparação (se houver uma). Esse Jump não

precisa ser precedido por uma comparação

• OBS: uma condicional normalmente é precedida por um cmpl (comparando dois valores):

cmpl $0, %eax je loop_exit

Page 33: Cool 3   assembly para linux