Last active
January 1, 2025 18:21
-
-
Save Romern/bd39b3b486e420fff1b0be7551cbfd3a to your computer and use it in GitHub Desktop.
Calling a c++ class constructor and a function on that constructor using Frida
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
class Greeter { | |
private: | |
std::string message; | |
public: | |
Greeter(const std::string& msg) : message(msg) {} | |
void sayHello() const { | |
std::cout << message << std::endl; | |
} | |
}; | |
int main() { | |
Greeter greeter("Hello, World!"); | |
greeter.sayHello(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// std::string has some more needed fields apparently, so simply calling allocUtf8String is not enough | |
// but calling readUtf8String() is enough | |
// note that this is library specific | |
function allocateStdString(stringData) { | |
var ptrToStr = Memory.allocUtf8String(stringData); | |
var stringObjectPointer = Memory.alloc(Process.pointerSize); | |
var stringConstructorPointer = Module.findExportByName(null, '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm'); | |
var stringConstructor = new NativeFunction(stringConstructorPointer, 'void', ['pointer', 'pointer', 'ulong']); | |
stringConstructor(stringObjectPointer, ptrToStr, stringData.length); | |
return stringObjectPointer; | |
} | |
function findSymbolByName(moduleName, symbolName) { | |
var symbols = Module.enumerateSymbols(moduleName); | |
return symbols.find(function(sym) { | |
return sym.name === symbolName; | |
}); | |
} | |
// actual code | |
function instantiateAndCallObject() { | |
var exampleObject = Memory.alloc(Process.pointerSize); | |
var printString = allocateStdString('Test!'); | |
GreeterConstructor(exampleObject, printString); | |
SayHello(exampleObject); | |
} | |
// definining functions | |
var constructorAddress = findSymbolByName('a.out', '_ZN7GreeterC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE').address; | |
var sayHelloAddress = Module.findExportByName(null, '_ZNK7Greeter8sayHelloEv'); | |
var GreeterConstructor = new NativeFunction(constructorAddress, 'void', ['pointer', 'pointer']); | |
var SayHello = new NativeFunction(sayHelloAddress, 'void', ['pointer']); | |
// for exiting the program before the usual main function is called | |
var exit = new NativeFunction(Module.findExportByName(null, 'exit'), 'void', ['int']); | |
// run the code right before main is called, as std::cout needs to be initialized somehow | |
Interceptor.attach(Module.findExportByName(null, 'main'), { | |
onEnter: function (args) { | |
console.log('Got into main(), running code...'); | |
instantiateAndCallObject(); | |
console.log('Ran code!'); | |
exit(0); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment