简体   繁体   中英

How to manipulate function pointers at compile time, and make calls to them, in LLVM IR

Simply put, I am trying to create an LLVM function pass that obfuscates a function's execution. The idea is that we:

  • Clone the function
  • Hollow out the original function
  • Get a pointer to the clone function
  • Encrypt the pointer at compile-time (as simple as an addition or subtraction at this stage)
  • Create a set of instructions inside the original function that decrypt the pointer at run-time , before calling it.

The IR below is a result of the pass running on a test C program's 'main' function. The function's original code (clone function) is irrelevant.

main_clone_ptr 's creation:

cloneFnPtr = m.getOrInsertGlobal("main_clone_ptr", PointerType::get(cloneFn->getFunctionType(), 0));
cloneFnPtr->setInitializer(cloneFn);

The IR:

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main(i32 noundef %0, i8** noundef %1) #0 
{
  %3 = add i32 (i32, i8**)** @main_clone_ptr, i32 -149 // Decrypt the pointer
  br label %callfn

callfn:
  %5 = load i32 (i32, i8**)*, i32 (i32, i8**)** %3, align 8 // Load the address
  %6 = call i32 %5() // Call
  br label %end

end:
  ret i32 %6
}

The issue is that main_clone_ptr still holds the original address of main, as I haven't figured out a way to modify the address at compile-time .. so, to my question; is this even possible? if so, how do I get that address and modify it when I need to.

I've tried something like this:

Constant* initializer = cloneFnPtr->getInitializer();
const ConstantInt* constInt = cast<ConstantInt>(initializer);

// Get value
uint64_t constIntValue = constInt->getZExtValue();

// Encrypt the value
constIntValue -= modifierVal; // constIntValue - (-149)

// Set the value back
cloneFnPtr->setInitializer(ConstantInt::get(builder.getInt64Ty(), constIntValue));

However, this doesn't seem to work at all. I have a feeling I may am doing multiple things wrong here, however I'm not sure, as I'm not well versed in LLVM knowledge.

The address of the function is finally resolved via a multi-stage process that involves a linker at the compilation time and dynamic linker at application loading time. So, no in general you cannot do it this way on LLVM IR level simply because the final function address is not quite constant at this stage

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM