Skip to content

Resources for Introduction to Static Code Analysis & Binary Obfuscation using LLVM Passes

License

Notifications You must be signed in to change notification settings

Saket-Upadhyay/llvm-obfuscation-edu

Repository files navigation

macOS Build Ubuntu Build LLVM-17

Introduction to Static Code Analysis & Binary Obfuscation using LLVM Passes.

About

This codebase is intentionally simple and contains the bare minimum code to aid learning.

Build macOS and tested on macOS14.3.1 and Ubuntu22.04LTS and with LLVM-17.0;

Table of contents

Project Contents

.
├── CMakeLists.txt
├── CompareAssembly
├── LICENSE
├── README.md
├── src
└── tests

src directory

  1. LLVMObfuscation.cpp (Driver Tool): Takes LLVM bitcode, runs passes on it, then saves the modified bitcode.
  2. OpSubstitutionPass (Transformation Pass): Operator substitution obfuscation pass.
  3. StaticFunctionCallAnalysis (Analysis Pass): Counts the number of static calls for each function in a module and saves the data in a CSV file.
  4. CryptoUtilsø : Pseudorandom number generator.
src
├── CMakeLists.txt
├── CryptoUtils
│   └── ...
│  
├── LLVMObfuscation.cpp
├── LLVMObfuscation.h
│  
├── OpSubstitutionPass
│   ├── CMakeLists.txt
│   ├── OperatorSubstitution.cpp
│   └── OperatorSubstitution.h
│
└── StaticFunctionCallAnalysisPass
    ├── CMakeLists.txt
    ├── StaticFunctionCallAnalysisPass.cpp
    └── StaticFunctionCallAnalysisPass.h

Compare Assembly

This directory contains the assembly output of OpSubstitutionPass with 1 and 3 iterations, along with an un-obfuscated assembly with the source code on two architectures.

aarch64: AppleM2; macOS14.3.1 (23D60) Darwin Kernel Version 23.3.0
intelx86: 13th Gen Intel® Core™ i9-13900KS; Ubuntu22.04.3 LTS 5.15.0-101-generic
CompareAssembly
├── aarch64
│   ├── obfuscatedbinaryITR1aarch64.asm
│   ├── obfuscatedbinaryITR3aarch64.asm
│   ├── originalbinaryAarch64.asm
│   └── sourcecode.cpp
└── intelx86
    ├── obfuscatedbinaryITR1x86.asm
    ├── obfuscatedbinaryITR3x86.asm
    ├── originalbinaryx86.asm
    └── sourcecode.cpp

Test Directory

Contains a C++ file to observe the effects of the passes and a Makefile to compile it.

tests
├── Makefile
└── ObfuscationTest.cpp

goto Tests section to read more.

Build Process

Prerequisite

Install LLVM 17+

Linux/Ubuntu: read more here

TLDR; -

sudo apt-get update
sudo apt install lsb-release wget software-properties-common gnupg cmake ninja-build
wget https://apt.llvm.org/llvm.sh; chmod +x llvm.sh; sudo ./llvm.sh 17 all

For macOS, you can use homebrew to install LLVM-17 by

brew install llvm@17

Add LLVM binaries to your shell path (change to .zshrc if applicable):

echo "export PATH=$(llvm-config --bindir):$PATH" >>~/.bashrc
source ~/.bashrc
reset

CMake, Ninja, objdump

Linux/Ubuntu:

apt-get install cmake ninja objdump

macOS:

brew install cmake ninja

macOS ships with objdump, it is part of com.apple.pkg.Essentials. LLVM usually ships with llvm-objdump; our Makefile in tests can use whichever is in the path.

Compile

Fetch Code

git clone git@github.com:Saket-Upadhyay/llvm-obfuscation-edu.git

Compile

cd llvm-obfuscation-edu
cmake -GNinja -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

Use

Tool

Location of binary and adding it to the system path

The tool's binary will be compiled at ./build/src/llvmobfuscator. You can create a symlink to the binary or add /build/src/ to the PATH.

To add the build path to PATH, from your project root execute -

export PATH="./build/src/":$PATH

Using the binary

llvmobfuscator <Input> <Output> <Pass Selector>
  1. Input - Takes the path of the LLVM bitcode to modify.
  2. Output - File name to save modified bitcode as.
  3. Pass Selector - Takes an integer.
  4. 0 = Run all Passes
  5. 1 = Operator substitution Pass
  6. 2 = User Defined Pass
  7. ...

NOTE: The Pass Selector is implemented in the runCustomPassesOnModule function in LLVMObfuscation.cpp. You can add your passes in the switch statement to isolate execution. This document will change if I add more passes in the future. This design is good for observing the transformations of specific obfuscation.

Analysis passes are run on all options.

Tests

Build the project, then go to the tests directory and execute -

make all

This will create the following files in the tests directory

tests
├── Makefile
├── ObfuscationTest.cpp
├── ObfuscationTool -> ../build/src/llvmobfuscator
├── StaticFunctionCallCount_originalbinary.bc.csv
├── obfuscatedbinary
├── obfuscatedbinary.asm
├── obfuscatedbinary.bc
├── obfuscatedbinary.ll
├── obfuscatedbinary.o
├── originalbinary
├── originalbinary.asm
├── originalbinary.bc
├── originalbinary.ll
└── originalbinary.o
  1. Two executable binary files, original and obfuscated.
  2. LLVM bitcode for binaries.
  3. LLVM IR file for binaries.
  4. Machine object files for binaries.
  5. Assembly dump for the binaries as respective .asm files.µ
  6. StaticFunctionCallCount_*.csv, contains SFCC Analysis Pass data.
  7. ObfuscationTool: a symlink to /build/src/llvmobfuscator.

For cleanup, execute -

make clean

It is assumed that you have built the tool, and it is available at ../build/src/llvmobfuscator. A symlink to that file named ObfuscationTool is created in the tests folder.

µ: *.asm files will only be produced if either objdump or llvm-objdump is found in the environment path.

To create just the symlink, execute -

make symlinktool

or you can create it manually by

ln -s ../build/src/llvmobfuscator ObfuscationTool

This will create an ObfuscationTool symlink.


License

MIT License - See this file

ø except CryptoUtils.

Contribute

Please don't hesitate to add new obfuscation passes. The goal is to annotate the code so that it is easy for students to follow along, and leave some opportunities for experiments.

References / Citations

  1. ø CryptoUtils is an AES-CTR-based cryptographically secure pseudo-random generator by jrinaldini, pjunod; UIUC. This code follows the UIUC OS License and is not covered under the MIT License of this project.
  2. LLVM Programmers Manual
  3. Pascal Junod, Julien Rinaldini, Johan Wehrli, and Julie Michielin. 2015. Obfuscator-LLVM -- Software Protection for the Masses. In Proceedings of the 2015 IEEE/ACM 1st International Workshop on Software Protection (SPRO '15). IEEE Computer Society, USA, 3–9. https://doi.org/10.1109/SPRO.2015.10

---
Saket Upadhyay
Ph.D. Student,
Department of Computer Science,
SEAS, University of Virginia.
saketupadhyay.com

GPG PUBLIC KEY
1742 06DB 710F 9E4A 06F5 9DF1 7473 B3A4 59BA 0808

About

Resources for Introduction to Static Code Analysis & Binary Obfuscation using LLVM Passes

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published