Shared libraries
grease
has rudimentary support for binaries that dynamically link against
shared libraries, but with some notable caveats.
Skipping external function calls
Dynamically linked binaries can invoke external functions defined in shared
libraries (e.g., libc
). Unless grease
has an override
available, grease
treats any invocation of a function defined in a shared
library as as no-op. grease
will log that the function is skipped, but it
will otherwise not simulate it at all. If you want to intercept grease
's
behavior when it invokes an external function and have it do something,
consider supplying an override for the function.
Limitations of PLT stub detection
On the architectures that grease
supports, grease
identifies which
functions are external by determining if the function is being invoked from a
PLT stub. Typically, a PLT stub is located in a specially marked .plt
or
.plt.sec
section of the binary.
Unfortunately, reliably identifying PLT stubs is
hard. Therefore, grease
has
(fallible) heuristics for determining which functions have PLT stubs, and it
relies on these heuristics to determine which functions are external (and
therefore should be skipped or not).
Unfortunately, grease
's PLT stub heuristics are not perfect. In particular,
grease
does not have reliable heuristics for detecting PLT stubs that are
located in .plt.got
sections, which are common in x86-64 binaries. If you run
grease
on a binary with a PLT stub that grease
cannot detect, then you will
likely get an error message stating that grease
does not support the
relocation type associated with the PLT stub, e.g.,
grease: Attempted to read from an unsupported relocation type (R_X86_64_GLOB_DAT) at address 0x3ff0.
This may be due to a PLT stub that grease did not detect.
If so, try passing --plt-stub <ADDR>:<NAME>, where
<ADDR> and <NAME> can be obtained by diassembling the
relevant PLT section of the binary
(.plt, .plt.got, .plt.sec, etc.).
If this occurs, then you must supply the address and name of the PLT stub to
grease
yourself. You can do so by passing --plt-stub <ADDR>:<NAME>
to
grease
on the command line, once for each PLT stub. (If you do not know the
name of the PLT stub, it is fine to leave <NAME>
empty.) Reverse engineering
suites such as Ghidra can be effective at
determining PLT stub information.