2

I'm working with 2 third party DLLs (let's A.dll and B.dll), which I don't have the source code, only the compiled DLL. I know A.dll uses the main function from B.dll, and they both works perfectly. However, I need to do some other stuff, so I wrote my own DLL (let's call C.dll) and added its funtions to A.dll import table.

Now I need A.dll to call these functions, just like it does evoking B.dll function.

I used CFF Explorer to add C.dll functions as import to A.dll, but my functions are not being executed. I need this to be done this way, since the main .exe file (which I don't have the source code aswell) will call A.dll on startup.

Thanks for help! :)

2 Answers 2

2

The proper way to do this is to rename your A.DLL to another name (let's call it Z.DLL), and then create a new A.DLL which is your code. For each export in the Z.DLL, you create an export in your A.DLL with the same name of the function but coming from Z.DLL.

For example, if Z.DLL exports "MySuperFunction", your A.DLL will export table entry for "MySuperFunction" will point to the string "Z.MySuperFunction, instead of code in your DLL. If you need to to additional work before calling the original function, then you can import the original function from Z.DLL, and your export code will be the code that you want to run first.

2
  • Thanks for support. I managed to a workaround, I put my code on DLL entrypoint, since this function is loades as soon as the OS loads the DLL. But your solution seems way better. How can I "redirect" the calls from my C.dll to A.dll? I mean, I don't have theri .h files.
    – VIRGO
    Commented Feb 13, 2022 at 14:56
  • ... aka "DLL placement attack". I also think it's also worthwhile to point out that those are function forwarders and perhaps refer to kernel32.dll as a source for function forwarders into ntdll.dll as a showcase.
    – 0xC0000022L
    Commented Feb 22, 2022 at 7:52
0

Reading @peter_ferrie's answer, this sounds a lot like the proxy DLL that I made once, so I'll add some details as to how I went about it.

I'll continue the naming scheme from peter's answer, so Z.DLL is the renamed original and A.DLL is your DLL (with Z.DLLs original name).

First, I ran dumpbin /EXPORTS on the Z.DLL, resulting in a list of all exports of that DLL. I then wrote a script that took the list and generated a header file that contained one statement like this for each function Z.DLL exported:

#pragma comment(linker, "/export:[mangled_func_name]=[Z.DLL_name].[mangled_func],@[func_ordinal]")

These need to be mangled names, and the field [Z.DLL_name] shouldn't contain the file extension!

You should now be able to include this header in your DLL and compile it. Put your A.DLL in the program's directory and you now have an "empty" proxy DLL. It only forwards the function calls through your A.DLL to the original Z.DLL for now though, which is thw work of these pragmas.

To do something interesting, you need to

  1. find the mangled name of the function you want to replace
  2. run it through undname to get the unmangled signature
  3. add a function with that signature to your A.DLL
  4. mark your function to be exported using e.g. __declspec(dllexport)
  5. delete the corresponding #pragma in your header

Voilà! The program now calls your custom function in A.DLL while everything else is passed to Z.DLL.

If you need to call the original function, you should be able to do that using LoadLibrary and GetProcAddress, but I haven't done this before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.