# Software Sec Lab3
## Phase 1: AFL++
### Bugs:
#### 1. sample_crash
add `current_chunk->chunk_data = NULL;` in `load_png` after `struct png_chunk *current_chunk = malloc(sizeof(struct png_chunk));` (ca line 557)
#### 2. double free
add `chunk->chunk_data = NULL;` in `read_png_chunk`, after `free(chunk->chunk_data);` in the error handling part.
#### 3. memory leak
##### with palette.png (and possibly all other files):
add `free(inflated_buf)` before `goto error` in `load_png`
##### with input from fuzzer
in `success` and/or `error` goto parts of `load_png`, add `free` statements to all of the different types of chunks, like so
```c
if (plte_chunk){
if(plte_chunk->chunk_data){
free(plte_chunk->chunk_data);
}
free(plte_chunk);
}
```
#### 4. nullpointer
`struct plte_entry *plte_entries = (struct plte_entry *)plte_chunk->chunk_data;` in `convert_color_palette_to_image` may cause a nullpointer dereference. Not sure yet how to solve underlying issue.
#### 5. HeapOverflow
In `convert_color_palette_to_image()` line 413 has a heap-buffer-overflow. Make a check:
```c
if (inflated_size < height || inflated_size < width) {
return NULL;
}
```
#### 6. heap-use-after-free
In `*convert_rgb_alpha_to_image`, the error handling doesn't return anything, but should return NULL;
---
### Answers
Answers from S.
#### Why did you need to change is_png_chunk_valid?
This function makes a crc check using another file `crc.h`.
If the check fails, the input used for this run will not be tested with actual functions that we want to fuzz. So we potentially loose some inputs.
#### Why did you have to use afl-clang to compile the source (and not e.g. ordinary clang)?
`afl-clang` is used to instrument the code. This leads to better white box fuzz testing. It further should be much faster.
#### How long did you fuzz? How many crashes in total did AFL++ produce? How many unique crashes?
Add your findings...
#### Why are hangs counted as bugs in AFL++? Which type of attack can they be used for?
DoS attack?
#### Which interface of libpngparser remains untested by AFL++ (take a look at pngparser.h)?
```c
int store_png(const char *filename, struct image *img, struct pixel *palette, uint8_t palette_length);
```
Even though it is implemented in `pngparser.c` it is never actually used.
---
## Phase 2: libFuzzer
### Fuzzer Stubs
### Errors/Crashes
#### Buffer Overflow
```c
uint32_t size_x = img->size_x;
uint32_t size_y = img->size_y;
for (uint32_t id_y = 0; id_y < size_y; id_y++) {
non_compressed_buf[id_y * (1 + size_x * 4)] = 0;
for (uint32_t id_x = 0; id_x < size_x; id_x++) {
uint32_t id_pix_buf = id_y * (1 + size_x * 4) + 1 + 4 * id_x;
uint32_t id_pix = id_y * size_x + id_x;
non_compressed_buf[id_pix_buf] = img->px[id_pix].red;
non_compressed_buf[id_pix_buf + 1] = img->px[id_pix].green;
non_compressed_buf[id_pix_buf + 2] = img->px[id_pix].blue;
non_compressed_buf[id_pix_buf + 3] = img->px[id_pix].alpha;
}
}
```
somehow,the img->px[id_pix] READ results in a global-buffer-overflow
### Custom Mutator
* Remove chunk types that don't exist in Yolo (can then remove the type checks for types that don't exist anymore (e.g. "iccP"))
```c
case 4: {
static const char *types[] = {
"IHDR", "IDAT", "IEND",
"fUZz", // special chunk for extra fuzzing hints.
};
```
* make sure we have some PLTE chunks
```c
void Serialize(std::ostream &out) {
const unsigned char header[] = {0x89, 0x50, 0x4e, 0x47,
0x0d, 0x0a, 0x1a, 0x0a};
out.write((const char*)header, sizeof(header));
WriteChunk(out, "IHDR", ihdr_);
if(time(NULL) % 2 == 0)
{
WriteChunk(out,"PLTE", {0x55, 0x66, 0x71}); //"Random bytes", choose something else and maybe a different length (multiple of 3)
}
for (auto &ch : chunks_) {
WriteChunk(out, ch.type, ch.v);
}
WriteChunk(out, "IEND", {});
}
```
## Answers
### 1. You did not change `is_png_chunk_valid` in this lab, does it affect the performance of libFuzzer's default mutator? What about the example PNG mutator and your custom YOLO PNG mutator?
default mutator is really slow, as it rarely generates valid pngs
the others aren't nevatively impacted.
### 2. How many PCs are covered within `100000 fuzzing runs` with your `fuzzer_store_png_rgba`, equiped with libFuzzer's default mutator, the example PNG mutator, and your custom YOLO PNG mutator separately? Do these numbers reflect the extent to which `store_png` has been teseted?
fuzzer_store_png_rgba (default) ~100 (but slow af)
fuzzer_store_png_rgba (png mutator) ~110
fuzzer_store_png_rgba_custom ~115
### 3. Do you think the mutator you customized (that aims at only generating well-formatted YOLO PNG inputs) helpful for finding bugs in `load_png`? Why?