Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Hook function calls by replacing PLT(Procedure Linkage Table) entries.

NotificationsYou must be signed in to change notification settings

kubo/plthook

Repository files navigation

tests

What is plthook.

A utility library to hook library function calls issued byspecified object files (executable and libraries). This modifiesPLT (Procedure Linkage Table) entries inELF format used on most UnixesorIAT (Import Address Table) entries in PE format used on Windows.

What is PLT (or IAT)

Note: This isn't precise explanation. Some details are omitted.

When a function calls another function in another file, it is called via PLT (onUnix using ELF) or IAT (on Windows).

figure1

In order to callfoo_func() inlibfoo.so, the address of the callee must beknown. When callers are in the same file, the relative address to the callee isknown at compile time regardless of the absolute address at run time. Sosome_func() callsfoo_func() using relative addressing.

When callers are in other files, the address of the callee cannot be known atcompile time. To resolve it, each file has a mapping from external function namesto addresses. The callers directly look at the address in the PLT entry forfoo_func() and jump to the address.

The addresses in PLT entries are resolved (1) at process startup or (2) at firstfunction call (lazy binding). It depends on OSes or on settings.

What plthook does.

figure2

Plthook changes the address in PLT entries as above.Whenfoo_func() is called fromprogram,hook_foo_func() is called instead.It doesn't change function calls fromlibfoo.so andlibbar.so.

How to call original functions from hook functions.

When hook functions are outside of modified files

figure3

When the hook functionhook_foo_func() is inlibbar.so, just call theoriginal functionfoo_func(). It looks the PLT entry inlibbar.so and jumpsto the original.

When hook functions are inside of modified files

figure4

When the hook functionhook_foo_func() is inprogram, do not call theoriginal functionfoo_func() because it jumps tohook_foo_func() repeatedlyand crashes the process after memory for stack is exhausted. You need to get theaddress of the original function and set it to the function pointer variablefoo_func_addr. Use the fourth argument ofplthook_replace() to get theaddress on Windows. Use the return value ofdlsym(RTLD_DEFAULT, "foo_func") onUnixes. The fourth argument ofplthook_replace() isn't available on Unixesbecause it doesn't set the address of the original before the address in the PLTentry is resolved.

Changes

2024-09-02: Fix issues on macOS (#48)

2024-08-05: Addplthook_enum_with_prot() to enumerate entries with memory protection information. (plthook_elf.c and plthook_osx.c)

2023-06-01: Add riscv support. (plthook_elf.c) (#45)

2022-09-19: Drop macOS 32-bit application support. Drop support for macOS 10.14 Mojave or before.

2022-08-12: Support LC_DYLD_CHAINED_FIXUPS on macOS intel

2020-03-30: Check _start also in plthook_open_by_handle() (plthook_elf.c) (#29)

2020-03-09: Add support for uClibc. (#28)

2019-11-14: Fix potential incorrect parsing of /proc/self/maps on linux. (#24)

2019-11-14: Fix possible double-close issue in plthook_elf.c (#23)

2019-09-27: Fix resource leaks when the format of /proc/self/maps is unexpected on Linux. (#20)

2019-09-26: Fix SEGV when plthook_open(..., "/usr/lib/libc.dylib") on macOS. (#19)

2019-02-17: Supportplthook_open_by_address() and changeinternal logic ofplthook_open() on Android.

2019-02-17: Stop checking RELRO and check memory protection atruntime instead.

2019-02-03: Fix crash when programs are compiled with compiler options-Wl,-z,relro and-fno-plt with the help ofJC Liang. (#10)

2018-02-06: Android support was contributed byDaniel Deptford.

2017-10-01:plthook_elf.c was rewritten. Plthook had needed toread files on filesystem to get various information about targetobject files. It now do it only for full RELRO object files.Note that plthook before 2017-10-01 gets segmentation fault whilehooking aprelinked file on Linux.

2017-09-18: Fixed for processes onvalgrind on Linux.

Usage

If you have a librarylibfoo.so.1 and want to intercepta function callrecv() without modifying the library,putplthook.h andplthook_elf.c,plthook_win32.c orplthook_osx.cin your source tree and add the following code.

#include"plthook.h"/* This function is called instead of recv() called by libfoo.so.1  */staticssize_tmy_recv(intsockfd,void*buf,size_tlen,intflags){ssize_trv;        ...doyourtask:logging,etc. ...rv=recv(sockfd,buf,len,flags);/* call real recv(). */    ...doyourtask:logging,checkreceiveddata,etc. ...returnrv;}intinstall_hook_function(){plthook_t*plthook;if (plthook_open(&plthook,"libfoo.so.1")!=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);return0;}

The above code doesn't work whenmy_recv() is in the file opened byplthook_open() as describedhere.Use the following code instead in the case.

staticssize_t (*recv_func)(intsockfd,void*buf,size_tlen,intflags);/* This function is called instead of recv() called by libfoo.so.1  */staticssize_tmy_recv(intsockfd,void*buf,size_tlen,intflags){ssize_trv;        ...doyourtask:logging,etc. ...rv= (*recv_func)(sockfd,buf,len,flags);/* call real recv(). */    ...doyourtask:logging,checkreceiveddata,etc. ...returnrv;}intinstall_hook_function(){plthook_t*plthook;if (plthook_open_by_address(&plthook,&recv_func)!=0) {printf("plthook_open error: %s\n",plthook_error());return-1;    }if (plthook_replace(plthook,"recv", (void*)my_recv, (void**)&recv_func)!=0) {printf("plthook_replace error: %s\n",plthook_error());plthook_close(plthook);return-1;    }#ifndefWIN32// The address passed to the fourth argument of plthook_replace() is// available on Windows. But not on Unixes. Get the real address by dlsym().recv_func= (ssize_t (*)(int,void*,size_t,int))dlsym(RTLD_DEFAULT,"recv");#endifplthook_close(plthook);return0;}

Note that built-in functions cannot be hooked. For example the Ccompiler in macOS Sierra compilesceil() as inline assembly code,not as function call ofceil in the system library.

When a functions is imported byordinal on Windows,the function name is specified byexport_dll_name:@ordinal.For exampleapi-ms-win-shcore-path-l1-1-0.dll:@170.

Another Usage

PLTHook provides a function enumerating PLT/IAT entries.

voidprint_plt_entries(constchar*filename){plthook_t*plthook;unsignedintpos=0;/* This must be initialized with zero. */constchar*name;void**addr;if (plthook_open(&plthook,filename)!=0) {printf("plthook_open error: %s\n",plthook_error());return-1;    }while (plthook_enum(plthook,&pos,&name,&addr)==0) {printf("%p(%p) %s\n",addr,*addr,name);    }plthook_close(plthook);return0;}

Supported Platforms

Platformsource filestatus
Linux i386 and x86_64plthook_elf.ctested usinggithub actions
Linux arm, aarch64, powerpc and powerpc64leplthook_elf.ctested onQEMU usinggithub actions
Windows 32-bit and x64 (MSVC)plthook_win32.ctested usinggithub actions
macOS (intel) (*4)plthook_osx.ctested usinggithub actions
macOS (arm)plthook_osx.ctested usinggithub actions
Windows 32-bit and x64 (Mingw32 and Cygwin)plthook_win32.cperhaps(*2)
Solaris x86_64plthook_elf.cperhaps(*1)
FreeBSD i386 and x86_64 except i386 program on x86_64 OSplthook_elf.cperhaps(*1)
Android(*3)plthook_elf.cperhaps(*2)

*1 Tested on a local VM before.
*2 Tested on travis-ci.org before.
*3 Contributed byDaniel Deptford.
*4 macOS 10.14 Mojave support was dropped on 2022-09-19.

License

2-clause BSD-style license.

About

Hook function calls by replacing PLT(Procedure Linkage Table) entries.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp