Skip to content

Commit bf79925

Browse files
committed
New release
1 parent 3870fe0 commit bf79925

File tree

17 files changed

+1586
-345
lines changed

17 files changed

+1586
-345
lines changed

.github/workflows/build.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Build
2+
3+
on:
4+
push
5+
6+
jobs:
7+
build:
8+
runs-on: ${{ matrix.os }}
9+
strategy:
10+
matrix:
11+
os: [ubuntu-24.04-arm, ubuntu-24.04]
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v3
16+
17+
- name: Install dependencies from apt
18+
run: |
19+
sudo apt update
20+
sudo apt install -y make clang llvm libbpf-dev linux-tools-generic
21+
22+
- name: Compile with Make
23+
run: |
24+
make CORE=1 static
25+
26+
- name: Upload x64 binary
27+
uses: actions/upload-artifact@v4
28+
with:
29+
name: lemon.x86_64
30+
path: "lemon.x86_64"
31+
continue-on-error: true
32+
33+
- name: Upload ARM64 binary
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: lemon.aarch64
37+
path: "lemon.aarch64"
38+
continue-on-error: true

.gitignore

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1 @@
1-
# Prerequisites
2-
*.d
3-
4-
# Object files
5-
*.o
6-
*.ko
7-
*.obj
8-
*.elf
9-
10-
# Linker output
11-
*.ilk
12-
*.map
13-
*.exp
14-
15-
# Precompiled Headers
16-
*.gch
17-
*.pch
18-
19-
# Libraries
20-
*.lib
21-
*.a
22-
*.la
23-
*.lo
24-
25-
# Shared objects (inc. Windows DLLs)
26-
*.dll
27-
*.so
28-
*.so.*
29-
*.dylib
30-
31-
# Executables
32-
*.exe
33-
*.out
34-
*.app
35-
*.i*86
36-
*.x86_64
37-
*.hex
38-
39-
# Debug files
40-
*.dSYM/
41-
*.su
42-
*.idb
43-
*.pdb
44-
45-
# Kernel Module Compile Results
46-
*.mod*
47-
*.cmd
48-
.tmp_versions/
49-
modules.order
50-
Module.symvers
51-
Mkfile.old
52-
dkms.conf
1+
vmlinux.h

Makefile

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,66 @@
1-
STATIC ?=
2-
CORE ?=
1+
# Optional build flags (can be overridden via command line)
2+
STATIC ?= # Default is not static
3+
CORE ?= 1 # Default to CORE=1, can be disabled via CORE=0
34

5+
# System and architecture detection
46
ARCH := $(shell uname -m)
7+
BPFTOOL := bpftool
58

6-
# For now supports only x86-64 and ARM64
9+
# Detect architecture for eBPF
710
ifeq ($(ARCH), x86_64)
811
TARGET_ARCH := __TARGET_ARCH_x86
912
else ifeq ($(ARCH), aarch64)
1013
TARGET_ARCH := __TARGET_ARCH_arm64
14+
else
15+
$(error Unsupported architecture: $(ARCH))
1116
endif
1217

13-
all: CORE=-D CORE
14-
all: ebpf loader
18+
# Define compiler and flags
19+
CLANG := clang
20+
CFLAGS := -Wall -O2 -D$(TARGET_ARCH)
21+
LDFLAGS := -lbpf -lelf -lz -lzstd
1522

16-
static: CORE=1
17-
static: STATIC=-static
18-
static: all
23+
# Conditional flags
24+
ifeq ($(CORE), 1)
25+
CFLAGS += -DCORE
26+
BPF_CORE_FLAG := -DCORE
27+
endif
28+
29+
ifeq ($(STATIC), 1)
30+
LDFLAGS += -static
31+
endif
32+
33+
# Files
34+
LOADER_SRCS := lemon.c cpu_stealer.c mem.c dump.c disk.c net.c
35+
LOADER_BIN := lemon.$(ARCH)
36+
BPF_SRC := ebpf/mem.ebpf.c
37+
BPF_OBJ := ebpf/mem.ebpf.o
38+
BPF_SKEL := ebpf/mem.ebpf.skel.h
1939

20-
loader:
21-
clang $(CORE) -D $(TARGET_ARCH) -Wall -O2 lemon.c mem.c disk.c -o lemon -lbpf -lelf -lz -lzstd $(STATIC)
40+
# Default target: If CORE is enabled, make vmlinux first, then compile eBPF and loader
41+
all: $(if $(filter 1,$(CORE)), vmlinux) $(BPF_OBJ) $(LOADER_BIN)
2242

23-
ebpf:
24-
clang -target bpf $(CORE) -D $(TARGET_ARCH) -I/usr/include/linux -I/usr/include/$(ARCH)-linux-gnu \
25-
-Wall -O2 -g -c lemon.ebpf.c -o lemon.ebpf.o
26-
llvm-strip -g lemon.ebpf.o
27-
bpftool gen skeleton lemon.ebpf.o > lemon.ebpf.skel.h
43+
# Build eBPF object and generate skeleton
44+
$(BPF_OBJ): $(BPF_SRC)
45+
$(CLANG) -target bpf -D$(TARGET_ARCH) $(BPF_CORE_FLAG) -I/usr/include/linux -I/usr/include/$(ARCH)-linux-gnu \
46+
-Wall -O2 -g -c $< -o $@
47+
llvm-strip -g $(BPF_OBJ)
48+
$(BPFTOOL) gen skeleton $(BPF_OBJ) > $(BPF_SKEL)
2849

50+
# Build the loader (compiled before eBPF program)
51+
$(LOADER_BIN): $(LOADER_SRCS)
52+
$(CLANG) $(CFLAGS) $^ -o $@ $(LDFLAGS)
53+
54+
# Dump vmlinux BTF as C header (only if CORE is enabled)
2955
vmlinux:
30-
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
56+
$(BPFTOOL) btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
57+
58+
# Static target for convenience
59+
static:
60+
$(MAKE) STATIC=1
3161

62+
# Clean
3263
clean:
33-
rm -f *.o *.bc vmlinux.h lemon.ebpf.skel.h lemon
64+
rm -f $(LOADER_BIN) $(BPF_OBJ) $(BPF_SKEL) vmlinux.h
65+
66+
.PHONY: all static clean vmlinux

README.md

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
1-
# LEMON - An eBPF Memory Dump Tool for x64 and ARM64 Linux
1+
# LEMON - An eBPF Memory Dump Tool for x64 and ARM64 Linux and Android
22

3-
LEMON is a Linux memory dump tool that utilizes eBPF to capture the entire physical memory of a system and save it in LiME format, compatible with forensic tools such as Volatility 3.
3+
LEMON is a Linux and Android memory dump tool that utilizes eBPF to capture the entire physical memory of a system and save it in LiME format, compatible with forensic tools such as Volatility 3.
44

55
LEMON is available as a precompiled static binary for x64 and ARM64, leveraging a CO-RE (Compile Once, Run Everywhere) eBPF program. This allows analysts to dump system memory without compiling anything on the target machine, checking for specific compatibility with installed libraries and kernel versions, and without requiring kernel headers. It is particularly useful in scenarios where loading kernel modules is not possible (e.g., due to Secure Boot) or when `{/proc, /dev}/kcore` is unavailable.
66

77
## Usage
88

9-
Copy the `lemon` binary to the target machine and initiate the memory dump with:
9+
Copy the `lemon` binary to the target machine and initiate a memory dump on disk with:
1010

1111
```sh
12-
./lemon memory.dump
12+
./lemon.ARCH -d memory_on_disk.dump
13+
```
14+
15+
For a network dump instead use:
16+
17+
```sh
18+
./lemon.ARCH -n TARGET_IP -p TARGET_PORT
19+
```
20+
while on the target machine
21+
```sh
22+
nc -l -p TARGET_PORT > memory_by_net.dump
1323
```
1424

1525
This generates a `memory.dump` file in LiME format, containing all physical memory pages. Since running eBPF programs typically requires root privileges, LEMON must be executed as `root` or with an appropriate `sudo` configuration.
1626

1727
## Build
1828

19-
Precompiled static binaries (`static_bins/lemon.x64` and `static_bins/lemon.arm64`) are available in this repository. Analysts can also compile LEMON themselves, either dynamically or statically. The dynamic version requires the presence of `libbpf`, `libz`, `libelf`, and `libzstd` on the target machine, whereas the static version has no external dependencies. Note that the build machine **MUST** have the same CPU architecture as the target.
29+
Precompiled static binaries are available in this repository (check the Github actions tab). Analysts can also compile LEMON themselves, either dynamically or statically. The dynamic version requires the presence of `libbpf`, `libz`, `libelf`, and `libzstd` on the target machine, whereas the static version has no external dependencies. Note that the build machine **MUST** have the same CPU architecture as the target.
2030

2131
### Dependencies
2232

@@ -36,7 +46,7 @@ Other distributions provide equivalent packages, which at minimum allow compilin
3646
git clone [email protected]:eurecom-s3/lemon.git && cd lemon
3747
```
3848

39-
2. **Generate a valid **``** file:**
49+
2. **Generate a valid **`vmlinux.h`** file (only for CO-RE builds):**
4050

4151
Copy a valid `vmlinux.h` file into `lemon/` or generate one with:
4252

@@ -46,24 +56,45 @@ Other distributions provide equivalent packages, which at minimum allow compilin
4656

4757
3. **Compile:**
4858

49-
- Dynamic binary:
59+
- Dynamic binary (set CORE=0 for non CO-RE binaries):
5060
```sh
51-
make
61+
make CORE=1
5262
```
5363
- Static binary:
5464
```sh
55-
make static
65+
make CORE=1 static
5666
```
5767

5868
## Limitations
5969

6070
- The kernel must support eBPF (obviously!).
6171
- Kernel lockdown must not be in confidentiality mode (or must allow `bpf_probe_read_kernel()`).
62-
- Currently, LEMON supports only CO-RE kernels and on-disk memory dumps.
6372
6473
## TODO
6574
66-
- [ ] Support non CO-RE kernels
67-
- [ ] Insert checks on kernel versions and ```CONFIG_``` kernel options to extend support
68-
- [ ] Implement network dump
69-
- [ ] Support other CPU architectures (x32, ARM32, MIPS, PowerPC, POWER, RISC-V)
75+
- [X] Support non CO-RE kernels ([this library](https://github.com/eunomia-bpf/bpf-compatible) might help)
76+
- [X] Insert checks on kernel versions and ```CONFIG_``` kernel options to extend support
77+
- [X] Implement network dump (TCP)
78+
- [X] Implement dump with reduced granule if page fail to be read
79+
- [ ] Support other CPU architectures (x32, ARM32, MIPS, PowerPC, POWER, RISC-V)
80+
- [ ] Introduce support for kernels that do not have uprobes (by hooking some syscall or intectept egress traffic in read only from TC?)
81+
- [ ] Use of `_stext` in x64 to bypass missing `CONFIG_KALLSYMS_ALL`
82+
- [ ] Bruteforce scanning (?) for page containing same data of `_stext` page in ARM64 to bypass missing `CONFIG_KALLSYMS_ALL`
83+
- [ ] Implement network dump (UDP)
84+
85+
## Notes
86+
87+
### eBPF cronology
88+
- Introduction of eBPF: 3.15
89+
- Introduction of Array maps 3.19
90+
- Introduction of kProbe/uProbe support 4.1
91+
- Introduction of tracepoint support (syscalls tracing) 4.7
92+
- Introduction of XDP 4.8
93+
- !!! Android 9 support eBPF: 4.9
94+
- Introduction of BTF 4.18
95+
- Introduction mmap() support for array maps 5.5
96+
- !!! Introduction of read_kernel() 5.5 <==== Minimum Lemon target version
97+
- Introduction of ring_buffer 5.8
98+
- !!! Android 13 support BTF 5.15
99+
- Introduction of SYSCALL program type 5.15
100+
- Introduction of kallsyms() in ebpf 5.16

0 commit comments

Comments
 (0)