Notes
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_gadgetto pop shell GitHub
angrop
- easilly find rop chain
Heap
mallocnever clears the user data unless calloc is used- glibc-2.32 onwards have safe-linking.
safe-linking
fdpointers 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)
Fastbins
TODO
House of spirit
TODO
Largebins
TODO
Largebin attack
TODO
Unsorted bins
TODO
Unsafe unlinking
TODO
FSOP
TODO
AAW
TODO
AAR
TODO
Control Flow Hijacking
TODO
Random notes
Format String
AAR
TODO
AAW
TODO
Control Flow Hijacking
TODO
memory “hopping”
TODO