hasherezade / pe-sieve

Scans a given process. Recognizes and dumps a variety of potentially malicious implants (replaced/injected PEs, shellcodes, hooks, in-memory patches).
https://hshrzd.wordpress.com/pe-sieve/
BSD 2-Clause "Simplified" License
3.09k stars 432 forks source link

Linking with libpe-sieve.a fails (MinGW) #71

Open hillu opened 4 years ago

hillu commented 4 years ago

Hi,

when trying to build this simple no-op program t.c

#include "pe_sieve_api.h"
int main() {
  PEsieve_params pp = {0};
  PESieve_scan(pp);
}

…using this following Makefile…

CC=x86_64-w64-mingw32-g++
CFLAGS=-I_pe-sieve/include
LDFLAGS=-L_pe-sieve -lpe-sieve
_t/t: _t/t.c
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

…I get the following error:

x86_64-w64-mingw32-g++ -I_pe-sieve/include -o _t/t _t/t.c -L_pe-sieve -lpe-sieve
/usr/bin/x86_64-w64-mingw32-ld: /tmp/ccGImspX.o:t.c:(.text+0x76): undefined reference to `__imp_PESieve_scan'
collect2: error: ld returned 1 exit status
make: *** [Makefile:6: _t/t] Error 1

Seems to me like PESieve_scan is not a visible symbol.

Adding a __declspec(dllexport) to PESIEVE_API_FUNC seems to fix the linker error, but I am not at all sure if this is the right way.

(After that the linker complained about missing symbols from -llibpeconv and ultimately about missing symbols that could be resolved using -lpsapi -lntdll -lshlwapi, but the main issue was the non-visible PESieve_scan symbol.)

hillu commented 4 years ago

Uh, I think I got the solutionn wrong. If make sure that neither dllimport nor dllexport are seen by the C++ compiler, I can build the static library and link against it. Seems that there's nothing wrong with the static library itself but with pe_sieve_api.h as it is processed as included from t.c.

hasherezade commented 4 years ago

Thank you for reporting. I am currently very busy, but I will fix it as soon as I will get a bit free. Can you please share as many details as possible on the full process of how are you building it, so that I can reproduce it quickly?

hillu commented 4 years ago

I think the only missing piece is the script I used to fetch and build pe-sieve in the subdirectory _pesieve that is referenced in the Makefile:

#!/bin/sh

set -e

test -d _pe-sieve \
    || git clone --recurse-submodules https://github.com/hasherezade/pe-sieve _pe-sieve
cd _pe-sieve

cmake . \
    -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
    -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
    -DCMAKE_SYSTEM_NAME=Windows-GNU \
    -DPESIEVE_AS_STATIC_LIB=1

make -j4
hasherezade commented 4 years ago

hi, can you please try again after my last updates? I tried it on my side and it seems to work...

linked

hillu commented 4 years ago

With a freshly-checked-out pe-sieve (1fa2fd18fe2a87acdea1ace98e403dedda666a7a) and libpeconv (8cbfef1d10e2d5cf05f81be101d050e9f0094693), I can confirm that libpe-sieve.a gets built. (This hadn't been a problem anyway when I reported this issue.)

However, it still cannot be linked against my little test porgram:

$ make -f Makefile.t
x86_64-w64-mingw32-g++ -I_pe-sieve/include -o _t/t _t/t.c -L_pe-sieve -lpe-sieve
/usr/bin/x86_64-w64-mingw32-ld: /tmp/cclLZtTs.o:t.c:(.text+0x76): undefined reference to `__imp_PESieve_scan'
collect2: error: ld returned 1 exit status
make: *** [Makefile.t:5: _t/t] Error 1
hasherezade commented 4 years ago

thanks for checking. it is weird because it managed to build Hollows Hunter using this script, and had no linking problems. can you share a script that you used for building your test app? I will keep trying...

jpohls1 commented 1 year ago

I'm running into the same issue. Here is a full script to reproduce the error:

#!/bin/sh

set -e
set -x

git clone --depth=1 --recurse-submodules https://github.com/hasherezade/pe-sieve pe-sieve
cd pe-sieve

cmake . \
    -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
    -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
    -DCMAKE_SYSTEM_NAME=Windows-GNU \
    -DPESIEVE_AS_STATIC_LIB=1
# Second cmake call is necessary, otherwise make fails with
# make[2]: windres: No such file or directory
cmake .

make -j`nproc`

cat <<EOT > test.cpp
#include "pe_sieve_api.h"
int main() {
  PEsieve_params pp = {0};
  PESieve_scan(pp);
}
EOT

x86_64-w64-mingw32-g++ -I./include -L. -lpe-sieve test.cpp

At the end, it fails with:

/usr/bin/x86_64-w64-mingw32-ld: /tmp/ccIxfGFH.o:test.cpp:(.text+0x3b): undefined reference to `__imp_PESieve_scan'
collect2: error: ld returned 1 exit status
jpohls1 commented 1 year ago

I figured it out, here is the full command line to link statically with MinGW for anyone else struggling:

x86_64-w64-mingw32-g++ -DPESIEVE_STATIC_LIB=1 -I./include test.cpp -L. -L./libpeconv/libpeconv/ -lpe-sieve -llibpeconv -lpsapi -lntdll -lshlwapi -limagehlp