-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace a function without reference to it #27
Comments
Does this mean that
The address is relative to the base address. You can get it if the platform is Linux.
|
Thank you so much! I'm trying this right now and will get back to you as soon as I fully wrap my head aound this.
Yes, just verified that. I can use your above search method to find the address of the function in question, and I can even call it, but puting the address into 24 void patch_via_funchook(void *original_function, void *hook_function) {
25 VALUE funchook_module_wrapper = rb_define_module("Funchook");
26 funchook_path = rb_iv_get(funchook_module_wrapper, "@path");
27
28 void *funchook_lib_handle;
29 void *funchook_reference, *(*funchook_create)(void);
30 int prepareResult, (*funchook_prepare)(void *, void **, void *);
31 int installResult, (*funchook_install)(void *, int);
32
33 funchook_lib_handle = dlopen(StringValueCStr(funchook_path), RTLD_NOW | RTLD_GLOBAL);
34
35 /* Load the funchook methods we need */
36 funchook_create = (void *(*)(void))dlsym(funchook_lib_handle, "funchook_create");
37 funchook_prepare = (int (*)(void *, void **, void *))dlsym( funchook_lib_handle, "funchook_prepare");
38 funchook_install = (int (*)(void *, int))dlsym(funchook_lib_handle, "funchook_install");
39
40 funchook_reference = (void *)(*funchook_create)();
41
42 prepareResult = (*funchook_prepare)(funchook_reference, (void **)original_function, hook_function);
43 installResult = (*funchook_install)(funchook_reference, 0);
44 } Which is probably because as far as I can tell our internal helper also relies on I'm researching further and will update again shortly. Once again, thanks for your help. |
Hey, I reviewed what we're doing, and while it is a bit convoluted, the use of Our Still, the address of The method in question can be found here: I'm not sure if I'm missing something in these statements, but I think these are just other ways to get an address?
The address is what funchook needs to replace a method right? Please advise further, and thanks again! |
Could you explain about this?
Yes, they are other ways to find the base address of the ruby library. |
And I realize I should give you more info to be able to reproduce/investigate, so here's a better rundown. Here is how I get the original (unrelocated) addresses of the functions in question. ➜ lib readelf -Ws libruby.so | grep -i rb_hash_key_str
6433: 00000000001085c0 37 FUNC LOCAL DEFAULT 13 rb_hash_key_str
➜ lib readelf -Ws libruby.so | grep -i rb_p$
362: 000000000011c4b0 247 FUNC GLOBAL DEFAULT 13 rb_p
➜ lib readelf -Ws libruby.so | grep -i rb_hash_aset
1050: 0000000000101ad0 341 FUNC GLOBAL DEFAULT 13 rb_hash_aset
7620: 0000000000101ad0 341 FUNC GLOBAL DEFAULT 13 rb_hash_aset And I just cleaned up and migrated the body of our funchook helper function into one function: static int install_hooks() {
// Original function addresses.
size_t relative_function_address = 0x00000000001085c0; // rb_hash_key_str
// size_t relative_function_address = 0x0000000000101ad0; // rb_hash_aset
// size_t relative_function_address = 0x000000000011c4b0; // rb_p
// Search for relative address of function in shared object library...
struct link_map *lm;
size_t new_addr;
for (lm = _r_debug.r_map; lm != NULL; lm = lm->l_next) {
if (strstr(lm->l_name, "libruby.so") != NULL) {
new_addr = lm->l_addr + relative_function_address;
printf("base address: %lx\n", lm->l_addr);
printf("function address: %lx\n", new_addr);
}
}
// Create reference to original function.
typedef VALUE func(VALUE);
func* rb_hash_key_str_orig = (func*)new_addr;
funchook_t *funchook_reference = funchook_create();
int prepareResult = funchook_prepare(funchook_reference, (void **)&rb_hash_key_str_orig, rb_hash_key_str_hook);
int installResult = funchook_install(funchook_reference, 0);
printf("Hooking results...\n");
printf("Prepare: %d\n", prepareResult);
printf("Install: %d\n", installResult);
fflush(stdout);
return 0;
} Where the hook looks like: VALUE rb_hash_key_str_hook(VALUE key) {
printf("asdf2\n"); fflush(stdout);
return key;
} The output from this is: base address: 7f5f5239d000
function address: 7f5f524a55c0
Hooking results...
Prepare: 0
Install: 0 So, that's how I now know that it succeeds, but unfortunately the behavior of Now to test that the overall method is sound, I switched the function to look like: static int install_hooks() {
// Original function addresses.
// size_t relative_function_address = 0x00000000001085c0; // rb_hash_key_str
// size_t relative_function_address = 0x0000000000101ad0; // rb_hash_aset
size_t relative_function_address = 0x000000000011c4b0; // rb_p
// Search for relative address of function in shared object library...
struct link_map *lm;
size_t new_addr;
for (lm = _r_debug.r_map; lm != NULL; lm = lm->l_next) {
if (strstr(lm->l_name, "libruby.so") != NULL) {
new_addr = lm->l_addr + relative_function_address;
printf("base address: %lx\n", lm->l_addr);
printf("function address: %lx\n", new_addr);
}
}
// Ruby test string.
VALUE mystr = rb_sprintf("blah");
rb_p(mystr);
rb_p(mystr);
rb_p(mystr);
// Create reference to original function.
typedef VALUE func(VALUE);
func* rb_hash_key_str_orig = (func*)new_addr;
funchook_t *funchook_reference = funchook_create();
int prepareResult = funchook_prepare(funchook_reference, (void **)&rb_hash_key_str_orig, rb_hash_key_str_hook);
int installResult = funchook_install(funchook_reference, 0);
printf("Hooking results...\n");
printf("Prepare: %d\n", prepareResult);
printf("Install: %d\n", installResult);
rb_p(mystr);
rb_p(mystr);
rb_p(mystr);
fflush(stdout);
return 0;
} Which uses the same technique to find ruby's This time the results are as expected. base address: 7feb39071000
function address: 7feb3918d4b0
"blah"
"blah"
"blah"
Hooking results...
Prepare: 0
Install: 0
asdf2
asdf2
asdf2 With ruby's |
I need to replace a function in a shared object library (ruby). I'm not sure how to get a function handle for the particular function so that I can replace it.
It's buried in the SO.
Can you please point me in the right direction? I can find the function in the SO via readelf, but the address doesn't match at runtime.
The text was updated successfully, but these errors were encountered: