Skip to content

Commit f81c033

Browse files
authored
Merge pull request #5 from whoismz/main
Add real eBPF XDP fallback for memory reading
2 parents 0b644df + 6041c37 commit f81c033

File tree

8 files changed

+210
-74
lines changed

8 files changed

+210
-74
lines changed

capabilities.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
* Capabilities needed in some cases
1414
*
15-
* CAP_SYS_ADMIN -> needed to change /proc/sys/kernel/kptr_restrict from 2 to 0 (not needed if set to 1 or 0), needed to access
15+
* CAP_SYS_ADMIN -> needed to change /proc/sys/kernel/kptr_restrict from 2 to 0 (not needed if set to 1 or 0), needed to access
1616
* /proc/iomem if CONFIG_KALLSYMS_ALL is not active and so iomem_resources is not available, needed on old kernels
1717
* CAP_DAC_OVERRIDE -> needed to create a brand new dump file in the case the directory is not owned by the user running LEMON
1818
*/
@@ -54,4 +54,4 @@ int check_capability(const cap_value_t cap) {
5454

5555
if(!ret) ret = (cap_flag == CAP_SET);
5656
return ret;
57-
}
57+
}

cpu_stealer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ typedef struct {
2929
* @param priority: The priority to set for the current process.
3030
* @return 0 on success, -1 on failure.
3131
*/
32-
static int set_priority(const int priority){
32+
static int set_priority(const int priority) {
3333
const struct sched_param sparam = {
3434
.sched_priority = priority
3535
};

dump.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ static int dump_region(const uintptr_t region_start, const uintptr_t region_end,
3030
unsigned char *read_data = NULL;
3131

3232
chunk_start = region_start;
33-
while (chunk_start <= region_end)
34-
{
33+
while (chunk_start <= region_end) {
3534
/* Read memory region in chunks of maximum granule bytes */
3635
chunk_end = (region_end - chunk_start + 1 > granule) ? chunk_start + granule - 1 : region_end;
3736
chunk_size = chunk_end - chunk_start + 1;

ebpf/mem.ebpf.c

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
#ifdef CORE
22
#include "../vmlinux.h"
33
#include <bpf/bpf_core_read.h>
4+
5+
#ifndef ETH_P_IP
6+
#define ETH_P_IP 0x0800
7+
#endif
8+
9+
#ifndef IPPROTO_UDP
10+
#define IPPROTO_UDP 17
11+
#endif
412
#else
5-
#include <linux/bpf.h>
613
#include <asm/ptrace.h>
14+
#include <linux/bpf.h>
15+
#include <linux/if_ether.h>
16+
#include <linux/in.h>
17+
#include <linux/ip.h>
18+
#include <linux/udp.h>
719
#endif
820

921
#include <bpf/bpf_helpers.h>
1022
#include <bpf/bpf_tracing.h>
23+
#include <bpf/bpf_endian.h>
1124

1225
#include "../lemon.h"
1326

@@ -113,32 +126,79 @@ int read_kernel_memory_uprobe(struct pt_regs *ctx)
113126
return read_memory(address, dump_size);
114127
}
115128

129+
#define TRIGGER_PACKET_PORT 9999
130+
#define TRIGGER_PACKET_ADDR 0x7f000001 /* 127.0.0.1 */
131+
116132
/*
117133
* read_kernel_memory_xdp() - XDP program to trigger a kernel memory read
118134
* @ctx: Pointer to the XDP context containing packet metadata
119135
*
120-
* Parses a synthetic packet containing address and size parameters used to
121-
* perform a kernel memory read.
136+
* Parses a UDP packet containing address and size parameters used to
137+
* perform a kernel memory read. Expects UDP packets to 127.0.0.1:9999.
122138
*/
123139
SEC("xdp")
124-
int read_kernel_memory_xdp(struct xdp_md* ctx) {
125-
int ret;
126-
127-
/* Validate data in fake network packet (needed to bypass eBPF validator )*/
140+
int read_kernel_memory_xdp(struct xdp_md* ctx) {
128141
void* data = (void*)(long)ctx->data;
129142
void* data_end = (void*)(long)ctx->data_end;
130-
if((data + sizeof(struct read_mem_args)> data_end)) return XDP_DROP;
131143

132-
/* Extract arguments from fake packet */
133-
struct read_mem_args *args = data;
144+
/* Validate Ethernet header */
145+
struct ethhdr *eth = data;
146+
if ((void*)(eth + 1) > data_end) {
147+
return XDP_DROP;
148+
}
149+
150+
/* Check if this is an IP packet */
151+
if (eth->h_proto != bpf_htons(ETH_P_IP)) {
152+
return XDP_PASS;
153+
}
154+
155+
/* Validate and parse IP header */
156+
struct iphdr *ip = (struct iphdr*)(eth + 1);
157+
if ((void*)(ip + 1) > data_end) {
158+
return XDP_DROP;
159+
}
160+
161+
/* Check if this is a UDP packet */
162+
if (ip->protocol != IPPROTO_UDP) {
163+
return XDP_PASS;
164+
}
165+
166+
/* Check if source/dest is loopback */
167+
if (ip->saddr != bpf_htonl(TRIGGER_PACKET_ADDR) || ip->daddr != bpf_htonl(TRIGGER_PACKET_ADDR)) {
168+
return XDP_PASS;
169+
}
170+
171+
/* Validate IP header length */
172+
if (ip->ihl < 5) {
173+
return XDP_DROP;
174+
}
175+
176+
/* Validate UDP header */
177+
struct udphdr *udp = (struct udphdr*)((char*)ip + (ip->ihl * 4));
178+
if ((void*)(udp + 1) > data_end) {
179+
return XDP_DROP;
180+
}
181+
182+
/* Check destination port */
183+
if (udp->dest != bpf_htons(TRIGGER_PACKET_PORT)) {
184+
return XDP_PASS;
185+
}
186+
187+
/* Validate payload */
188+
struct read_mem_args *args = (struct read_mem_args*)(udp + 1);
189+
if ((void*)(args + 1) > data_end) {
190+
return XDP_DROP;
191+
}
192+
134193
__u64 address = args->addr;
135-
__u64 dump_size = args->size;
194+
__u64 dump_size = args->size;
136195

137196
/* Read memory! */
138-
ret = read_memory(address, dump_size);
139-
if(ret) return XDP_DROP;
197+
if (read_memory(address, dump_size)) {
198+
return XDP_DROP;
199+
}
140200

141201
return XDP_PASS;
142202
}
143203

144-
char _license[] SEC("license") = "GPL";
204+
char _license[] SEC("license") = "GPL";

lemon.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ static int check_kernel_version() {
119119
return (major > MIN_MAJOR_LINUX) || ((major == MIN_MAJOR_LINUX) && (minor >= MIN_MINOR_LINUX));
120120
}
121121

122-
int main(int argc, char **argv)
123-
{
122+
int main(int argc, char **argv) {
124123
struct ram_regions ram_regions;
125124
struct options opts = {0};
126125
struct argp argp = {options, parse_opt, "", doc};

lemon.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <stdbool.h>
55
#include <errno.h>
66

7-
#define MIN_MAJOR_LINUX 5 /* Minimium kernel version supported */
7+
#define MIN_MAJOR_LINUX 5 /* Minimium kernel version supported */
88
#define MIN_MINOR_LINUX 5
99

1010
#define HUGE_PAGE_SIZE 2 * 1024 * 1024 /* Same for huge pages */

0 commit comments

Comments
 (0)