kubo / plthook Goto Github PK
View Code? Open in Web Editor NEWHook function calls by replacing PLT(Procedure Linkage Table) entries.
Hook function calls by replacing PLT(Procedure Linkage Table) entries.
@kubo Hello
Thanks for your project, I have a usage question, is it possible to intercept a function with STB_LOCAL binding, because it seems that these functions are not in PLT
Some code:
plthook_t *plthook;
if (plthook_open(&plthook, "libc.so.6") != 0) {
printf("plthook_open error: %s\n", plthook_error());
return -1;
}
if (plthook_replace(plthook, "recv", (void*)my_recv, NULL) != 0) {
printf("plthook_replace error: %s\n", plthook_error());
plthook_close(plthook);
return -1;
}
plthook_close(plthook);
return 0;
}
As root user is it possible to hook dlopen to get reading & writing access on /proc/$pid/mem ?
@redmercury what would be the way to intercept a call of an Android Java or NDK library in my app that calls into some Android core service, let's say Maps or Camera?
@kubo Hello, kubo
Thanks for your great tools, I have a question about usage.
If I wirte a program a
. The program a
use a function b
in LIBRARY B
, function b
calls the function c
in LIBRARY C
. I cant edit the LIBRARY B
and LIBRARY C
, LIBRARY B
is the further wrapper of LIBRARY C
。I use the API provided by LIBRARY B
. Can I use the methods in Readme to hook the function c
in program a
?
If not, can u tell me how to implement this feature?
We have existing DLL that works on C++, C# both runtime.
and we wanted to hook on WSASocketW, WSASocketA but it works fine with C++ base but not working on C# base. (same DLL implementation, but loaded from another executable)
I can see there is WSASocket functions on C++ base using plthook_enum
but C# one does not.
maybe there is difference between IAT mapping on .NET runtime?
The strcmp() at plthook_win32.c:241
sometimes causes a segmentation fault. This is because name
s of entries in plthook->entries
are sometimes null (such as for some entries in "Shell32.dll" on my Windows 10 install).
A simple workaround is to replace plthook_win32.c:241
from
plthook->entries[idx].name = name;
to
plthook->entries[idx].name = name ? name : "(null)";
I want to hook a member function of some class in C++, for example, Helper::func()
class Helper {
public:
void func(){
// do something here...
}
}
But I have not found related document here. Is this possible with plthook? If I want to achieve this, what efforts do I need to make? Thanks in advance.
I really thank you for this library! However,
I got this error using this code:
plthook_t *plthook;
unsigned int pos = 0; /* This must be initialized with zero. */
const char *name;
void **addr;
if (plthook_open(&plthook, filename) != 0)
{
__android_log_print(ANDROID_LOG_ERROR, "Disassembler","plthook_open error: %s\n", plthook_error());
return NULL;
}
So I tried modifying to
static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename)
{
void *hndl = dlopen(filename, RTLD_LAZY /*| RTLD_NOLOAD*/);
struct link_map *lmap = NULL;
if (hndl == NULL) {
set_errmsg("dlopen error: %s", dlerror());
return PLTHOOK_FILE_NOT_FOUND;
}
Then I get this error:
12-25 19:36:12.580 E/linker (954): library "/storage/emulated/0/adaTest/libhello-jni.so" ("/storage/emulated/0/adaTest/libhello-jni.so") needed or dlopened by "/data/app/com.kyhsgeekcode.disassembler-2/lib/arm/libhello-jni.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/com.kyhsgeekcode.disassembler-2/lib/arm:/data/app/com.kyhsgeekcode.disassembler-2/base.apk!/lib/armeabi-v7a", permitted_paths="/data:/mnt/expand:/data/data/com.kyhsgeekcode.disassembler"]
12-25 19:36:12.580 E/Disassembler(954): plthook_open error: dlopen error: dlopen failed: library "/storage/emulated/0/adaTest/libhello-jni.so" needed or dlopened by "/data/app/com.kyhsgeekcode.disassembler-2/lib/arm/libhello-jni.so" is not accessible for the namespace "classloader-namespace"
Do you know how to use it well on android?
I can hook "eglSwapBuffers", "malloc" function, it works well.
But any opengl es function in android platform can not be hooked. I don't know why.
I want to apply custom distortion to any android VR app. Can I use this hook to access its GPU context and hook my custom code to create distortion ?
https://stackoverflow.com/questions/50753051/accessing-android-app-gpu-context
Is it possible to access any VR Android app's GPU context i.e. what images/graphics the other VR app is rendering on screen from our custom app. I want to get the images rendered by other VR app and apply custom distortion. If yes, how can it be achieved?
My idea was to hook a service the the buffer stream, i.e. read whatever is going to be displayed on screen, apply custom distortion/filter and display it back. Will SwapChain from gvr-android-sdk work in this scenario? Reading GPU buffer from an android service and displaying it back. (For now we don't worry about the DRM protection etc. later we'll be askig for permissions)
https://stackoverflow.com/questions/50920427/android-access-vr-apps-gpu-context
HI,
Thank you for a wonderful tool. I was curious why mprotect(PROT_WRITE) was not needed before modifying the PLT on osx? I thought that __TEXT and __LINKEDIT segments did not have write permission?
Hi
I'm trying to hook GLES calls on Android 10 for a Unity apk, but calling library (libunity.so) exports none of the 3 required symbols.
The rest of the libraries in the apk all export _end.
Any ideas? Thanks!
#include "plthook.h"
ssize_t recv(){
ssize_t rv = main();
return rv;
};
int main(){
plthook_t *hook;
plthook_open(&hook, "vulkan.elf");
recv();
};
i compile it with g++ main.cpp
and on the vulkan.elf
i have everything in extern "C"{}
all plhook stuff is in the same directory as main.cpp
how do i solve this?
compiler error =
main.cpp: In function ‘ssize_t recv()’:
main.cpp:12:14: error: ‘main’ was not declared in this scope
12 | ssize_t rv = main();
| ^~~~
I'm writing a library and want to intercept and take some action on any call to fork
. This requires overriding the function in all loaded shared libraries. Users install the interceptor after process start so LD_PRELOAD
is out of the question, and instead I'm using plthook.
Currently, my approach is:
"\x7fELF"
) in /proc/self/maps
plthook_open_by_address(&hook, (void *) address)
plthook_replace(hook, "fork", (void *) my_fork, NULL)
to actually do workplthook_replace(hook, "dlopen", (void *) my_dlopen, NULL)
to intercept and hook any future loaded librariesIs this the most straightforward use of plthook to accomplish the stated goal?
Hi,
Thanks for your great efforts in developing plthook. It is a very useful tool.
While I am going through the code, I found a minor typo in code which in most cases does not affect the correctness but may be wrong sometimes.
I feel both below statements should use dyn->d_un.d_val
instead of dyn->d_un.d_ptr
.
Line 631 in 8bf1499
Line 638 in 8bf1499
It is quite trivial, so I hope I would not bother you too much.
Thanks.
It's not specified where address
can come from - on Linux it would be anything that would be passed to dladdr1
i.e. a pointer to some location in a loaded program header segment.
Hi, I'm looking for a way to hook malloc() inside a library that's loaded via dlopen()
with RTLD_DEEPBIND
. Is this possible with plthook? Thanks!
Hi :)
Thank you for your library, one minor nitpick though: the plthook_replace function takes the function pointer as a void*, and that conversion isn't guaranteed to work per C11 standard, 6.3.2.3 §1 :
"A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer."
So the conversion from/to void* is only guaranteed to work for object pointers, it says nothing about function pointers. However, (C11 standard, 6.3.2.3 §8) :
"A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer."
So an easy fix could be to change void* to void (*)(void), which could be typedef'd to something like plthook_func or similar.
Thanks!
There are two new load commands added in 10.15 / iOS 13 (http://newosxbook.com/articles/13-10.15.html and can be seen in /Applications.Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach-o/loader.h:324
#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */
#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */
Without handling these linker commands, the functionality of the library is restricted to macOS < 10.15
We came across an executable in which the plthook_open_by_handle()
fails as
dlsym()
can't find the __INIT_ARRAY__
and _end
symbols. The _end
symbol
seems to be local in the file:
micha ~/temp/plthook $ nm -CD example | egrep -w "__INIT_ARRAY__|_end"
0111ab6c b _end
It might be because this is executable was extracted from a UPX packed
executable. Unlike _end
the _start
symbol is exported:
001b3d48 T _start
We currently added a call to dlsym(hndl, "_start")
in order to make it
work.
I tested codes like below but get no such function
error. Is there something wrong and how to know which function could be hooked? BTW, I used same way to hook puts
function is ok. thanks!
static void* (*malloc_hook_func)(size_t size);
static void* malloc_hook(size_t size)
{
char* buffer = (char*) (*malloc_hook_func)(size);
return buffer;
}
// install hook
if (plthook_open_by_address(&plthook, &malloc_hook_func) != 0) {
printf("plthook_open error: %s\n", plthook_error());
return -1;
}
if (plthook_replace(plthook, "malloc", (void*)malloc_hook, (void**)&malloc_hook_func) != 0) {
printf("plthook_replace error: %s\n", plthook_error());
plthook_close(plthook);
return -1;
}
malloc_hook_func = (void* (*)(size_t size))dlsym(RTLD_DEFAULT, "malloc");
hello, how to hook function from vtable with plthook on android armv7-a?
i tried this
if(plthook_replace(plthook, "_ZN25StartMenuScreenController4tickEv", (void*)my_startMenuTick, (void**)&startMenuTick) != 0) return 1;
static unsigned int (*startMenuTick)(void *thiz);
static unsigned int my_startMenuTick(void *thiz) { __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "%s\n", "my_startMenuTick"); }
but "my_startMenuTick" message is not shown via logcat, although messages from other functions are displayed
and there were no errors while applying the hook
i got an error as the tittle when hook eglSwapBuffers function, any idea how to fix it
#include <iostream>
#include <thread>
#include <string>
#include "plthook/plthook.h"
int mop(void);
ssize_t recv(){
ssize_t rv = mop();
return rv;
};
int main(){
plthook_t *hook;
plthook_open(&hook, "vulkan.elf");
recv();
};
where i get
/usr/bin/ld: /tmp/ccjaXJTy.o: in function `recv()':
main.cpp:(.text+0x9): undefined reference to `mop()'
/usr/bin/ld: /tmp/ccjaXJTy.o: in function `main':
main.cpp:(.text+0x42): undefined reference to `plthook_open'
collect2: error: ld returned 1 exit status
the same with plthook_open_by_address
i tried compiling it including the plthook_elf.c
and got
plthook_elf.c: In function ‘int plthook_open_real(plthook_t**, link_map*)’:
plthook_elf.c:655:26: error: invalid conversion from ‘void*’ to ‘plthook_t*’ {aka ‘plthook*’} [-fpermissive]
655 | *plthook_out = malloc(sizeof(plthook_t));
| ~~~~~~^~~~~~~~~~~~~~~~~~~
| |
| void*
any help?
compiling with g++
When i hook read/write of socket function on macOS Platform as follows, it reported "segmentation fault".
ssize_t hook_read(int fildes, void *buf, size_t nbyte) {
ssize_t rv;
rv = read(fildes, buf, nbyte);
printf("Hook read end\n");
return rv;
}
void install_hook() {
plthook_t *plthook;
void *handle;
// const char *filename = "/usr/lib/libc.dylib"; // this also not work
const char *filename = "/usr/lib/libSystem.B.dylib";
if (plthook_open(&plthook, filename) != 0) {
printf("plthook_open error: %s\n", plthook_error());
return;
}
if (plthook_replace(plthook, "read", (void*)hook_read, NULL) != 0) {
printf("plthook_replace error: %s\n", plthook_error());
plthook_close(plthook);
return;
}
plthook_close(plthook);
}
Removed for impermanence
GetModuleHandleEx
will increments the module's reference count.
Please add flag GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
Line 383 in a1bbcea
PATH_MAX
is not enough to have as buffer size as it may be the reason of overflow in fgets
used below
Probably, it's better to use something like char buf[PATH_MAX + 128]
...
UPDATE:
Here is the kernel part which generates content of /proc/self/maps
and there are no explicit limits in line length: https://elixir.bootlin.com/linux/latest/source/fs/proc/task_mmu.c#L300
Line 428 in 8fbdd8d
fclose(fp);
is missing
Line 374 in 85dad50
I am working on 64-bit ubuntu20.04.
I was learning ELF and hook recently, so I found pltkook.
plthook is so cool,plthook is a very useful tool,
I learned how to hook a dynamic library function, thanks.
but I found a fatal error,
I think ... lmap is equal to hndl,
so, if hndl is invalid after dlclose, lmap is invalid too.
I add memset into here:
if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {
set_errmsg("dlinfo error");
dlclose(hndl);
return PLTHOOK_FILE_NOT_FOUND;
}
dlclose(hndl);
memset(hndl, 0x00, 16+1);
return plthook_open_real(plthook_out, lmap);
lmap's l_addr and l_ld are invalid,then the program crashed
how about adding the hndl into struct plthook:
struct plthook {
void* hndl;
const Elf_Sym *dynsym;
const char *dynstr;
size_t dynstr_size;
const char *plt_addr_base;
const Elf_Plt_Rel *rela_plt;
size_t rela_plt_cnt;
#ifdef R_GLOBAL_DATA
const Elf_Plt_Rel *rela_dyn;
size_t rela_dyn_cnt;
#endif
};
Can you reply me?
thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.