# Assembly (x86)

### Assembly vs Assembler

Antes de começarmos vamos esclarecer um ponto, a diferença entre Assembly e Assembler.

O **Assembly** é uma linguagem de programação que irá ser escrito de uma forma que seja entendível por humanos e, então, será convertido para linguagem de máquina através do Assembler. Esses arquivos desenvolvidos em Assembly irá conter a extensão `.asm`.

Já o **Assembler** tem um papel diferente, pois este converte código desenvolvido em linguagem Assembly para linguagem de máquina. Após utilizamos o Assembler, irá ser gerado um `Object File`, que é uma representação binária do programa. Feito, será preciso utilizar um `linker` para combinar (juntar) os arquivos necessários para gerar o executável final (isso é necesário quando temos chamadas externas, por exemplo, de arquivos `.dll` situadas na `system32`).

### Compilando em Assembly

Primeiro precisamos escrever um código `asm` (Assembly), transformar em arquivo `obj` (linguagem de máquina) e por último fazer um `linker` (arquivo exe), para associar o código com as bibliotecas, como por exemplo, o arquivo User32.dll, presente na system32.

```bash
nasm -f win32 <file.asm> -o <file.obj>
golink /entry _main <file.obj>
```

Caso utilize algum recurso, como por exemplo o `sleep`  (que utiliza Kernel32.dll) iremos ter que adicionar a algumas informações a mais no comando.

```bash
nasm -f win32 <file.asm> -o <file.obj>
golink /console /entry _main <file.obj> Kernel32.dll
```

### Registradores

Os processadores têm seu próprio conjunto de variáveis especiais chamadas `Registradores`. A maioria das instruções usam esses Registros para ler ou gravar dados, portanto é essencial entender os Registradores de um processador para então entender as `Instruções` (mais detalhes logo abaixo).

| **REGISTRADOR** | **DESCRIÇÃO**                                                                                                                                                                                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EAX`           | Utilizado em operações aritméticas e guardar resultados. É o registrador acumulador                                                                                                                                                                                                    |
| `EBX`           | É um Registrador secundário, usado como "base" em operações de vetores                                                                                                                                                                                                                 |
| `ECX`           | Contador utilizado em Loops                                                                                                                                                                                                                                                            |
| `EDX`           | Guarda endereço de dados                                                                                                                                                                                                                                                               |
| `ESP`           | Este fica sempre no topo da Stack e é conhecido como **`Stack Pointer`**, é chamado Ponteiro porque armazenam endereços de 32 bits, que apontam essencialmente para esse local na memória. Esse registro é bastante importante para a execução de programas e gerenciamento de memória |
| `EBP`           | Conhecido como **`Base Pointer`** e assim como o ESP, este também é chamado Ponteiro porque armazenam endereços de 32 bits                                                                                                                                                             |
| `ESI`           | Conhecido como **`Source Index`**, tecnicamente também é um Ponteiro que é comumente utilizado para apontar para a origem e o destino quando os dados precisam ser lidos ou gravados                                                                                                   |
| `EDI`           | Conhecido como **`Destination Index`**, tecnicamente também é um Ponteiro, pois trabalha de forma semelhante ao ESI.                                                                                                                                                                   |
| `EIP`           | **`Instruction Pointer`** (Program Counter), indica em qual instrução do código a execução se encontra no momento                                                                                                                                                                      |
| `EFLAGS`        | Guarda resultado de operações, por exemplo, condições feita em um `if`, onde o resultado dessa condição não é armazenada em nenhuma variável                                                                                                                                           |

Ao realizarmos um Disassembler, podemos ver os Registradores divididos em partes, ou seja, utilizando somente uma parte dele. Isso é feito por questões de performance do software. Podemos utilizar como exemplo, o Registrador `rax` (64 bits), que pode tem uma parte chamada `eax` (32 bits), que tem uma parte chamada `ax` (16 bits), que tem duas partes chamadas de `ah` (8 bits - memória alta) e `al` (8 bits - memória baixa).

### Diferenças Entre Intel e AT\&T

#### Ordem dos Parâmetros

Quando utilizamos o `mov`, para mover algo, temos uma pequena e importante diferença nessas sintaxes. No exemplo abaixo, ambos os casos `ebp` irá receber o valor de `esp`, porém note que eles estão escritos em ordem diferente:

```bash
# Intel
mov     ebp,esp

# AT&T
mov     %esp,%ebp
```

#### Tamanho dos Parâmetros

Na Intel, o Assembler identifica o tamanho do registrador que foi utilizado, já na AT\&T podemos ver sufixos que indicam o tamanho dos operandos (note que é um `pushl` e não `push`).

```bash
# Intel
push    DWORD PTR [ecx-0x4]

# AT&T
pushl   -0x4(%ecx)
```

#### Valores Imediatos

Estes, são valores que não estão armazenadas em variáveis. Podemos usar um exemplo de Valor Imediato no seguinte trecho, onde a string está sendo definida sem passar por uma variável:

```bash
printf('Mysther');
```

Na Intel, o Assembler identiica o tipo automaticamente, enquanto na AT\&T possui um `$` como prefixo, enquanto os registradores possuem um `%`.&#x20;

```bash
# Intel
sub     esp,0x10

# AT&T
sub     $0x10,%esp
```

###

### Instruções

#### Movimentos

Antes de vermos as Instruções de fato, vamos entender quais são essas movimentação de dados.

| MOVIMENTO                                            | DESCRIÇÃO                                                               |
| ---------------------------------------------------- | ----------------------------------------------------------------------- |
| `Imediato para Registrador`                          | Acontece quando setamos o valor de uma variável, exemplo: `x = 10;`     |
| `Registrador para Registrador`                       | Quando passamos o valor de `eax` para `ebx`                             |
| `Imediato para Memória`                              | Quando defimos que vamos escrever em determinada posição da Memória RAM |
| `Registrador para Memória / Memória para Regitrador` | Quando movemos um valor da Registrador para a Memória RAM               |

#### Tipos de Instruções

Agora podemos ver e entender melhor sobre as instruções.

| **INSTRUÇÃO** | **EXEMPLO**                                                               | **DESCRIÇÃO**                                                                                                                    |
| ------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `NOP`         | `NOP`                                                                     | No Operation (\x90), o processador não faz nada. Útil pra utilizar antes da chamada de shellcode                                 |
| `INT3`        |                                                                           | Interrupção (Breakpoint)                                                                                                         |
| `MOV`         | <p><code>mov ecx,eax</code></p><p></p><p><code>mov eax, \[esp]</code></p> | Define o valor de `ecx` com o mesmo valor de `eax`. No segundo exemplo, joga valor (e não o endereço de memória) de ESP para EAX |
| `ADD`         | `add eax,0x10`                                                            | Incrementa um valor (imediato) hexadecimal de 10 em `eax`                                                                        |
| `SUB`         | `sub eax,0x10`                                                            | Subtrai 0x10 de `eax` e armazena o valor em `eax`                                                                                |
| `XOR`         | <p><code>xor eax,ebx</code></p><p></p><p><code>xor eax,eax</code></p>     | Faz o `xor` entre `eax` e `ebx` e joga o valor em `eax`. No segundo exemplo, teremos `eax` com o valor zerado                    |
| `AND`         | `and eax,ebx`                                                             | Faz um `and` entre `eax` e `ebx` e joga o valor em `eax`                                                                         |
| `CMP`         | `cmp eax,ebx`                                                             | Compara `eax` e `ebx` e seta flags                                                                                               |
| `JE`          | `je 0x40084`                                                              | Jump Equal = Pula para o endereço informado se a `eflag` estiver setado como igual na instrução `cmp`                            |
| `JNE`         | `jne 0x40084`                                                             | Jump Not Equal = Semelhante ao `JE`, porém este irá mudar de endereço caso a instrução `cmp` não seja igual                      |
| `JMP`         | `jmp 0x40084`                                                             | Jump = Pula para o endereço informado, independente de condições em `CMP`                                                        |
| `CALL`        | `call 0x40084`                                                            | Pula para o endereco definido e salva a sua localização atual                                                                    |
| `RET`         | `ret`                                                                     | Retorna para o endereço salvo com a instrução `call`                                                                             |
| `LEA`         | `lea eax,[esp+0x1c]`                                                      | Semelhante ao `mov`, porém ao invés de mover o valor, esse move o endereço de um registrador para outro                          |
| `PUSH`        | `PUSH 41424344`                                                           | Coloca no topo da Stack                                                                                                          |
| `POP`         | `POP EBX`                                                                 | Remove do topo da stack e joga o valor para EBX                                                                                  |

### Compilando

Primeiro precisamos escrever um código `asm` (Assembly), transformar em arquivo `obj` (linguagem de máquina) e por último fazer um `linker` para gerar o arquivo exe e associar o código as devidas bibliotecas, como por exemplo, o arquivo `User32.dll`, presente no `system32`.

```bash
nasm -f win32 <file.asm> -o <file.obj>
golink /entry _main code.obj
```

No exemplo acima não utilizamos nenhuma biblioteca externa. No exemplo abaixo, estamos compilando um código que utiliza o Sleep, presente em Kernel32.dll, então o comando ficaria da seguinte forma.

```bash
nasm -f win32 <file.asm> -o <file.obj>
golink /console /entry _main <file.obj> Kernel32.dll
```

### Permissões

Antes de começarmos, é sempre bom verificar as permissões que o binário possui

```bash
checksec <file>
```

### Disassemble

#### Objdump

Por padrão, será utilizado o AT\&T.

```bash
# AT&T
objdump -D <file>

# Intel
objdump -D -M intel <file>
```

Outra maneira

```bash
objdump -D Minte-l,i386 b binary -m i386 <file>
readelf -h <file>
```

#### arwin

Busca pelo endereço de memória que está sendo utilizado para chamar determinada DLL.

```bash
arwin <file.dll> <binary>
```

#### Sites

```bash
https://wiki.osdev.org/Calling_Conventions

# Ferramenta para monitorar as API's do Windows que estão em uso
http://www.rohitab.com/
```
