Rellic est une implémentation de l'algorithme de structuration indépendant du motif pour produire une sortie C sans goto à partir de Bitcode LLVM.
La philosophie de conception derrière le projet est de fournir une base de code relativement petite et facilement piratable avec une grande interopérabilité avec d'autres projets LLVM et Remill.
| Programme original | Compilé avec -emit-llvm -O0 et décompilé |
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 vos structures de données avec rellic-headergen
Décompilation interactive avec rellic-xref
Magnifique: une expérience avec une décompilation interactive
| maître | |
|---|---|
| Linux |
Si vous rencontrez des problèmes sans papiers avec Rellic, demandez de l'aide dans le canal #binary-lifting de l'Empire Hacking Slack.
Rellic est pris en charge sur les plates-formes Linux et a été testée sur Ubuntu 22.04.
La plupart des dépendances de Rellic peuvent être fournies par le référentiel cxx-commun. Trail of Bits Hosts Versions téléchargeables et prédéfinies de CXX-Common, ce qui facilite la mise en service avec Rellic. Néanmoins, le tableau suivant représente la plupart des dépendances de Rellic.
| Nom | Version |
|---|---|
| Git | Dernier |
| Cmake | 3.21+ |
| Drapeaux google | Dernier |
| Journal Google | Dernier |
| Llvm | 16 |
| Bruit | 16 |
| Z3 | 4.7.1+ |
Les images docker pré-construites sont disponibles sur Docker Hub et le giber de package GitHub.
Tout d'abord, mettez à jour l'aptitude et obtenez des dépendances de base.
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-devSi la distribution sur laquelle vous vous trouvez n'inclut pas une version récente de CMake (3.21 ou version ultérieure), vous devrez l'installer. Pour Ubuntu, consultez ici https://apt.kitware.com/.
L'étape suivante consiste à cloner le référentiel Rellic.
git clone --recurse-submodules https://github.com/lifting-bits/rellic.git Enfin, nous construisons et emballons Rellic. Ce script créera un autre répertoire, rellic-build , dans le répertoire de travail actuel. Toutes les dépendances restantes nécessaires à Rellic seront téléchargées et placées dans le répertoire parent parallèlement à la caisse du référentiel dans lifting-bits-downloads (voir l'option -h du script pour plus de détails). Ce script crée également des packages Deb, RPM et TGZ installables.
cd rellic
./scripts/build.sh --llvm-version 16
# to install the deb package, then do:
sudo dpkg -i rellic-build/ * .debPour essayer Rellic, vous pouvez effectuer ce qui suit, étant donné un fichier Bitcode LLVM de votre choix.
# 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/stdoutAssurez-vous d'avoir la dernière version de CXX-Common pour LLVM 16. Ensuite, construisez avec
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 -j8L'image Docker doit fournir un environnement qui peut configurer, construire et exécuter Rellic. Les images Docker sont paramétrées par Ubuntu Vérison, la version LLVM et l'architecture.
Pour construire l'image docker en utilisant LLVM 16 pour Ubuntu 22.04, vous pouvez exécuter la commande suivante:
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}Pour exécuter le décompilateur, le point d'entrée a déjà été défini, mais assurez-vous que le bitcode que vous décomposez est la même version LLVM que le décompilateur et exécutez:
# 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/stdoutPour expliquer davantage la commande ci-dessus:
# Mount current directory and change working directory
-v $( pwd ) :/test -w /testet
# Set the user to current user to ensure correct permissions
-u $( id -u ) : $( id -g ) Nous utilisons plusieurs tests d'intégration et unitaires pour tester Rellic.
Les tests aller-retour prendront le code C, le construisent sur LLVM IR, puis traduiront que IR revient à C. Le test voit alors si le C résultant peut être construit et si le code traduit fait (à peu près) la même chose que l'original. Pour les exécuter, utilisez:
cd rellic-build # or your rellic build directory
CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --verbose --target test Anghabench 1000 est un échantillon de 1000 fichiers (architectures X 4, donc un total de 4000 tests) des millions de programmes complets qui sont livrés avec Anghabench. Ce test vérifie uniquement si le code binaire pour ces programmes se traduit par C, et non la joliessse ou la fonctionnalité de la traduction résultante. Pour exécuter ce test, installez d'abord les dépendances Python requises trouvées dans scripts/requirements.txt , puis exécutez:
scripts/test-angha-1k.sh --rellic-cmd < path_to_rellic_decompiler_exe > Veuillez utiliser l'extrait de bibtex suivant pour citer Rellic:
@online{rellic,
title={Rellic},
author={Surovič, Marek and Bertolaccini, Francesco},
organization={Trail of Bits},
url={https://github.com/lifting-bits/rellic}
}