avast / avast/retdec

Can't use C++ library

Open
#920 5 comments 0 reactions 0 assignees View on GitHub
Q-question
Dominant language
C++
Stars
8.6k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

Hi, thank you for making this project available to the community.

I have a problem when using the new retdec C++ library and the LLVM framework.
If i use both of them separate, they work just fine. The problem is when the two are in the same program.

Using libraries:
Retdec: https://github.com/avast/retdec/commit/6ed327e30fd2bbd45767ff45eae7cfd63fdfc2f1
LLVM: https://github.com/llvm/llvm-project/releases/tag/llvmorg-11.0.1

I compiled both of them and installed system wide.

I copied the example program in the retdec blog post: https://engineering.avast.io/retdec-v4-0-is-out/ - "4. retdec library"
And i copied the LLVM example program Fibonacci: https://github.com/llvm/llvm-project/tree/main/llvm/examples/Fibonacci
This is my final code:

lift_jit_pass.cpp
```cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace llvm;

// Function in the LLVM Fibonacci example
static Function *CreateFibFunction(Module *M, LLVMContext &Context) {
// Create the fib function and insert it into module M. This function is said
// to return an int and take an int parameter.
FunctionType *FibFTy = FunctionType::get(Type::getInt32Ty(Context),
{Type::getInt32Ty(Context)}, false);
Function *FibF =
Function::Create(FibFTy, Function::ExternalLinkage, "fib", M);

// Add a basic block to the function.
BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF);

// Get pointers to the constants.
Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1);
Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2);

// Get pointer to the integer argument of the add1 function...
Argument *ArgX = &*FibF->arg_begin(); // Get the arg.
ArgX->setName("AnArg"); // Give it a nice symbolic name for fun.

// Create the true_block.
BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF);
// Create an exit block.
BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF);

// Create the "if (arg <= 2) goto exitbb"
Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond");
BranchInst::Create(RetBB, RecurseBB, CondInst, BB);

// Create: ret int 1
ReturnInst::Create(Context, One, RetBB);

// create fib(x-1)
Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB);
CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB);
CallFibX1->setTailCall();

// create fib(x-2)
Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB);
CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB);
CallFibX2->setTailCall();

// fib(x-1)+fib(x-2)
Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2,
"addresult", RecurseBB);

// Create the return instruction and add it to the basic block
ReturnInst::Create(Context, Sum, RecurseBB);

return FibF;
}

int main(int argc, char *argv[]) {
// retdec example program

if (argc != 2) {
llvm::errs() << "Expecting path to input\n";
return 1;
}
std::string input = argv[1];

retdec::common::FunctionSet fs;
retdec::LlvmModuleContextPair llvm = retdec::disassemble(input, &fs);

// Dump entire LLVM IR module.
llvm::outs() << *llvm.module;

// Dump functions, basic blocks, instructions.
for (auto &f : fs) {
llvm::outs() << f.getName() << " @ ";
std::cout << f << "\n";
for (auto &bb : f.basicBlocks) {
llvm::outs() << "\t"
<< "bb @ ";
std::cout << bb << "\n";
// These are not only text entries.
// There is a full Capstone instruction.
for (auto *i : bb.instructions) {
llvm::outs() << "\t\t" << retdec::common::Address(i->address) << ": "
<< i->mnemonic << " " << i->op_str << "\n";
}
}
}

// LLVM Fibonacci example

int n = argc > 1 ? atol(argv[1]) : 24;

InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
LLVMContext Context;

// Create some module to put our function into it.
std::unique_ptr Owner(new Module("test", Context));
Module *M = Owner.get();

// We are about to create the "fib" function:
Function *FibF = CreateFibFunction(M, Context);

// Now we going to create JIT
std::string errStr;
ExecutionEngine *EE =
EngineBuilder(std::move(Owner))
.setErrorStr(&errStr)
.create();

if (!EE) {
errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr
<< "\n";
return 1;
}

errs() << "verifying... ";
if (verifyModule(*M)) {
errs() << argv[0] << ": Error constructing function!\n";
return 1;
}

errs() << "OK\n";
errs() << "We just constructed this LLVM module:\n\n---------\n" << *M;
errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n";

// Call the Fibonacci function with argument n:
std::vector Args(1);
Args[0].IntVal = APInt(32, n);
GenericValue GV = EE->runFunction(FibF, Args);

// import result of execution
outs() << "Result: " << GV.IntVal << "\n";

return 0;
}
```

CMakeLists.txt
```CMake
cmake_minimum_required(VERSION 3.13.4)
project(lift_jit_pass)

find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

find_package(retdec REQUIRED
COMPONENTS
retdec
llvm
)
message(STATUS "Found retdec ${retdec_PACKAGE_VERSION}")
message(STATUS "Using retdecConfig.cmake in: ${retdec_DIR}")

# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.

set(CMAKE_CXX_STANDARD 20)

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
message(STATUS "retdec_INCLUDE_DIRS ${retdec_INCLUDE_DIRS}")
message(STATUS "retdec_DEFINITIONS ${retdec_DEFINITIONS}")
message(STATUS "LLVM_INCLUDE_DIRS ${LLVM_INCLUDE_DIRS}")
message(STATUS "LLVM_DEFINITIONS ${LLVM_DEFINITIONS}")

add_compile_options(-no-pie)

# Now build our tools
add_executable(lift_jit_pass lift_jit_pass.cpp)

# Link against LLVM and retdec libraries
target_link_libraries(lift_jit_pass
retdec::retdec
retdec::deps::llvm
)
target_link_libraries(lift_jit_pass LLVM)
```

Problem when running:
```bash
~/.../Thesis/build >>> rm -rf * && cmake ../ && make && ./lift_jit_pass a.out
zsh: sure you want to delete all 5 files in /home/REDACTED/Builds/Thesis/build [yn]? y
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found LLVM 11.0.1
-- Using LLVMConfig.cmake in: /usr/local/lib/cmake/llvm
-- Found OpenSSL: /usr/lib/libcrypto.so (found suitable version "1.1.1i", minimum required is "1.0.1")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found ZLIB: /usr/lib/libz.so (found version "1.2.11")
-- Found retdec
-- Using retdecConfig.cmake in: /usr/local/share/retdec/cmake
-- retdec_INCLUDE_DIRS
-- retdec_DEFINITIONS
-- LLVM_INCLUDE_DIRS /usr/local/include
-- LLVM_DEFINITIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
-- Configuring done
-- Generating done
-- Build files have been written to: /home/REDACTED/Builds/Thesis/build
Scanning dependencies of target lift_jit_pass
[ 50%] Building CXX object CMakeFiles/lift_jit_pass.dir/lift_jit_pass.cpp.o
[100%] Linking CXX executable lift_jit_pass
[100%] Built target lift_jit_pass
: for the -W option: cl::alias must have argument name specified!
realloc(): invalid pointer
zsh: abort (core dumped) ./lift_jit_pass a.out
```

Does anyone know why is this happening? Maybe the LLVM versions (LLVM 11 and the custom LLVM for retdec) are in conflict.

Another question: I know that i can't compile the program again to the binary form and that means that i can't JIT it using LLVM right? Only make manual analysis. Is this correct? I have read other issues in github that state this (the re-compile part).

PS. (not related): My objective is to make a tool or framework to deobfuscate obfuscated binaries by lifting them and apply deobfuscation techniques to it.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with lift_jit_pass.cpp and CMakeLists.txt, then reproduce the reported cmake, make, and ./lift_jit_pass a.out command. Compare the RetDec and LLVM installations and the linked libraries, focusing on the reported cl::alias and realloc errors. Done means the compatibility question and the JIT/decompilation limitation are answered with evidence from this setup.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, cpp
Domain
compilers, reverse-engineering
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
18/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.