Rellicは、LLVMビットコードからGOTOフリーC出力を生成するためのパターンに依存しない構造化アルゴリズムの実装です。
プロジェクトの背後にある設計哲学は、他のLLVMおよびレミルプロジェクトとの優れた相互運用性を備えた比較的小さくて簡単にハッキング可能なコードベースを提供することです。
| オリジナルプログラム | -emit-llvm -O0でコンパイルされ、逆コンパイルされました |
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 rellic-headergenを使用したデータ構造
rellic-xrefとのインタラクティブな逆コンパイル
拡大器:インタラクティブな逆コンパイルを使用した実験
| マスター | |
|---|---|
| Linux |
Rellicで文書化されていない問題が発生している場合は、帝国のハッキングスラックの#binary-liftingチャネルで助けを求めてください。
RellicはLinuxプラットフォームでサポートされており、Ubuntu 22.04でテストされています。
Rellicの依存関係のほとんどは、CXX-Commonリポジトリによって提供できます。 Trail of Bitsは、ダウンロード可能な事前に構築されたバージョンのCXX-Commonをホストしているため、Rellicで起動して実行しやすくなります。それにもかかわらず、次の表はRellicの依存関係のほとんどを表しています。
| 名前 | バージョン |
|---|---|
| git | 最新 |
| cmake | 3.21+ |
| Google Flags | 最新 |
| Googleログ | 最新 |
| LLVM | 16 |
| クラン | 16 |
| Z3 | 4.7.1+ |
事前に構築されたDocker画像は、Docker HubとGitHubパッケージレジストリで入手できます。
まず、適性を更新し、ベースライン依存関係をインストールします。
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-devあなたが使用している分布に、Cmakeの最近のリリース(3.21以降)が含まれていない場合、インストールする必要があります。 ubuntuについては、https://apt.kitware.com/を参照してください。
次のステップは、Rellic Repositoryをクローンすることです。
git clone --recurse-submodules https://github.com/lifting-bits/rellic.git最後に、Rellicを構築およびパッケージ化します。このスクリプトは、現在の作業ディレクトリに別のディレクトリ、 rellic-buildを作成します。 Rellicが必要とする残りの依存関係はすべてダウンロードされ、 lifting-bits-downloadsのレポアウトチェックアウトとともに親ディレクトリに配置されます(詳細については、スクリプトの-hオプションを参照)。このスクリプトは、インストール可能なDEB、RPM、およびTGZパッケージも作成します。
cd rellic
./scripts/build.sh --llvm-version 16
# to install the deb package, then do:
sudo dpkg -i rellic-build/ * .debRellicを試すには、選択したLLVMビットコードファイルを考慮して、以下を実行できます。
# 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/stdoutLLVM 16のCXX-Commonの最新リリースを必ず用意してください。
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 -j8Docker画像は、レリックをセットアップ、構築、および実行できる環境を提供する必要があります。 Docker画像は、Ubuntu Verison、LLVMバージョン、およびアーキテクチャによってパラメーター化されています。
Ubuntu 22.04のLLVM 16を使用してDocker画像を構築するには、次のコマンドを実行できます。
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}逆コンパイラを実行するには、エントリポイントが既に設定されていますが、DecompiledのビットコードがDecompilerと同じLLVMバージョンであることを確認し、実行してください。
# 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/stdout上記のコマンドを詳細に説明するには:
# Mount current directory and change working directory
-v $( pwd ) :/test -w /testそして
# Set the user to current user to ensure correct permissions
-u $( id -u ) : $( id -g ) いくつかの統合とユニットテストを使用して、レリックをテストします。
RoundTripテストでは、Cコードを使用し、LLVM IRにビルドしてから、IRをCに戻します。テストは、結果のCを構築できるかどうか、翻訳されたコードが(ほぼ)元のものと同じことを行うかどうかを確認します。これらを実行するには、使用してください。
cd rellic-build # or your rellic build directory
CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --verbose --target test Anghabench 1000は、Anghabenchに付属する100万のプログラムからの1000ファイル(x 4アーキテクチャなので、合計4000のテスト)のサンプルです。このテストでは、これらのプログラムのビットコードがCに変換されるかどうかをチェックしますが、結果の翻訳のきれいさや機能性はありません。このテストを実行するには、最初にscripts/requirements.txtで見つかった必要なPython依存関係をインストールしてから実行してから実行します。
scripts/test-angha-1k.sh --rellic-cmd < path_to_rellic_decompiler_exe > レリックを引用するには、次のBibtexスニペットを使用してください。
@online{rellic,
title={Rellic},
author={Surovič, Marek and Bertolaccini, Francesco},
organization={Trail of Bits},
url={https://github.com/lifting-bits/rellic}
}