ROP

Stack pivoting

  • Commonly used in places where you can only execute 1 or 2 gadgets (basically limited gadget execution) mainly because there is some metadata on stack you can’t corrupt (in cases like FSOP) or stack size is small.

One gadget

  • one_gadget to pop shell GitHub

angrop

  • easilly find rop chain

GitHub


Heap

  • malloc never clears the user data unless calloc is used
  • glibc-2.32 onwards have safe-linking.

safe-linking

  • fd pointers in tcache and fastbins are mangled to make exploitation harder.
  • straight-forward principle: use randomness from ASLR to mangle ptrs.
  • heap leak is needed to break safe-linking.
  • target address should be 0x10 byte aligned
def mangle(pos, ptr):
    """
    pos: int = position of heap chunk
    ptr: int = ptr we need. This should be 0x10 byte aligned
    """
    return (pos >> 12) ^ ptr

tcache

  • The free bin is a single linked list (LIFO based).
  • Used to store small freed allocations .
  • 7 allocations per bin.
  • ptr = malloc(size); free(ptr) with size <= 0x408 will go in tcache.
  • “thread” cache. So one tcache per thread.

NOTE-1: >= glibc-2.32 requires heap leak for breaking safe-linking.


NOTE-2: malloc clears out key field (address+8) for tcache


tcache bin struct:

typedef struct tcache_perthread_struct {
    char counts[TCACHE_MAX_BINS];
    tcache_entry* entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;

tcache entry struct:

typedef struct tcache_entry {
    struct tcache_entry* next;
    uintptr_t *key;
} tcache_entry;

key field prevents double-free.

https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L312

Arbitrary Access Read/Write (AAW / AAR)

  • UAF write is required.
  • heap leak to break safe-linking
a = malloc(0x10);
b = malloc(0x10);
free(a);
free(b);

// tcache freelist: [b -> a -> NULL]
// write to b, to overwrite next ptr
// take care of safelinking if needed

b = malloc(0x10); // freelist [ mangled_target -> NULL]
target = malloc(0x10); // get target

// write/read from target ...

Double-free protection bypass

  • UAF write is required.
a = malloc(0x10);
free(a);

write(a, "abcdefghijklmnop", 0x10); // overwrite the key(+8) field

free(a); // double free

House of spirit

The main principle: free(ptr) doesn’t check if the ptr points to valid heap memory, so if we can craft a fake “malloc” like chunk (with chunk size <= 0x410 and malloc arg <= 0x408) then freeing this ptr will add the address pointed by chunk on tcache.

Requirments:

  • Free on near arbitrary ptr (ptr needs to be 0x10 byte aligned).

pseudocode rough sketch:

uint64_t fake_chunks[10];
fake_chunks[1] = 0x40; // chunk size
a = &fake_chunks[2];
free(a);

void* b = malloc(0x35); // get chunk of size 0x40

// b == &fake_chunks[2] (user controlled address)

how2heap poc

Beyond tcache

Fastbins

TODO

House of spirit

TODO

Largebins

TODO

Largebin attack

TODO

Unsorted bins

TODO

Unsafe unlinking

TODO


FSOP - File Struct Oriented Programming

when attacker has ability to write into FILE struct and change metadata.

FILE struct

AAW

fake_file_struct = FileStructure(fp)
payload = fake_file_struct.write(flag_address, 55)
p.send(payload)

AAR

fake_file_struct = FileStructure(fp)
payload = fake_file_struct.write(flag_address, 55)
p.send(payload)

Control Flow Hijacking

TODO

Random notes


Format String

AAR

TODO

AAW

TODO

Control Flow Hijacking

TODO


memory “hopping”

TODO

environ

Breaking ASLR

Breaking PIE

Breaking canary

Timing side channel