I'm fiddling around with an old game and am trying to learn how it works. My current experiments include trying to proxy one of the game's DLL.
So I renamed the original DLL.dll to trueDLL.dll, dumped the DLL's exports with dumpbin and created the #pragmas (fine for now, I'll look into .def files later) to generate an "empty" proxy. This worked as expected.
Now, I'd like to redirect some of the functions to my reverse engineered implementations to test if they work. This is where I got stuck. Here's an example: the LogDebug function. The "empty", working pragma in the proxy DLL look like this:
#pragma comment(linker, "/export:?LogDebug##YAXPBDZZ=trueDLL.?LogDebug##YAXPBDZZ,#504")
I thought I could change the pragma like so to redirect the call to my implementation:
#pragma comment(linker, "/export:?LogDebug##YAXPBDZZ=LogInfo,#504")
Running the program, it fails to start because it can't find ?LogDebug##YAXPBDZZ. Some research shows that the ##YAXPBDZZ part isn't exported in my DLL. It appears to be some kind of info represented in the mangled name, but I couldn't find out what it actually means. Ghidra and this demangler aren't helping either, and the only search results are in russian.
Using VS 2019, no project settings are altered.
What is the problem here and how would I go about making this work? Or is there an easier/better way of achieving this? I'd like to avoid hooking the calls in the program exe for now but if I have to, I'll do it.
EDIT - Mangling scheme and compiler
I don't know exactly what was used to create DLL.dll, but according to Ghidra it was visualstudio:unknown. I'd interpret that as a 1998 (game file dates) version of MSVC. I'm using the current MSVC compiler (CL ver. 19).
It'd make sense for a current CL to use the C++ scheme. Looking at this page, and comparing it to the exports, DLL.dll appears to be using the C++ scheme too, but I could be wrong. How do I find this out for sure?
It turns out that the method in my DLL doesn't need the #pragma, as it actually overwrites the desired behaviour. If I define my function like undname.exe says and just add a __declspec(dllexport) in front, everything falls into place nicely.
Related
Basically, I get a console window I don't want to see while writing SDL-windowed applications.
In C, the answer is simple: change your linker SubSystem to Windows; then SDL does the rest. It has a macro that redefines your main to SDL_main, which it calls from inside its own hidden WinMain function. Just make sure you take arguments in your main function and all goes smoothly.
In D, I'm having a little more trouble with it. Upon simply changing the subsystem by passing -L/SUBSYSTEM:WINDOWS to the linker, it informs me that I have declared main, SDL has declared WinMain, and it doesn't know how to deal. I thought changing the signature from void main() to extern(C) int SDL_main(int argc, char*[] argv) would solve the problem, but then the linker says it can't locate any of D's runtime symbols. Might have something to do with the entry point being written in C?
On the other side, my problem might be with how I have set up Derelict. I am working from this repository, which is a live-updated amalgam of all the different Derelict repositories on GitHub. In my VisualD solution, I have three relevant projects: a home-brewed Derelict project containing the source to SDL2 and the Utilities library, and the C-API SDL2 and SDL2main projects as found here. I compile and link to all three resulting libraries -- Derelict and SDL2main are static, SDL2 is dynamic. I am less inclined to say this setup is to blame, because it works just fine save the undying console window.
In the command line passed to DMD, add the linker option -L/SUBSYSTEM:WINDOWS
In case you use dub (which i recommend) and gdc, insert the following into your dub.json file:
"dflags": ["-Wl,--subsystem,windows"]
I was wondering about the BII_IMPLICIT_RULES_ENABLED flag which I had switched off in one of my CMakeLists.txt files, in order to get an OpenGL related block to compile on a Mac, following a suggestion from biicode. This setting is still there and everything works perfectly, but I would like to find out more about it. Could someone explain what it does exactly?
Thanks!
BII_IMPLICIT_RULES_ENABLED activates the addition of system libs to the target that has included certain headers. For example, if your code contains an:
#include "math.h"
And you are in *nix systems, then the library "m" (libm) will be added to your target via TARGET_LINK_LIBRARIES.
You can see the headers that are processed in your cmake/biicode.cmake file, in the HANDLE_SYSTEM_DEPS
My recommendation: Put it to False whenever possible, and handle the required system libs yourself, exactly what you have done. It is something that will be deprecated soon, or at least set to False by default to new projects. This option sometimes causes troubles, if something fails or there is a bug in biicode.cmake, e.g. in the past it tried to add libm to targets also in windows. It will be gradually deprecated and probably substituted by some CMake macros hosted (as in http://www.biicode.com/biicode/cmake) that could be used by users if they decide to, but not automatically as it is done now.
I am giving Gwan a whirl.
Having made it through example code, I started a small project with more than one source file. I now have two problems:
I got a linking error at server startup:
Linking main.cpp: undefined symbol: _ZN7GwanUrl9concatAllEv
(the main file #includes the two other files; all the files are in the csp directory)
As an alternative to having all the files in the /csp directory, I would like to make a library outside of the /csp directory while still using some of the gwan functions. sadly, a tonne of errors follow -- WHEN I GCC from commandline not via G-WAN Startup.
In file included from /home/ec2-user/gwan/include/gwan.h:22,
from Xbufstream.h:10,
from Xbufstream.cpp:10:
/usr/include/time.h:199: error: ‘size_t’ does not name a type
.....
Anyone knows what the gwan g++ argument string looks like?
(odd the 1. and 1. its 1. and 2. in the editor)
First, this is not a linker issue: you have "undefined symbol" rather than "unresolved symbol" as an error.
This is simply an #include issue.
define the main() function in your script.cpp file.
there's a G-WAN folder dedicated to user-defined include files called /gwan/include but you can as well use /csp/my_include.hpp... if you are using the right syntax:
For example, having #include "toto.hpp" in /csp/hello.cpp lets me reach C++ functions defined and implemented in the gwan/include/toto.hpp file (or defined in toto.hpp and implemented in a pre-compiled library linked to your script with #pragma link).
If you rather use #include <toto.hpp> then the SYSTEM INCLUDE PATH will be searched instead (and this will work providing that your library was correctly installed).
If you want to use #include "toto.hpp" for a custom folder that was not setup in the system, you can use G-WAN's #pragma include "../my_folder" directive to specify its PATH or you can explicitely specify it in each include: #include "../my_folder/toto.hpp".
Nothing fancy there, only C/C++ dependancy rules apply (and G-WAN really helps by providing alternate ways that do not involve system settings).
For libraries (see the G-WAN examples for SQLite, Cairo, mySQL, cURL, etc.) you can either use pre-installed libraries that exported their location in SYSTEM variables... or put your library in the /gwan/libraries folder and their include file in the /gwan/include folder.
When writing your own libraries, remember that they need to be pre-compiled. This means that you obviously cannot use G-WAN symbols since your compiler may #include "gwan.h" (to have the definitions) but your linker will not know from where G-WAN symbols can be found. The way around is to always use the G-WAN API from the G-WAN scripts. Your custom libraries must either be general-purpose or buffer any payload intended to be used by G-WAN. No-double copy is needed since G-WAN provides the set_reply() call to let G-WAN use persistent replies built without the reply xbuffer provided by G-WAN servlets.
Now, a last word about linking (which was not the cause of your trouble but could participate to the confusion). If you mix C and C++, use extern C {} to wrap your C++ prototypes called from C (otherwise you will really have "unresolved symbols").
With all this information, you should be ready to face every possible situation.
the issue of referencing gwan.h symbols inside #include files can also be solved by moving all code into the header file, whether its .h or .hpp
its ungraceful but a fix nevertheless. and good enough for the simple extension i wanted.
looking into the /libraries/sqlite3/sqlite.h helped.
#gil, thanks for your time.
I have a program do so some graphics. When I run it interactively, I want it to use OpenGL from the system to provide hardware accelerated graphics. When I run it in batch, I want to be able to redirect it to use the Mesa GL library so that I can use OSMesa functionality to render to an offscreen buffer. The OSMesa functionality is enabled by doing a LoadLibrary/GetProcAddress if the batch start up option is selected.
On Linux, its fairly easy to make this work. By using a wrapper script to invoke the program, I can do something like this:
if [ "$OPTION" = "batch" ]; then
export LD_LIBRARY_PATH=$PATHTO/mesalibs:$LD_LIBRARY_PATH
fi
It is possible to do something this in Windows?
When I try adding a directory to the PATH variable, the program continues to go to the system opengl32.dll. The only way I can get the program to use the Mesa GL/OSMesa shared libraries is to have them reside in the same directory as my program. However, when I do that, the program will never use the system opengl32.dll.
If I've understood what you're saying correctly, the wrong version of opengl32.dll is being loaded when your process starts up, i.e., load-time dynamic linking. There is probably no good way to solve your problem without changing this.
You say you can't use conveniently use run-time dynamic linking (LoadLibrary/GetProcAddress) for opengl32.dll because the calls to it are coming from the Qt library. I presume that the Qt library is itself dynamically linked, however, so you should be able to solve your problem by using run-time linking for it. In this scenario, provided you load opengl32.dll before you load the Qt library, you should be able to explicitly choose which version of opengl32.dll you want to load.
You might want to consider using delayed loading in order to simplify the process of moving from load-time to run-time linking. In this scenario, the first call into the Qt library causes it to be loaded automatically, and you'll just need to explicitly load opengl32.dll first.
There are a few ways you could handle this, depending on the libraries and their names/locations:
If both have the same name (opengl32.dll), then you need to add the Mesa DLL location to the search path such that it is searched before the system directory. The order directories are checked in is detailed here. As you can see, $PATH comes last, after system, so you can't just add the directory to that. However, you can make use of the second step ("The current directory") by setting the working directory to a path containing the mesa files. Generally this means starting the application using an absolute path while in the directory containing the files.
That's still not particularly pleasant, though. If you can, you should use LoadLibrary and check for an environment variable (OPENGL_LIBRARY_PATH) when your app starts up. Assuming the exports from opengl32.dll and Mesa's DLL are the same, you can do something like:
void LoadExports()
{
char location[MAX_PATH];
getenv("OPENGL_LIBRARY_PATH", location);
HMODULE oglLib = LoadLibrary(location);
function1 = GetProcAddress(oglLib, "glVertex2f");
...
}
This will work perfectly fine, doing almost exactly what you want.
However, if you want to do that, you can't import opengl32.dll, which you're probably doing, you have to dynamically link throughout. Make sure not to link against opengl32.lib and you should be fine. Depending on how many functions you use, it may be a pain to set up, but the code can easily be scripted and only needs done once, you can also use static variables to cache the results for the lifetime of the program. It's also possible to use different function names for different libraries, although that takes a bit more logic, so I'll leave the details to you.
Though this should be possible in the cmd window, it seems you're having no luck.
Try: set a variable in your script (RUNNING_IN_SCRIPT=Y) and then parse for that variable in your executable and LoadLibrary from the absolute path of installation - be sure to clear the variable when you exit.
Windows used to search different paths for dynamic libraries, but due to security consideration, the system path is searched first.
You could, however use Delay Load Imports to get a workaround:
If you're using MSVC, you could single-out the DLLs you're interested in loading on your own with /DELAYIMPORT flag to the linker.
Then, override the delay load helper function and use LoadLibrary to find the proper DLL (and not trust it to the system).
After loading the correct DLL, have your helper function just call the original one that will do all the GetProcAddress business by itself.
I'm working on a (rather horrible) project that involves importing a C++ class hierarchy through a dll interface. One of the more horrible details requires me know the 'decorated' names for the various class elements that are exposed - mostly member functions and static data.
There are many ways to achieve this - the assembly listing or map file, dumpbin, a dependency walker, the _FUNCDNAME_ macro, etc. Unfortunately, they all require me to actually compile the code or have the compiled dll - and all I have available is the header files. (That may leave you scratching your head for a minute - just take my word that it truly is a horrible project.)
Now, I can easily concoct something compilable from just the headers and use one of the above approaches. But if I can avoid it, that would be much better. So my question is: is there a way to browse decorated symbol names from within Visual Studio, a la Object Browser? I know that the decoration is technically done at compile time, but Intellisense does so many other things while you type that I'm hoping it might do this too.
If all else fail take that .h, rename it to .cpp, replace all semicolons (;) with
{
#pragma message(__FUNCDNAME__)
}
edit it a little, and compile it. You'll get your list.