Rellic ist eine Implementierung des Muster-unabhängigen Strukturierungsalgorithmus, um einen goto-freien C-Ausgang aus LLVM-Bitcode zu erzeugen.
Die Designphilosophie hinter dem Projekt besteht darin, eine relativ kleine und leicht hackbare Codebasis mit großer Interoperabilität mit anderen LLVM- und Remill -Projekten zu bieten.
| Originalprogramm | Mit -emit-llvm -O0 kompiliert und zerlegt |
int main () {
for ( int i = 0 ; i < 30 ; ++ i ) {
if ( i % 3 == 0 && i % 5 == 0 ) {
printf ( "fizzbuzzn" );
} else if ( i % 3 == 0 ) {
printf ( "fizzn" );
} else if ( i % 5 == 0 ) {
printf ( "buzzn" );
} else {
printf ( "%dn" , i );
}
}
} | int main () {
unsigned int var0 ;
unsigned int i ;
var0 = 0U ;
i = 0U ;
while (( int ) i < 30 ) {
if (( int ) i % 3 != 0U || !(( int ) i % 5 == 0U || ( int ) i % 3 != 0U )) {
if (( int ) i % 3 != 0U ) {
if (( int ) i % 5 != 0U ) {
printf ( "%dn" , i );
} else {
printf ( "buzzn" );
}
} else {
printf ( "fizzn" );
}
} else {
printf ( "fizzbuzzn" );
}
i = i + 1U ;
}
return var0 ;
} |
int main () {
int i = 0 ;
start:
i ++ ;
switch ( i ) {
case 1 : printf ( "%dn" , i ); goto start; break ;
case 2 : printf ( "%dn" , i ); goto start; break ;
case 3 : printf ( "%dn" , i ); break ;
}
} | int main () {
unsigned int var0 ;
unsigned int i ;
var0 = 0U ;
i = 0U ;
do {
i = i + 1U ;
if (!( i != 3U && i != 2U && i != 1U ))
if ( i == 3U ) {
printf ( "%dn" , i );
break ;
} else if ( i == 2U ) {
printf ( "%dn" , i );
} else {
printf ( "%dn" , i );
}
} while (!( i != 3U && i != 2U && i != 1U ));
return var0 ;
} |
int main () {
int x = atoi ( "5" );
if ( x > 10 ) {
while ( x < 20 ) {
x = x + 1 ;
printf ( "loop1 x: %dn" , x );
}
}
while ( x < 20 ) {
x = x + 1 ;
printf ( "loop2 x: %dn" , x );
}
} | int main () {
unsigned int var0 ;
unsigned int x ;
unsigned int call2 ;
var0 = 0U ;
call2 = atoi ( "5" );
x = call2 ;
if (( int ) x > 10 ) {
while (( int ) x < 20 ) {
x = x + 1U ;
printf ( "loop1 x: %dn" , x );
}
}
if (( int ) x <= 10 || ( int ) x >= 20 ) {
while (( int ) x < 20 ) {
x = x + 1U ;
printf ( "loop2 x: %dn" , x );
}
}
if (( int ) x >= 20 && (( int ) x <= 10 || ( int ) x >= 20 )) {
return var0 ;
}
} |
C Ihre Datenstrukturen mit rellic-headergen
Interaktive Dekompilierung mit rellic-xref
Lupe: Ein Experiment mit interaktiver Dekompilierung
| Master | |
|---|---|
| Linux |
Wenn Sie ohne Papiere Probleme mit Rellic haben, bitten Sie um Hilfe im #binary-lifting Kanal des Empire Hacking Slack.
Rellic wird auf Linux -Plattformen unterstützt und wurde auf Ubuntu 22.04 getestet.
Die meisten Abhängigkeiten von Rellic können vom CXX-Common-Repository bereitgestellt werden. Trail of Bits hostet herunterladbare, vorgefertigte Versionen von CXX-Common, was es wesentlich erleichtert, mit Rellic aufzunehmen. Die folgende Tabelle repräsentiert jedoch die meisten Abhängigkeiten von Rellic.
| Name | Version |
|---|---|
| Git | Letzte |
| Cmake | 3.21+ |
| Google Flags | Letzte |
| Google -Protokoll | Letzte |
| Llvm | 16 |
| Klang | 16 |
| Z3 | 4.7.1+ |
Vorgefertigte Docker-Bilder finden Sie in Docker Hub und der GitHub-Paketregistrierung.
Aktualisieren Sie zunächst die Eignung und installieren Sie die Basisabhängigkeiten.
sudo apt update
sudo apt upgrade
sudo apt install
git
python3
wget
unzip
pixz
xz-utils
cmake
curl
build-essential
lsb-release
zlib1g-dev
libomp-dev
doctest-devWenn die Verteilung, auf die Sie sind, keine aktuelle Veröffentlichung von CMake (3.21 oder höher) enthält, müssen Sie sie installieren. Für Ubuntu finden Sie hier https://apt.kitware.com/.
Der nächste Schritt besteht darin, das Rellic -Repository zu klonen.
git clone --recurse-submodules https://github.com/lifting-bits/rellic.git Schließlich bauen und packen wir Rellic auf. Dieses Skript erstellt im aktuellen Arbeitsverzeichnis ein weiteres Verzeichnis, rellic-build . Alle verbleibenden Abhängigkeiten, die Rellic benötigt, werden neben der Repo-Checkout in lifting-bits-downloads im übergeordneten Verzeichnis heruntergeladen und platziert (weitere Details finden Sie in der Option -h Option des Skripts). Dieses Skript erstellt auch installierbare Deb-, RPM- und TGZ -Pakete.
cd rellic
./scripts/build.sh --llvm-version 16
# to install the deb package, then do:
sudo dpkg -i rellic-build/ * .debUm Rellic auszuprobieren, können Sie Folgendes ausführen, wenn Sie eine LLVM -Bitcode -Datei Ihrer Wahl haben.
# Create some sample bitcode or your own
clang-16 -emit-llvm -c ./tests/tools/decomp/issue_4.c -o ./tests/tools/decomp/issue_4.bc
./rellic-build/tools/rellic-decomp --input ./tests/tools/decomp/issue_4.bc --output /dev/stdoutStellen Sie sicher
cmake
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
-DVCPKG_TARGET_TRIPLET=x64-osx-rel
-DRELLIC_ENABLE_TESTING=OFF
-DCMAKE_C_COMPILER= ` which clang `
-DCMAKE_CXX_COMPILER= ` which clang++ `
/path/to/rellic
make -j8Das Docker-Bild sollte eine Umgebung bereitstellen, die Rellic einrichten, erstellen und ausführen kann. Die Docker -Bilder werden von Ubuntu Verison, LLVM -Version und Architektur parametrisiert.
Um das Docker -Bild mit LLVM 16 für Ubuntu 22.04 zu erstellen, können Sie den folgenden Befehl ausführen:
UBUNTU=22.04 ; LLVM=16 ; docker build .
-t rellic:llvm ${LLVM} -ubuntu ${UBUNTU}
-f Dockerfile
--build-arg UBUNTU_VERSION= ${UBUNTU}
--build-arg LLVM_VERSION= ${LLVM}Um den Dekompiler auszuführen, wurde der Einstiegspunkt bereits festgelegt. Stellen Sie jedoch sicher, dass der Bitcode, den Sie zerlegen, dieselbe LLVM -Version wie der Dekompiler und Run:
# Get the bc file
clang-16 -emit-llvm -c ./tests/tools/decomp/issue_4.c -o ./tests/tools/decomp/issue_4.bc
# Decompile
docker run --rm -t -i
-v $( pwd ) :/test -w /test
-u $( id -u ) : $( id -g )
rellic:llvm16-ubuntu22.04 --input ./tests/tools/decomp/issue_4.bc --output /dev/stdoutUm den obigen Befehl mehr zu erklären: mehr:
# Mount current directory and change working directory
-v $( pwd ) :/test -w /testUnd
# Set the user to current user to ensure correct permissions
-u $( id -u ) : $( id -g ) Wir verwenden mehrere Integrations- und Unit -Tests, um Rellic zu testen.
Roundtrip -Tests nehmen C -Code auf, erstellen ihn zu LLVM IR und übersetzen Sie dann, dass IR auf C zurücksetzt. Der Test sieht dann fest, ob das resultierende C erstellt werden kann und ob der übersetzte Code (ungefähr) dasselbe wie das Original ausfällt. Um diese auszuführen, verwenden Sie:
cd rellic-build # or your rellic build directory
CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --verbose --target test Anghabench 1000 ist eine Stichprobe von 1000 Dateien (x 4 Architekturen, also insgesamt 4000 Tests) aus den mit Anghabench ausgestatteten Gesamtprogrammen. Dieser Test prüft nur, ob der Bitcode für diese Programme in C übersetzt wird, nicht die Schönheit oder Funktionalität der resultierenden Übersetzung. Um diesen Test auszuführen, installieren Sie zuerst die erforderlichen Python -Abhängigkeiten in scripts/requirements.txt und dann aus:
scripts/test-angha-1k.sh --rellic-cmd < path_to_rellic_decompiler_exe > Bitte verwenden Sie das folgende Bibtex -Snippet, um Rellic zu zitieren:
@online{rellic,
title={Rellic},
author={Surovič, Marek and Bertolaccini, Francesco},
organization={Trail of Bits},
url={https://github.com/lifting-bits/rellic}
}