open-obfuscator/o-mvll

Prebuilt LLVM needs X86 MC backend for JIT execution

junknet opened this issue · 11 comments

OS: Linux manjaro 6.1.38-1-MANJARO #1 SMP PREEMPT_DYNAMIC Wed Jul 5 23:49:30 UTC 2023 x86_64 GNU/Linux
Dokcer build libOMVLL.so.

export OMVLL_CONFIG=/home/junknet/Desktop/test.py
export OMVLL_PYTHONPATH=/home/junknet/Downloads/Python-3.10.7/Lib 
cd  /home/junknet/Downloads/android-ndk-r25c-linux/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin
./aarch64-linux-android21-clang  -fpass-plugin=/home/junknet/Desktop/o-mvll/src/build_ndk_r25/libOMVLL.so /home/junknet/Desktop/kankanshili/src/qwe.cpp -o main

out:
/home/junknet/Downloads/android-ndk-r25c-linux/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-14 -S -emit-llvm -std=c++17 -o /tmp/omvll-x86_64-unknown-linux-gnu-b682cc.cpp.ll /tmp/omvll-x86_64-unknown-linux-gnu-b682cc.cpp
/home/junknet/Downloads/android-ndk-r25c-linux/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-14 -S -emit-llvm -target aarch64-unknown-linux-android21 -std=c++17 -o /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp.ll /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp
No available targets are compatible with triple "x86_64-unknown-linux-gnu"

As mentioned in the documentation Currently, it only supports AArch64 but there is on-going work to support more architectures.

As mentioned in the documentation Currently, it only supports AArch64 but there is on-going work to support more architectures.

I don't quite understand what you mean, are you saying that my development platform also needs to be aarch64 architecture?
I use the ./aarch64-linux-android21-clang compiler. Isn't the target platform aarch64?

I don't quite understand what you mean, are you saying that my development platform also needs to be aarch64 architecture?

Nop but look at your triple in /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp.ll

I don't quite understand what you mean, are you saying that my development platform also needs to be aarch64 architecture?

Nop but look at your triple in /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp.ll

cat omvll-aarch64-unknown-linux-android21-4b8419.cpp.ll

; ModuleID = '/tmp/omvll-aarch64-unknown-linux-android21-4b8419.cpp'
source_filename = "/tmp/omvll-aarch64-unknown-linux-android21-4b8419.cpp"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-android21"

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @encode(i8* noundef %0, i8* noundef %1, i64 noundef %2, i32 noundef %3) #0 {
%5 = alloca i8*, align 8
%6 = alloca i8*, align 8
%7 = alloca i64, align 8
%8 = alloca i32, align 4
%9 = alloca i8*, align 8
%10 = alloca i32, align 4
store i8* %0, i8** %5, align 8
store i8* %1, i8** %6, align 8
store i64 %2, i64* %7, align 8
store i32 %3, i32* %8, align 4
%11 = bitcast i64* %7 to i8*
store i8* %11, i8** %9, align 8
store i32 0, i32* %10, align 4
br label %12

12: ; preds = %36, %4
%13 = load i32, i32* %10, align 4
%14 = load i32, i32* %8, align 4
%15 = icmp slt i32 %13, %14
br i1 %15, label %16, label %39

16: ; preds = %12
%17 = load i8*, i8** %6, align 8
%18 = load i32, i32* %10, align 4
%19 = sext i32 %18 to i64
%20 = getelementptr inbounds i8, i8* %17, i64 %19
%21 = load i8, i8* %20, align 1
%22 = zext i8 %21 to i32
%23 = load i8*, i8** %9, align 8
%24 = load i32, i32* %10, align 4
%25 = sext i32 %24 to i64
%26 = urem i64 %25, 8
%27 = getelementptr inbounds i8, i8* %23, i64 %26
%28 = load i8, i8* %27, align 1
%29 = zext i8 %28 to i32
%30 = xor i32 %22, %29
%31 = trunc i32 %30 to i8
%32 = load i8*, i8** %5, align 8
%33 = load i32, i32* %10, align 4
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds i8, i8* %32, i64 %34
store i8 %31, i8* %35, align 1
br label %36

36: ; preds = %16
%37 = load i32, i32* %10, align 4
%38 = add nsw i32 %37, 1
store i32 %38, i32* %10, align 4
br label %12, !llvm.loop !10

39: ; preds = %12
ret void
}

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @decode(i8* noundef %0, i8* noundef %1, i64 noundef %2, i32 noundef %3) #0 {
%5 = alloca i8*, align 8
%6 = alloca i8*, align 8
%7 = alloca i64, align 8
%8 = alloca i32, align 4
%9 = alloca i8*, align 8
%10 = alloca i32, align 4
store i8* %0, i8** %5, align 8
store i8* %1, i8** %6, align 8
store i64 %2, i64* %7, align 8
store i32 %3, i32* %8, align 4
%11 = bitcast i64* %7 to i8*
store i8* %11, i8** %9, align 8
store i32 0, i32* %10, align 4
br label %12

12: ; preds = %36, %4
%13 = load i32, i32* %10, align 4
%14 = load i32, i32* %8, align 4
%15 = icmp slt i32 %13, %14
br i1 %15, label %16, label %39

16: ; preds = %12
%17 = load i8*, i8** %6, align 8
%18 = load i32, i32* %10, align 4
%19 = sext i32 %18 to i64
%20 = getelementptr inbounds i8, i8* %17, i64 %19
%21 = load i8, i8* %20, align 1
%22 = zext i8 %21 to i32
%23 = load i8*, i8** %9, align 8
%24 = load i32, i32* %10, align 4
%25 = sext i32 %24 to i64
%26 = urem i64 %25, 8
%27 = getelementptr inbounds i8, i8* %23, i64 %26
%28 = load i8, i8* %27, align 1
%29 = zext i8 %28 to i32
%30 = xor i32 %22, %29
%31 = trunc i32 %30 to i8
%32 = load i8*, i8** %5, align 8
%33 = load i32, i32* %10, align 4
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds i8, i8* %32, i64 %34
store i8 %31, i8* %35, align 1
br label %36

36: ; preds = %16
%37 = load i32, i32* %10, align 4
%38 = add nsw i32 %37, 1
store i32 %38, i32* %10, align 4
br label %12, !llvm.loop !12

39: ; preds = %12
ret void
}

attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+neon,+outline-atomics,+v8a" }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"branch-target-enforcement", i32 0}
!2 = !{i32 8, !"sign-return-address", i32 0}
!3 = !{i32 8, !"sign-return-address-all", i32 0}
!4 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 1}
!8 = !{i32 7, !"frame-pointer", i32 1}
!9 = !{!"Android (9352603, based on r450784d1) clang version 14.0.7 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0cca074e9238af8b4106c30add4418f6)"}
!10 = distinct !{!10, !11}
!11 = !{!"llvm.loop.mustprogress"}
!12 = distinct !{!12, !11}

It's only appears in string obfuscation.

Yes, StringEncOpt.* has two parts:

  • decode() is compiled for the target device and injected into the module:
    /home/junknet/Downloads/android-ndk-r25c-linux/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-14 -S -emit-llvm -target aarch64-unknown-linux-android21 -std=c++17 -o /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp.ll /tmp/omvll-aarch64-unknown-linux-android21-f4f132.cpp
  • encode() is compiled for the host machine and executed on-the-fly at compile-time of the module:
    /home/junknet/Downloads/android-ndk-r25c-linux/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-14 -S -emit-llvm -std=c++17 -o /tmp/omvll-x86_64-unknown-linux-gnu-b682cc.cpp.ll /tmp/omvll-x86_64-unknown-linux-gnu-b682cc.cpp

That's why in the LLVM libraries we link against, we need the MC backend for the host platform. @junknet Do you have this issue with the prebuilt dependencies package from https://data.romainthomas.fr/omvll-deps-ndk-r25.tar ?

Yes, StringEncOpt.* has two parts:

* `decode()` is compiled for the target device and injected into the module

* `encode()` is compiled for the host machine and executed on-the-fly at compile-time of the module

That's why in the LLVM libraries we link against, we need the MC backend for the host platform. @junknet Do you have this issue with the prebuilt dependencies package from https://data.romainthomas.fr/omvll-deps-ndk-r25.tar ?

Yeah. I use the following command to build.

$ docker pull openobfuscator/omvll-ndk
$ git clone https://github.com/open-obfuscator/o-mvll.git

$ curl -LO https://data.romainthomas.fr/omvll-deps-ndk-r25.tar
$ mkdir -p ./third-party
$ tar xvf omvll-deps-ndk-r25.tar -C ./third-party
$ docker run --rm                           \
         -v $(pwd)/o-mvll:/o-mvll           \
         -v $(pwd)/third-party:/third-party \
         openobfuscator/omvll-ndk sh /o-mvll/scripts/docker/ndk_r25_compile.sh

Interesting, looking at the script here suggests that the existing package has the X86 backend already:
https://github.com/open-obfuscator/o-mvll/blob/main/scripts/docker/deps/compile_llvm_r25.sh#L1

Can you confirm that @romainthomas ? If so, this must be an issue with target registration in LLVM

Yes I confirm that pre-built LLVM has both architectures

Hey @junknet, would you mind trying the latest release and see if it solves your issue?

Closing this due to inactivity. Please @junknet let us know if this needs to be re-opened.