This is the repository of our paper presented at the ACSAC 2025.
Paper: (to appear)
The artifacts submitted for our paper include a prototype of ELK, as described in the design (Section 4) and implementation (Section 6). ELK is comprised of two major components. A runtime library (RIOT-OS) and an LLVM pass to instrument the C source codes. The current implementation is based on the MPU and TT features (Armv8-M). To support these features, a development board based on the Armv8-M architecture is required. ELK has been tested on the NUCLEO-L552ZE-Q development board by STMicroelectronics. The current implementation uses a cross-compilation approach. The input to the ELK instrumentation pass is an LLVM bitcode file, and the output is an instrumented ELF binary.
| File | Description |
|---|---|
claims |
Example C programs to test the basic functionality of ELK |
llvm-project-15 |
Modified LLVM 15.0 for compiler instrumentation |
riot-os-2022 |
Modified RIOT-OS 2022.10 for ELK runtime library |
env.sh |
Script to configure the running environment |
install-llvm.sh |
Script to automatically install modified LLVM for ELK |
pyterm.sh |
Script to connect the development board using pyterm |
Important
Public research infrastructure is not applicable due to the hardware requirement.
ELK requires the following software and hardware components:
- Development boards NUCLEO-L552ZE-Q by STMicroelectronics (Available 8 MPU Regions, 256 KB SRAM)
- A workstation running Ubuntu 22.04 LTS
- Embedded ARM cross-compiler toolchain
- Python 3.7+ (pySerial)
$ sudo apt install cmake ninja-build build-essential gcc-arm-none-eabi
$ pip3 install pyserial$ git clone https://github.com/cslab-pnu/ELK
$ cd ELKLet's install LLVM. Building LLVM can take some time.
$ ./install-llvm.shThen, load the environment in your current shell:
$ source env.shNote
Connect the development board to the workstation. Check the corresponding development board manual for more details (Link).
To check the test results of ELK, the development board must be connected to the terminal as shown below.
In a new terminal, enter the following:
$ ./pyterm.sh- Expected output:
2025-09-08 10:59:22,561 # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
Compile the example programs in the claims directory.
Claim 1. use-after-free
$ cd claims/use-after-free
$ make flash- Expected output: View image
2025-09-08 11:10:35,736 # obj allocated at: 0x20006000
2025-09-08 11:10:35,739 # obj 0x20006000 has been deallocated
2025-09-08 11:10:35,740 # use after free...
2025-09-08 11:10:35,742 # [ELK] Use After Free Detected!
Claim 2. double-free
$ cd claims/double-free
$ make flash- Expected output: View image
2025-09-08 11:06:52,065 # allocated: 0x20004000
2025-09-08 11:06:52,067 # freed once: 0x20004000
2025-09-08 11:06:52,069 # [ELK] Double Free Detected!
Claim 3. invalid-free
$ cd claims/invalid-free
$ make flash- Expected output: View image
2025-09-08 11:04:33,627 # base: 0x20004000, interior: 0x20004008
2025-09-08 11:04:33,633 # [ELK] Invalid Free Detected! (Free of Pointer not at Start of Buffer)
To check whether ELK's instrumentation pass works correctly when compiling a C program, enter the following command:
$ cd claims/use-after-free
$ clang -emit-llvm -S use_after_free.c -o test.ll
$ cat test.llAfterward, you can confirm that the instrumentation code has been inserted as shown below:
...
%arrayidx = getelementptr inbounds i8, i8* %3, i64 0
%4 = call i8* @check_and_translation(i8* %arrayidx)
%5 = load i8, i8* %4, align 1
...If you use this work or parts of it, please cite our paper as follows:
@inproceedings {
}