Open zeroSteiner opened 1 year ago
I noticed that Windows Server 2008 x64 (WoW64) and Windows Vista x86 have the same issue.
Loading metsrv.x86.dll on Windows XP SP3 the entry point GetThreadId
could not be located in the dynamic link library KERNEL32.dll
Windows XP SP3 version: 5.1.2600
According to the documentation this API is available from Windows Vista for Desktop Edition, and Windows Server 2003.
The API is static imported because it's used by create_remote_thread
in remote_thread.c
I guess other api could be not available in Windows Xp.
That sounds unrelated to this issue. If we're trying to import GetThreadId
, that'd likely fail regardless of if the build is from MinGW or MSVC. @wolfcod are you experiencing this issue with the MinGW build? We don't ship it so you'd had have to have built it yourself or obtained it from somewhere else.
I read reflective loader source code and there are no checks if any api is available or not. I will build with mingw and try again.. thanks
@zeroSteiner I built metsrv.x86.dll with mingw on Linux, and the issue is somehow same of GetThreadId.
Building with MSVC using v141xp toolchain is working (with or without a patch for GetThreadId, because the ReflectiveLoader doesn't check the return value of GetProcAddress).
Building with MingW doesn't work, in other words, when you're trying to load metsrv.x86.dll in a process via reflective loader or using a simple LoadLibrary there is an error due a symbol not resolved rightly.
The function server_setup
in c/meterpreter/source/metsrv/server_setup.c
uses OpenThreadToken, an API available on Windows XP according to MSDN.
OpenThreadToken in MSVC build is imported from ADVAPI32.dll (the documentation says ADVAPI32.lib/ADVAPI32.dll) but in MingW build this API is imported from KERNEL32.dll, so when the server is initialized, there is an access violation when the function is called, because not resolved in the reflectiveloader, and the return value of GetProcAddress is NULL.
I guess somehow you should use an old release of MingW to build for Windows XP, or to resolve dynamically OpenThreadToken from ADVAPI32, which will be solved as symbol forward KERNEL32.OpenThreadToken in new OS and ADAVAPI32.OpenThreadToken on Windows XP.
I can submit a patch ASAP, but how I can apply the new build to metasploit-framework to use it? Is there any way to apply a different build to GEM files?
@zeroSteiner I built metsrv.x86.dll with mingw on Linux, and the issue is somehow same of GetThreadId.
Building with MSVC using v141xp toolchain is working (with or without a patch for GetThreadId, because the ReflectiveLoader doesn't check the return value of GetProcAddress).
Building with MingW doesn't work, in other words, when you're trying to load metsrv.x86.dll in a process via reflective loader or using a simple LoadLibrary there is an error due a symbol not resolved rightly.
The function
server_setup
inc/meterpreter/source/metsrv/server_setup.c
uses OpenThreadToken, an API available on Windows XP according to MSDN.OpenThreadToken in MSVC build is imported from ADVAPI32.dll (the documentation says ADVAPI32.lib/ADVAPI32.dll) but in MingW build this API is imported from KERNEL32.dll, so when the server is initialized, there is an access violation when the function is called, because not resolved in the reflectiveloader, and the return value of GetProcAddress is NULL.
I guess somehow you should use an old release of MingW to build for Windows XP, or to resolve dynamically OpenThreadToken from ADVAPI32, which will be solved as symbol forward KERNEL32.OpenThreadToken in new OS and ADAVAPI32.OpenThreadToken on Windows XP.
I can submit a patch ASAP, but how I can apply the new build to metasploit-framework to use it? Is there any way to apply a different build to GEM files?
Hello @wolfcod, did you inspect the PE to determinate the import of OpenThreadToken
is expected from kernel32.dll
?
By reading the mingw-w64 source, I would expect it loaded from advapi32.dll
anyway.
Check this out
And specifically this
Hi @dledda-r7, yes I did. I inspected metsrv.x86.dll built using mingw on ubuntu 22.
The symbol OpenThreadToken is present on both dll (kernel32 and advapi32) for x86 target, but is missing from kernel32 in x86_64 library.
The problem came from CMakeLists.txt. The symbol LINK_LIBS override the default order used by gcc/ld to link libraries with object files.
In the standard build, the sequence is: kernel32, user32... advapi32 (the order is stored into linklibs.rsp generated by cmake during the build in ~/c/meterpreter/workspace/build/mingw-x86/${project}/CMakeFiles/${project}.dir/linklibs.rsp, and the symbol (in x86 build) is present in kernel32 before inspecting advapi32.
Adding advapi32 in set(LINK_LIBS, advapi32, .....) in CMakeLists for metsrv and extensions forces CMake to generate a linklibs.rsp where advapi32 is duplicated (I guess is present by default in CMAKE) but also present before kernel32 in gcc parameters for ld, generating a metsrv.x86.dll where OpenThreadToken is present but imported directly from ADVAPI32.dll instead of KERNEL32.dll
Hi @dledda-r7, yes I did. I inspected metsrv.x86.dll built using mingw on ubuntu 22.
The symbol OpenThreadToken is present on both dll (kernel32 and advapi32) for x86 target, but is missing from kernel32 in x86_64 library.
The problem came from CMakeLists.txt. The symbol LINK_LIBS override the default order used by gcc/ld to link libraries with object files.
In the standard build, the sequence is: kernel32, user32... advapi32 (the order is stored into linklibs.rsp generated by cmake during the build in ~/c/meterpreter/workspace/build/mingw-x86/${project}/CMakeFiles/${project}.dir/linklibs.rsp, and the symbol (in x86 build) is present in kernel32 before inspecting advapi32.
Adding advapi32 in set(LINK_LIBS, advapi32, .....) in CMakeLists for metsrv and extensions forces CMake to generate a linklibs.rsp where advapi32 is duplicated (I guess is present by default in CMAKE) but also present before kernel32 in gcc parameters for ld, generating a metsrv.x86.dll where OpenThreadToken is present but imported directly from ADVAPI32.dll instead of KERNEL32.dll
Thanks a lot for the analysis! probably the best way is, as you said, to modify the linking order instead of modify metsrv + extensions to resolve the function dynamically.
Hi @dledda-r7, yes I did. I inspected metsrv.x86.dll built using mingw on ubuntu 22. The symbol OpenThreadToken is present on both dll (kernel32 and advapi32) for x86 target, but is missing from kernel32 in x86_64 library. The problem came from CMakeLists.txt. The symbol LINK_LIBS override the default order used by gcc/ld to link libraries with object files. In the standard build, the sequence is: kernel32, user32... advapi32 (the order is stored into linklibs.rsp generated by cmake during the build in ~/c/meterpreter/workspace/build/mingw-x86/${project}/CMakeFiles/${project}.dir/linklibs.rsp, and the symbol (in x86 build) is present in kernel32 before inspecting advapi32. Adding advapi32 in set(LINK_LIBS, advapi32, .....) in CMakeLists for metsrv and extensions forces CMake to generate a linklibs.rsp where advapi32 is duplicated (I guess is present by default in CMAKE) but also present before kernel32 in gcc parameters for ld, generating a metsrv.x86.dll where OpenThreadToken is present but imported directly from ADVAPI32.dll instead of KERNEL32.dll
Thanks a lot for the analysis! probably the best way is, as you said, to modify the linking order instead of modify metsrv + extensions to resolve the function dynamically.
Both issue (GetThreadId and OpenThreadToken) fixed in https://github.com/rapid7/metasploit-payloads/pull/712
I noticed this while testing #631 and it appears to be unrelated to #630. It also seems to be related to the Meterpreter core and not any of the extensions as I can reproduce it with
AutoLoadStdapi
disabled (to avoid #630).