How to preload library with ld_preload to wine(windows game)? - c

I want to learn how to preload and hook functions in wine running windows apps.
I'm trying to preload a library with ld_preload to wine(windows game(32-bit)) on Arch Linux (64-bit but I think I installed 32-bit support). I get the error wrong ELF class: ELFCLASS32 and the same for ELFCLASS64.
Full error text:
"ERROR: ld.so: object './eve.so' from LD_PRELOAD cannot be preloaded
(wrong ELF class: ELFCLASS32): ignored."
the same for 64bit and another one
ERROR: ld.so: object './eve.so' from LD_PRELOAD cannot be preloaded
(cannot open shared object file): ignored.
How am I getting "wrong class" when I have both 32 and 64-bit installed? What architecture do I need to make it work right?
Wow.exe:
Wow.exe: PE32 executable (GUI) Intel 80386, for MS Windows
I tried to build with and without the -m32 flag ( I changed all uint32 to uint64):
gcc -std=c99 -Wall -Werror -m32 -O0 -fpic -shared -ldl -lGL -o eve.so eve.c
I saw this answer:
ltrace /lib/ld-linux.so.2 --preload /path/to/lib/strcmp.so ./exec
But don't know how to run it with wine running the app.
I want to learn how to preload and hook functions in wine running windows apps. I saw this guide:
https://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/276206-linux-simple-injection-ld_preload.html

The wrong ELF class: ELFCLASS32 means you are trying to inject a 32-bit program into a 64-bit process. This would lead me to believe your game is 64-bit, and you should compile your libraries as 64-bit as well. But since you mention you saw the error for 64-bits as well, it would be best to check your wine installation directly. Run pacman -Q --info wine to check.
The second error message you reported, cannot open shared object file, means the dynamic linker can't find your library. Double check all your file paths. Instead of using the relative import ./eve.so, use a full absolute path (/path/to/lib/eve.so) so there's no ambiguity to the system. You usually want to specify an absolute path to LD_PRELOAD. The reason is that it being an environment variable, it's inherited by child processes - which may have a different working directory than the parent process. So any relative path would fail to locate the library to preload.
As for how to set the environment variable in Wine, wine passes on the entire shell environment variable space to the Windows environment variable space, so you just set the variable in Linux beforehand and it will be available to the game inside wine:
export LD_PRELOAD=/path/to/lib/eve.so
wine ...
As another note, LD_PRELOAD will affect the wine loader only. If you would like to affect wineserver as well:
wineserver -k
export LD_PRELOAD=...
wine ...
Finally, see this post for more details if this still isn't working for you, it's a more in depth explanation of how to do injection into wine specifically.

Related

qemu-arm running compiled binary

Trying to run a compiled binary I've extracted from a firmware on qemu, however I encounter this error:
root#ubuntu14:~# qemu-arm -L /usr/arm-linux-gnueabi ~/x
/system/bin/linker: No such file or directory
root#ubuntu14:~# file ./x
./x: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), stripped
I'm using the "-L" flag, as suggested in:
qemu-arm can't run arm compiled binary
However, this flag doesn't seem to make a different for me, neither does setting QEMU_LD_PREFIX
Could it be some missing dependencies?
It looks like the system is not able to find the dynamic linker (which in your case appears to be /system/bin/linker, rather than the the normal /lib/ld-linux-armhf.so.3 or similar.
Since I don't have access to your code, I've tried to reproduce this by mounting a Raspberry Pi "Raspbian" image on /mnt on my system. If I try to run /mnt/bin/echo hello, like this:
qemu-arm /mnt/bin/echo hello
I get a similar error:
/lib/ld-linux-armhf.so.3: No such file or directory
I can provide an explicit path to the dynamic linker like this:
qemu-arm /mnt/lib/ld-linux-armhf.so.3 /mnt/bin/echo hello
Now I get a different error:
/mnt/bin/echo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
That's actually great, because that is a normal "I can't find my shared libraries" error, and the solution is to use LD_LIBRARY_PATH. Rather than setting this in our environment, we can set this in the environment created by qemu-arm with the -E flag:
qemu-arm -E LD_LIBRARY_PATH=/mnt/lib/arm-linux-gnueabihf/ /mnt/lib/ld-linux-armhf.so.3 /mnt/bin/echo hello
Which gets me the output:
hello
I suspect that these same two techniques -- providing an explicit path to the linker, and providing an explicit library search path in LD_LIBRARY_PATH -- may help you out. Let me know how it works!
/system/bin/linker is the Android dynamic linker, so you need a directory with the Android dynamic linker and dynamic libraries, not one for Linux (which is what /usr/arm-linux-gnueabi will be). You should be able to pull the relevant files out of your firmware image, I expect.

Makefile for C code

I inherited a code which has a makefile, but so far I was unable to run it on a linux server. The main complain of the compiler is that it is unable to load libgmp.so.3 : error while loading shared libraries: libgmp.so.3. I know that libgmp.so.10 exists on this server, but I was wondering which part of the makefile needs to be changed so the compiler looks for libgmp.so.10 rather than libgmp.so.3.
OPTFLAG = -O2 -Wall -fPIC -fexceptions -DNDEBUG
LDFLAGS = -O2 -Wl,-no_compact_unwind -DNDEBUG -lm -pthread
COMPILER = gcc ${OPTFLAG}
LINKER = gcc ${LDFLAGS}
# CPLEX directory
CPLEX_HOME = /opt/ibm/ILOG/CPLEX_Studio1263/cplex
CPLEX_INC = ${CPLEX_HOME}/include/
CPLEX_LIB = ${CPLEX_HOME}/lib/x86-64_linux/static_pic/ -lcplex
# Compile the main file
code: code.c
${COMPILER} -c code.c -o code.o -I${CPLEX_INC}
${LINKER} -o code code.o -L${CPLEX_LIB}
clean::
rm -f *.o
rm -f ${LIB}/*.o
rm -f *~
rm -f ${SRC}/*~ ${INCLUDE}/*~
You need to rebuild whatever program or library uses libgmp.so.3 from source code. Could you provide the exact command run by make and the error message it produces?
EDIT The problem here is that the system has installed a version of the IBM CPLEX software which comes with its own GCC binary, and that GCC binary uses libgmp.so.3. The easiest way to fix this would be to upgrade the CPLEX software to a version which supports the operating system being used, or use the software on the operating system for which it was written (i.e., something really old that actually ships libgmp.so.3).
The most easy way it to install libgmp-dev package, from your linux distribution. GMP is a package library to do multiple precision calculations on large integers, which is probably needed by your program. As you put in some comments, adding -L/usr/lib64/libgmp.so.10 is an error, as -L option allows to add a directory to search for libraries, and not a specific library.
If only the library is needed and no header file is missing in your compilation (this is something strange, but sometimes happen) then you can still link with only the libgmp.so.10 object, but you have to do in a something nasty way. Just add /usr/lib64/libgmp.so.10 as an object file (not a library, with -l option) to your link command.
EDIT
From looking more closely your Makefile I see no reference to the libgmp.so.3 library, so I only can assume this is a indirect reference from some other already compiled library that comes from outside with your package. Just use
ldd lib<nameOfLibrary>.so.x.x
with all the libraries needed by your final executable, so see which shared objetc is the one that requests libgmp.so.3 soname, and then recompile it, reinstall it, or use your system's libraries ONLY, and not mesh anymore with libraries coming from another system. For example you can try (this is an expensive command, but it will get the answer)
find / -name "lib*.so.*" -print | xargs ldd > all_libs.lddout
and then find all_libs.lddout to see which library uses libgmp.so.3 (this will be the outdated library) You'll need to deinstall it or upgrade it, to be able to continue.
Linux systems have a library version system that allows an executable to be able to load different versions of the same library and allow them to live together in the same system. One of two: or you are able to locate the sources of version 3 of the shared libgmp.so.3 library and install it on your system, or you'll need to update the libraries your program uses to be able to link with the libgmp.so.10 already installed on your system.
2ND EDIT
As I see in the comments, you have changed the default compiler on your system by another coming possibly from other linux distribution (as your installed library is libgmp.so.10 while the one cc1 requests is libgmp.so.3, which is not installed on your system.
Installing a different compiler from the one you have installed, and doing that without previously deinstalling the other compiler, can lead you to this kind of problems.
The most reliable thing you can do is to reinstall the compiler from your distribution, or better, reinstall the whole linux system, as you have probably broken many things that will be emerging as you use your system. There's very poor info on what you have done to go further in your problem. Anyway, my recommendation is to not use the comment parts to add new information about your problem, just edit your question and add all those new information to it.

Build 'libconfig' as a 32-bit library

I am trying to use the libconfig (http://www.hyperrealm.com/libconfig/ ) for a little utility I am trying to write. I am trying to build libconfig then copy the library file (libconfig.a) to my utility's directory. When I build my utility I get warnings about the architecture being incompatible. Here is one of the specific warning messages I receive.
/usr/bin/ld: warning: i386:x86-64 architecture of input file 'libconfig.a(libconfig_la-libconfig.o)' is incompatible with i386 output
I am building on a Red Hat Enterprise Linux Server release 5.10 machine (uname -m produces 'x86_64'). I tried building libconfig with the following:
configure --disable-cxx CFLAGS='-m32' LDFLAGS='-m32'
But unfortunately, this didn't seem to produce the correct library as I still see the same warnings. There are other utilities that are created during the build process and all utilities share make common make directives which are specifying CFLAGS = -m32 -Wextra -Wall -Werror -Os and LDFLAGS = -m32, so I am unable to change this behavior.
I have also tried configure --disable-cxx CFLAGS='-arch i386' LDFLAGS='-arch i386, but this command line will not build the library.
Does anyone know how to build the libconfig as a 32-bit library to be consumed correctly.
Thanks,
Mark
The configure script will ignore arguments like CFLAGS= when passed on the command line. You need to set them for the invocation of configure, i.e. something like:
env CFLAGS=-m32 LDFLAGS=-m32 ./configure --disable-cxx
When this is done, all the symbols listed in the resulting lib/.libs/libconfig.a are listed with 32-bit addresses when the library is rebuilt.
Note in the configure script help output it does say:
Some influential environment variables:
which means that they need to be environment variables, not passed in as parameters to the command

Overcome DLL Hell with Code::Blocks

I'm using Code::Blocks for a project. I have not used an IDE on Linux in years, so I'm a bit out of touch with Linux IDEs.
I'm working with an OpenSSL project that uses FIPS validated library. I duplicated the GCC compiler toolchain and modified it to use OpenSSL's fipsld (and set it as default).
When the project's code executes under Code::Blocks via F8, FIPS_mode_set fails with error 252104805 (0xF06D065). 0xF06D065 is:
$ openssl errstr 0xF06D065
error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supported
which tells me Code::Blocks is not using the OpenSSL I specified in /usr/local/ssl/lib. Rather, the program is using the non-FIPS library provided by Debian in /usr/lib/x86_64-linux-gnu/.
An image of the link library settings is below. Note that the libraries are fully specified, and nothing is left to chance.
CodeBlocks is clearly doing things with LD_LIBRARY_PATH (shown below).
I've also verified the project is using the correct search directories - /usr/local/ssl/include for headers and /usr/local/ssl/lib for the linker.
With compiler logging set to "Full Command Line" set, here's what I get from the build log:
-------------- Build: Debug in ac ---------------
Compiling: main.cpp
/home/jwalton/Desktop/ac/main.cpp:8:5: warning: unused parameter ‘argc’ [-Wunused-parameter]
/home/jwalton/Desktop/ac/main.cpp:8:5: warning: unused parameter ‘argv’ [-Wunused-parameter]
Linking console executable: bin/Debug/ac
Output size is 569.67 KB
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 2 warnings
I'm aware of Basile Starynkevitch's suggestions on rpath's and LD_PRELOAD tricks, but this seems like one of those things the IDE should be handling for me (Visual Studio will handle it properly, and even gives us an input box to set Working Directories to find additional libraries).
Any ideas how to make Code::Blocks use the shared objects in /usr/local/ssl/lib when executing the program under the debugger?
Your IDE instructs the compiler to link against the specified libraries, but not to load them at run time. For this latter thing to happen, you need to pass another option to the linker, namely
-rpath=/path/to/directory/with/your/libraries
or, if the linker is invoked by the compiler,
-Wl,-rpath=/same/thing
Code::Blocks don't use shared objects (DLL are a Windows thing). Because Code::Blocks is simply an IDE. IDEs are glorified source code editors with the ability to run external software development tools. You could (and sometimes you should, at least to learn how things happen) edit your code with a plain good editor like emacs, and build it with commands. Your IDE is just running commands, notably a compiler and a linker, probably using gcc
So what is using shared objects in /usr/local/ssl/lib/ is the compiler and linker (and the runtime dynamic linker). BTW, /usr/local/ssl/lib/ is a very strange name for a directory containing shared objects; you should have configured OpenSSL to be installed in /usr/local/lib/ !
First, I really believe you should reconfigure and recompile and rebuild and reinstall your SSL to get it installed under /usr/local/ (or perhaps /opt/) prefix (i.e. shared libraries in /usr/local/lib).
Then you could add appropriate options for the ld linker (from binutils). You probably want -L/usr/local/ssl/lib (to the gcc command which is running ld), and you may want to pass -Wl,-rpath (see this).
I would suggest to reinstall your SSL in /usr/local/, add /usr/local/lib/ into /etc/ld.so.conf (or at least into your LD_LIBRARY_PATH...) and run ldconfig
Otherwise, add at least /usr/local/ssl/lib/ in front of your LD_LIBRARY_PATH (and also -L/usr/local/ssl/lib/ to your linking command).
Read Program Library HowTo, the answers to this, and Drepper's How To Write Shared libraries paper.
Just open the terminal and type
export LD_LIBRARY_PATH=/path/to/your/libraries
sudo ldconfig

How to created a shared library (dylib) using automake that JNI/JNA can use?

How do I convince LibTools to generate a library identical to what gcc does automatically?
This works if I do things explicitly:
gcc -o libclique.dylib -shared disc.c phylip.c Slist.c clique.c
cp libclique.dylib [JavaTestDir]/libclique.dylib
But if I do:
Makefile libclique.la (which is what automake generates)
cp .libs/libclique.1.dylib [JavaTestDir]/libclique.dylib
Java finds the library but can't find the entry point.
I read the "How to create a shared library (.so) in an automake script?" thread and it helped a lot. I got the dylib created with a -shared flag (according to the generated Makefile). But when I try to use it from Java Native Access I get a "symbol not found" error.
Looking at the libclique.la that is generated by Makefile it doesn't seem to have any critical information in it, just looks to be link overloads and moving things around for the convenience of subsequent C/C++ compiler steps (which I don't have), so I would expect libclique.1.dylib to be a functioning dynamic library.
I'm guessing that is where I'm going wrong, but, given that JNA links directly to a dylib and is not compiled with it (per the example in the discussion cited above), it seems all the subsequent compilation steps described in the LibTools manual are moot.
Note: I'm testing on a Mac, but I'm going to have to do this on Windows and Linux machines also, which is why I'm trying to put this into Automake.
Note2: I'm using Eclipse for my Java development and, yes, I did import the dylib.
Thanks
You should be building a plugin and in particular pass
libclique_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
This way you tell libtool you want a dynamically loadable module rather than a shared library (which for ELF are the same thing, but for Mach-O are not.)

Resources