title: Intercepting Statically Linked Dependencies of a Dynamically Linked Library
body: <p>I'm trying to debug an API in use by a third party app.
  The third party app has a configuration I had thought impossible:</p>
  <p>The application binary contains exports required by one of its shared library dependencies. That is, they dynamically linked their dependency, but that dependency's dependency is statically linked.</p>
  <p>This is occurring on a MIPS based linux with an ancient kernel.</p>
  <p>I have confirmed this using Ghidra to disassemble the executable/shared library.</p>
  <p>Basically we have the binary and the shared object</p>
  <pre><code>file initApp
  initApp: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
  
  file libhyCoreSdk.so
  libhyCoreSdk.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, stripped
  
  objdump -T libhyCoreSdk.so | grep -i IMP_ISP_Open
  00047900      DF *UND*  00000000 IMP_ISP_Open
  </code></pre>
  <p>initApp calls &quot;coreAvInit&quot; in libhyCoreSdk.so, and then libhyCoreSdk.so calls IMP_ISP_Open() back inside initApp.</p>
  <p>You might be thinking &quot;that's not that unusual, you can do that with callbacks, passing pointers, a call to dlsym etc. etc.&quot; But this isn't any of those things, this is a direct import/export of symbols exactly what you'd expect to see if libhyCoreSdk depended on another shared library.</p>
  <p>All that aside, my real problem is that I am trying to figure out what parameters are being passed by IMP_ISP_Open and LD_PRELOAD does not help this strange/unique circumstance. I have another example application which is calling the same APIs against a shared library version of the API. When I use LD_PRELOAD (loading a little interceptor program I wrote) against that version it works great. But when I use it against this version that links back to the binary, it doesn't work.</p>
  <p>I'm hoping someone has ideas on how I can intercept those API calls.</p>
  <h2>Partial Solution:</h2>
  <p>Daniel Kleinstein has given me a good start. I renamed the target functions from IMP_... to XMP_... (e.g. IMP_ISP_DisableSensor-&gt; XMP_ISP_DisableSensor). Now the IMP_ISP_DisableSensor from my LD_PRELOAD is correctly hit. Unfortunately, I'm still running into trouble. Calling dlsym(RTLD_DEFAULT, &quot;XMP_ISP_DisableSensor&quot;) returns NULL for no obvious reason... This means I can't redirect back to the original function.</p>
  <p>Despite objdump showing this:</p>
  <pre><code>objdump -T initApp_mod | grep -i XMP
  0061fb5c g    DF .text  00000338  Base        XMP_FrameSource_CreateChn
  00613c6c g    DF .text  00000204  Base        XMP_ISP_DisableSensor
  006097f0 g    DF .text  00000eb0  Base        XMP_Encoder_CreateChn
  </code></pre>