GitBook: [master] 2 pages and 4 assets modified

This commit is contained in:
CPol 2021-10-06 22:07:38 +00:00 committed by gitbook-bot
parent 5cdfdadfe8
commit d8255eaa8b
No known key found for this signature in database
GPG Key ID: 07D2180C7B12D0FF
6 changed files with 91 additions and 75 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -352,120 +352,135 @@ Este tipo de overflows no busca lograr escribir algo en el proceso del programa,
No se sabe el valor que puede tomar una variable no inicializada y podría ser interesante observarlo. Puede ser que tome el valor que tomaba una variable de la función anterior y esta sea controlada por el atacante.
## **6.Explotando format strings**
## **Format Strings**
Cuando se llama a printf se ponen los parámetros de forma ordenada.
In C **`printf`** is function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
%08x —> 8 bytes hexadecimales
%d —> Entero
%u —> Entero sin signo
%s —> Cadena
%n —> Bytes escritos
%hn —> Ocupa 2 bytes en vez de 4
<n>$X —> Parámetro de acceso directo —> \(“%3$d”, var1, var2, var3\) —> Accede directamente a var3
The vulnerability appears when an **attacker text is put as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to **write any data in any address**. Being able this way to **execute arbitrary code**.
AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
AAAA.%4\$x —> 4º parametro
AAAA%.6000x%4\$n —> Se escribe 6004 en la dirección que apunta el 4º parametro
AAAA%6000d%4\$n —> Se escribe 6004 en la dirección que apunta el 4º parametro
AAAA.%500\$08x —> Parámetro en el offset 500
Fomatters:
**objdump -t ./exec \| grep varBss
objdump -TR ./exec \| grep exit\(func lib\)
objdump -d ./exec \| grep funcCode
objdump -D ./exec \| grep "VAR\_NAME"** --> Direccion de memoria donde se carga una variable stática \(en la region DATA\)
```bash
%08x —> 8 hex bytes
%d —> Entire
%u —> Unsigned
%s —> String
%n —> Number of written bytes
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
```
Con %n escribimos el número bytes escritos y normalmente podremos controlar dónde, si por ejemplo queremos escribir el valor 400 en una dirección que es el 8º parámetro:
**`%n`** **writes** the **number of written bytes** in the **indicated address. Writing** as much **bytes** as the hex number we **need** to write is how you can **write any data**.
python -c print “DIRECCION” %.396d%8\$n
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
```
#### **DTOR**
### **GOT \(Global Offsets Table\) / PLT \(**Procedure Linkage Table\)
Los destructores son funciones que se ejecutan justo antes de la finalización de un programa.
This is the table that contains the **address** to the **external functions** used by the program.
**objdump -s -j .dtors /exec
rabin -s /exec \| grep “\_\_DTOR”**
Get the address to this table with: **`objdump -s -j .got ./exec`**
Si se logra escribir algo en \_\_DTOR\_END\_\_ la dirección de una shellcode, esta se ejecutará a la salida del programa.
![](../../.gitbook/assets/image%20%28619%29.png)
Los DTOR se encuentran entre los valores ffffffff y 00000000, por lo que si no hay ningún DTOR encontraremos al ejecutar el **objdump** esos valores seguidos. Entonces, si introducimos una valor entre ambos, será tomado como lla dirección de una función y se ejecutará \(es decir, hay que sobreescribir el 00000000\).
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xDIR_GOT`
Es raro que hoy en día un binario tenga DTORs.
![](../../.gitbook/assets/image%20%28620%29.png)
#### **GOT \(Tabla de offsets global\) - Mejor esta que la anterior si se puede elegir**
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
Contiene las direcciones absolutas de las funciones que son utilizadas en un programa.
![](../../.gitbook/assets/image%20%28622%29.png)
**objdump -s -j .got ./exec
\(peda\)&gt; x/20x 0xDIR\_GOT** --&gt; Se ve una lista con las direcciones de las funciones
**\(peda\)&gt; x/i 0xDIR\_FUNC\_GOT** --&gt; Veríamos el inicio de una función \(probablemente un push ebp\)
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this exploit is to **override the GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function**. Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** \(so you will be able to control the parameters sent to the system function\).
or using GEF you can start a debugging session and execute `got` to see the got table.
If **`system`** **isn't used** by the script, the system function **won't** have an entry in the GOT. In this scenario, you will **need to leak first the address** of the `system` function.
You can see the PLT addresses with `objdump -j .plt -d ./vuln_binary`
**Procedure Linkage Table** is a **read only** table in ELF file that stores all necessary **symbols that need a resolution**. When one of these functions are called the **GOT** will **redirect** the **flow** to the **PLT** so it can **resolve** the **address** of the function and write it on the GOT.
Then, the **next time** a call is performed to that address the **function** is **called directly** without needing to resolve it.
In a binary the GOT has the addresses of the functions \(pointing to the PLT\). The goal of this exploit is to override the GOT entry of a function that is going to be executed later with the address of the PLT of the system function. Ideally, you will override the GOT of a function that is going to be called with parameters controlled by you \(so you will be able to control the parameters sent to the system function\).
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
If system isn't used by the script, the system function won't have an entry in the PLT. In this scenario, you will need to leak first the address of the system function.
### **Exploit Flow**
You an find a **template** to exploit the GOT using format-strings here:
As explained before the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Ideally we could set the **address to a shellcode** located in a executable section, but highly probable you won't be able to write a shellcode in a executable section.
So a different option is to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.
{% page-ref page="format-strings-template.md" %}
To write the address, usually 2 steps are done: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
#### **Exploit \(format strings\)**
**HOB** is called to the 2 higher bytes of the address
**LOB** is called to the 2 lower bytes of the address
Si modificamos el valor de la dirección de una de estas funciones y apuntamos a una shellcode y esta función se ejecuta después del printf tendremos un exploit.
So, because of how format string works you need to **write first the smallest** of \[HOB, LOB\] and then the other one.
Para escribir la dirección de una shellcode normalmente hay que escribirla en dos pasos, primero 2 bytes y luego los otros 2, para ello se usa $hn.
If HOB &lt; LOB
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
HOB —&gt; 2bytes superiores de la dirección de la shellcode
LOB —&gt; 2bytes inferiores de la dirección de la shellcode
Hay que escribir siempre primero el menor de \[HOB, LOB\] y luego el otro.
Si HOB &lt; LOB
\[dirección+2\]\[direccion\]%.\[HOB-8\]x%\[offset\]\$hn%.\[LOB-HOB\]x%\[offset+1\]
Si HOB &gt; LOB
\[dirección+2\]\[direccion\]%.\[LOB-8\]x%\[offset+1\]\$hn%.\[HOB-LOB\]x%\[offset\]
If HOB &gt; LOB
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB\_shellcode-8 NºParam\_dir\_HOB LOB\_shell-HOB\_shell NºParam\_dir\_LOB
\`python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'\`
#### **Format Strings como Buffer Overflows**
### **Format String Exploit Template**
La función **sprintf** copia a un string \(char \*str\) lo mismo que se le pasaría a una función printf. Es decir, si no tiene en cuenta el formato \(“%s”\), y el string introducido es dominado por el atacante, se puede introducir una cadena como %.44xAAAA —&gt; Que hará escribir 44bytes +”AAAA” en \*str y eso puede provocar un bufferoverflow.
You an find a **template** to exploit the GOT using format-strings here:
#### **Estructuras \_\_atexit \(ya no útil en general\)**
{% page-ref page="format-strings-template.md" %}
atexit\(\) es una función a la cuál se le pasan como parámetros otras funciones y estas funciones se ejecutarán al ejecutarse un exit\(\) o el return del main.
### **DTOR**
Si se consigue modificar la dirección de alguna de estas funciones para que apunte a un shellcode se ganaría el control del proceso, pero actualmente esto es más complicado.
{% hint style="danger" %}
Nowadays is very **weird to find a binary with a dtor section**.
{% endhint %}
Actualmente las direcciones a las funciones que hay que ejecutar se esconden tras varias estructuras y finalmente la dirección a la que apunta no son las direcciones de las funciones, sino que están cifradas con XOR y desplazamientos con una clave aleatoria. Por lo que actualmente este vector de ataque no es de mucha utilidad por lo menos en x86 y x64\_86. La función de cifrado es PTR\_MANGLE.
The destructor are functions that are **executed before program finishes**.
If you manage to **write** an **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
Get the address of this section with:
Otras arquitecturas como m68k, mips32, mips64, aarch64, arm, hppa… No implementas la función de cifrado pues que esta devuelve lo mismo que recibió como entrada. Así que estas arquitectura sí serían atacables mediante este vector.
```bash
objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”
```
#### **setjmp\(\) y longjmp\(\) \(ya no útil en general\)**
Usually you will find the **DTOR** section **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
Setjmp\(\) permite guardar el contexto \(los registros\)
### **Format Strings to Buffer Overflows**
longjmp\(\) permite restablecer el contexto
Tthe **sprintf moves** a formatted string **to** a **variable.** Therefore, you could abuse the **formatting** of a string to cause a **buffer overflow in the variable** where the content is copied to.
For example, the payload `%.44xAAAA` will **write 44B+"AAAA" in the variable**, which may cause a buffer overflow.
Los registros guardados son: EBX, ESI, EDI, ESP, EIP, EBP
### **\_\_atexit Structures**
Lo que pasa es que EIP y ESP son pasados por la función PTR\_MANGLE, por lo que las arquitectura vulnerables a este ataque son las mismas que las anteriores.
{% hint style="danger" %}
Nowadays is very **weird to exploit this**.
{% endhint %}
Son útiles para recuperación de errores o interrupciones.
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64\_86**.
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
Sin embargo, según lo leído, no se protegen los demás registros, por lo que si dentro de la función a la que se llame hay un call ebx, call esi o call edi se puede tomar el control. O también se podría modificar EBP para modificar el ESP.
### **setjmp\(\) & longjmp\(\)**
{% hint style="danger" %}
Nowadays is very **weird to exploit this**.
{% endhint %}
**`Setjmp()`** allows to **save** the **context** \(the registers\)
**`longjmp()`** allows to **restore** the **context**.
The **saved registers** are: `EBX, ESI, EDI, ESP, EIP, EBP`
What happens is that EIP and ESP are passed by the **`PTR_MANGLE`** function, so the **architecture vulnerable to this attack are the same as above**.
They are useful for error recovery or interrupts.
However, from what I have read, the other registers are not protected, **so if there is a `call ebx`, `call esi` or `call edi`** inside the function being called, control can be taken over. Or you could also modify EBP to modify the ESP.
#### **VTable y VPTR en C++**
Cada clase tiene una Vtable que es un array de punteros a métodos.
Each class has a **Vtable** which is an array of **pointers to methods**.
Cada objeto de una clase tiene un VPtr que es un puntero a la Viable de su clase. El VPtr forma parte de la cabecera de cada objeto, por lo que si se logra una sobreescritura del VPtr se podría modificar para que apuntase a una Viable falsa para que al ejecutar una función se fuese a la shellcode.
Each object of a **class** has a **VPtr** which is a **pointer** to the arrayof its class. The VPtr is part of the header of each object, so if an **overwrite** of the **VPtr** is achieved it could be **modified** to **point** to a dummy method so that executing a function would go to the shellcode.
## **Medidas preventivas y evasiones**

View File

@ -158,15 +158,16 @@ nasm -f elf assembly.asm** --&gt; return a ".o"
## Objdump
**-d** --&gt; Disassemble executable sections \(see opcodes of a compiled shellcode, find ROP Gadgets, find function address...\)
**-Mintel** --&gt; Intel sintax
**-t** --&gt; Symbols table \(grep varBSS to get the address\)
**-D** --&gt; Disassemble all \(address of static variable\)
**-s -j .dtors** --&gt; Contenido de dtors
**-s -j .got** --&gt; Contenido de got
**-TR** --&gt; Relocations
**-d** --&gt; **Disassemble executable** sections \(see opcodes of a compiled shellcode, find ROP Gadgets, find function address...\)
**-Mintel** --&gt; **Intel** syntax
**-t** --&gt; **Symbols** table
**-D** --&gt; **Disassemble all** \(address of static variable\)
**-s -j .dtors** --&gt; dtors section
**-s -j .got** --&gt; got section
-D -s -j .plt --&gt; **plt** section **decompiled**
**-TR** --&gt; **Relocations**
**ojdump -t --dynamic-relo ./exec \| grep puts** --&gt; Address of "puts" to modify in GOT
**objdump -TR ./exec \| grep exit\(func lib\)** —&gt; Get address of all the functions inside the GOT
**objdump -D ./exec \| grep "VAR\_NAME"** --&gt; Address or a static variable \(those are stored in DATA section\).
## Core dumps