Closed dwendt closed 8 months ago
I recently (do not hold this against me, I will forever deny it) helped someone to install JtR on some Windoes gear. I tried using your (@claudioandre-br) latest binary and did just that - copied a known-good nvidia OpenCL.dll
right over cygOpenCL-1.dll
. Worked like a champ (but not until that). Good lord knows I was relieved.
Given all of the above and the recent reminder in #5262, I wonder if we can workaround the issue by somehow linking against OpenCL.dll
instead of cygOpenCL.dll
(or is it cygOpenCL-1.dll
). As I understand. right now we link against -lOpenCL
, so the usage of cygOpenCL.dll
(or cygOpenCL-1.dll
) is added implicitly by Cygwin. Can we bypass that by usage of different options to the linker? If not, or not easily, then maybe we should add a step where we use e.g. sed -i
to patch the library name in the already-linked binary? Luckily, cygOpenCL.dll
is longer than OpenCL.dll
, so we should be able to replace one string by the other plus several NUL bytes. @claudioandre-br or anyone else who's on Windows (maybe @boulevard-h from #5262 as someone who ran into this issue most recently?), can you please give this a try? Thank you!
This seems to do what's needed, but I did not actually test on Windows (just checked that the file is changed the way I want, on two Linux systems with different versions of sed
and different locales):
LC_CTYPE=C sed -rbi 's/cygOpenCL-1\.dll(.)/OpenCL.dll\1\1\1\1\1\1/' john.exe
Please test and let us all know. If this works as desired, then let's get it into our build procedure for Cygwin (perhaps into the configure
-generated Makefile
and into Makefile.legacy
).
I'm afraid this is not a good solution as we also need to package the cygWin library (otherwise error in non-OpenCL environments).
The example below will show where the devil lives:
C:\Temp\debug> run\john --test --format=nt-opencl
Device 1: gfx902 [AMD Radeon(TM) Vega 8 Graphics]
Benchmarking: NT-opencl [MD4 OpenCL/mask accel]... LWS=64 GWS=2048 (32 blocks) x2470 DONE
Raw: 1170M c/s real, 6911M c/s virtual
C:\Temp\debug> del run\cygOpenCL-1.dll
C:\Temp\debug> dir run\cyg*.dll
[...]
8 file(s) 7.180.198 bytes
# => john useless
C:\Temp\debug> run\john --test --format=nt
C:/Temp/debug/run/john-best.exe: error while loading shared libraries: cygOpenCL-1.dll: cannot open shared object file: No such file or directory
C:\Temp\debug> run\john --help
C:/Temp/debug/run/john-best.exe: error while loading shared libraries: cygOpenCL-1.dll: cannot open shared object file: No such file or directory
C:\Temp\debug> copy c:\Windows\System32\OpenCL.dll c:\Windows\System32\cygOpenCL-1.dll
# Admin is required.
# => Now we have a valid and functional OpenCL library, please don't worry about the name.
C:\Temp\debug> run\john --test --format=nt-opencl
Device 1: gfx902 [AMD Radeon(TM) Vega 8 Graphics]
Benchmarking: NT-opencl [MD4 OpenCL/mask accel]... LWS=64 GWS=16384 (256 blocks) x2470 DONE
Raw: 1489M c/s real, 29880M c/s virtual
What if we have some cygwin OpenCL DLL in run folder:
#=> Copy the CygWin original cygOpenCL-1.dll to the run folder.
C:\Temp\debug> dir run\cyg*.dll
[...]
01/01/2018 09:55 110.099 cygOpenCL-1.dll
[...] 9 files(s) 7.290.297 bytes
C:\Temp\debug> run\john --test --format=nt-opencl
No OpenCL devices found
I'm afraid this is not a good solution as we also need to package the cygWin library (otherwise error in non-OpenCL environments).
I think I get what you mean, even though your examples don't really show it - this would matter for Windows systems that don't have c:\Windows\System32\OpenCL.dll
, and it would prevent usage of our CPU formats, which otherwise should work even on such systems. (That nt-opencl
fail, like in your examples, is of less importance - on such systems, it'd have failed anyway, just differently. However, if you ran e.g. run\john --test --format=nt
, it'd also bump into the error while loading shared libraries
, which would actually make john
useless.)
Is c:\Windows\System32\OpenCL.dll
in fact optional on modern Windows, or do modern versions of Windows provide it even when there are no OpenCL device drivers installed? Would it be sane for us to assume that any 64-bit Windows has this DLL?
e.g.
run\john --test --format=nt
, it'd also bump into the error while loading shared libraries, which would actually make john useless.)
100% useless, not even a run\john --help
.
do modern versions of Windows provide it even when there are no OpenCL device drivers installed?
Well, I don't know, but I can uninstall stuff, so I would say that's a dangerous assumption. But we should call people to comment on the matter.
[edited]
In fact, we can use AWS Amazon EC2 T2 (Free Tier) to verify this. I'll do that when I have my security keys in hand.
Skimming https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order I see that "Known DLLs" are of higher priority than those in "The folder from which the application loaded." So if OpenCL.dll
is listed in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
, then we can get around the issue just brought up by @claudioandre-br above by shipping a copy of Cygwin's cygOpenCL-1.dll
renamed to OpenCL.dll
in the current directory, for it to be used as fallback when the system does not have its own copy of OpenCL.dll
. OTOH, I don't know if it's commonly or ever the case that OpenCL.dll
is listed among known ones even when it's missing?
If OpenCL.dll
isn't "known", then unfortunately our program directory's version of it will take precedence over the system's, which is not what we want here.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
Starting with 'O' only 2 files: ole*.dll
.
Just to document it here, another way to fix it:
C:\WINDOWS\System32\DriverStore\FileRepository\u0357645.inf_amd64_3c66802dbd4d45a0\B357435\amdocl64.dll
(if you are using https://github.com/openwall/john-packages) Inside the main john folder you will find a subdirectory called etc
C:\Temp\debug> dir etc\OpenCL\vendors\*
[...]
Folder C:\Temp\debug\etc\OpenCL\vendors
02/04/2023 18:25
- Edit the `.icd` file and point it to the correct vendor DLL file. Just put the DLL full name inside the file.
echo 'C:\WINDOWS\System32\DriverStore\FileRepository\u0357645.inf_amd64_3c66802dbd4d45a0\B357435\amdocl64.dll' > etc\OpenCL\vendors\amd.icd
[1] A very good and easy to remember place to save a library.
On Linux, we use something awful like `/lib` and a symbolic link.
- Edit the
.icd
file and point it to the correct vendor DLL file. Just put the DLL full name inside the file.
Apparently, we could automate that by reading the registry and writing to Cygwin's .icd
file (we could do this in john
or in a separate program, and would need to inform the user of us making such changes outside of our program tree). See: https://github.com/openwall/john/issues/3191#issuecomment-508086364
What is the problem with:
In the configure script. If we are under Cygwin and OpenCL is supported:
In the configure script. If we are under Cygwin and OpenCL is supported:
* copy the file C:\Windows\System32\OpenCL.dll to JtR's run directory, renaming it to cygOpenCL-1.dll * If no file exists we print a warning/error
This only works for those building from source on the very machine where they intend to run. Most Windows users will probably run our pre-built binary distribution instead.
I actually thought of doing something like this in john.exe
, so it'd work right starting from the second invocation of it - but I'd prefer us finding/implementing a cleaner solution.
This only works for those building from source on the very machine where they intend to run. Most Windows users will probably run our pre-built binary distribution instead.
I understand. Question. How does JtR manage the distribution of OpenCL-supported JtR on Linux on systems without libOpenCl.so?
The solution that I guess gives the most compatibility is to not link to OpenCL statically, create a *.c file with all the OpenCL functions, and implement them as a hub to the pointer of functions dynamically loaded. If we are lucky the compiler will inline most of them and we probably only need to check if the pointers are good on the couple of OpenCL functions that you can call at the beginning.
How does JtR manage the distribution of OpenCL-supported JtR on Linux on systems without libOpenCl.so?
It does not, and there's not as much need for that. Packages for Linux typically target a specific distro/version and have dependencies on other packages specified in them. As an alternative for that, @claudioandre-br provides Flatpak and Snap packages, which bundle their dependencies. Anyway, we recommend building for Linux from source, and the releases on JtR homepage are currently only source tarballs except for Windows, where we do provide binary builds.
The solution that I guess gives the most compatibility is to not link to OpenCL statically, create a
*.c
file with all the OpenCL functions, and implement them as a hub to the pointer of functions dynamically loaded. If we are lucky the compiler will inline most of them and we probably only need to check if the pointers are good on the couple of OpenCL functions that you can call at the beginning.
Right, I think (but am not sure) this is similar to what hashcat does (please take a look). I was thinking we'd use an .h
file with macros wrapping around dlsym
, but I don't mind wrapper functions as well (can also be static inline
ones in an .h
file). I'm not worried about performance since OpenCL calls shouldn't be frequent (if they are, we have a problem anyway).
So if you're willing to proceed to try and implement this, please go ahead. Thank you very much!
I think (but am not sure) this is similar to what hashcat does (please take a look).
@alainesp See https://github.com/openwall/john/issues/3191#issuecomment-508119262
I'm not worried about performance since OpenCL calls shouldn't be frequent (if they are, we have a problem anyway).
That said, we should cache dlsym
results. The overhead of a function call doesn't worry me much, but the overhead of redoing a symbol lookup by name could be too great.
How does JtR manage the distribution of OpenCL-supported JtR on Linux on systems without libOpenCl.so?
It does not, and there's not as much need for that. Packages for Linux typically target a specific distro/version and have dependencies on other packages specified in them. As an alternative for that, @claudioandre-br provides Flatpak and Snap packages, which bundle their dependencies.
Could you do that? Reference a supposed driver library from a Linux package manager? I was under the impression that the OpenCL support was installed by the GPU driver, at least on Windows.
Could you do that? Reference a supposed driver library from a Linux package manager?
I think the auto-generated dependency would be on libOpenCL.so.1
or such, and e.g. on Debian/Ubuntu that can be provided by https://packages.debian.org/sid/ocl-icd-libopencl1 - which is just the loader - or by the actual GPU driver package. You could also add various dependencies manually (such as to require a specific OpenCL backend installed via the package manager), but that's inconvenient and not normally done.
Anyway, I think we should go for the dlopen
approach for Windows, and when we have it then also use it on Linux (which would also provide more debugging/testing of it).
I think we should go for the
dlopen
approach for Windows, and when we have it then also use it on Linux
We now have initial implementation of this in #5386 by @alainesp - thank you, Alain!
- Locate the vendor's OpenCL dll file. In my case it is [1]:
C:\WINDOWS\System32\DriverStore\FileRepository\u0357645.inf_amd64_3c66802dbd4d45a0\B357435\amdocl64.dll
If there are several directories with the DLL library, use the one with the most recent date on C:\WINDOWS\System32\DriverStore\FileRepository
It might also be possible to use the ObjectListView component of Driver Store Explore where it is possible to access the directory with the dll of AMD-OpenCL User Mode Driver:
Thank you @mainmind83, but none of this should be needed now that we've merged @alainesp's #5386 and there's a new Windows build at https://github.com/openwall/john-packages/releases/tag/jumbo-dev also linked from the "Download Windows Build" badge in README.md
in this repo. So I'll close this issue as completed. We already had some people report that those changes have helped, but it'd be great if you @mainmind83 also test and let us know in here (it's OK to add comments to a closed issue).
It was still open 🥲 It's working without edit .icd file but appear warning:
john.exe --test --format=nt-opencl
Device 1: gfx1031 [AMD Radeon RX 6700 XT]
Benchmarking: NT-opencl [MD4 OpenCL/mask accel]... Build log: warning: argument unused during compilation: '-I opencl' [-Wunused-command-line-argument]
1 warning generated.
Build log: warning: argument unused during compilation: '-I opencl' [-Wunused-command-line-argument]
1 warning generated.
LWS=128 GWS=327680 (2560 blocks) x9500 DONE
Raw: 36402M c/s real, 6031G c/s virtual
Thank you for testing this @mainmind83!
The Build log: warning: argument unused during compilation: '-I opencl'
is a separate (non-)issue related to our fix of #4335, which was #4373. I'm surprised by this warning, though, since opencl/nt_kernel.cl
does include a few other files and we're only chdir
'ing to the run
directory, not inside opencl
. Maybe that's an extra reason for us to chdir
to run/opencl
instead, like we discussed in https://github.com/openwall/john/pull/4938#issuecomment-992621520
Edit: Upon a second thought, I am not surprised by the warning. Perhaps the newer/better OpenCL runtimes are looking for the #include "..."
files in the same directory with the file that includes them, like it would be in C. However, we historically had problems with this not happening, which is why we added the -I
(with a different path back then).
This bug initially started with
clGetPlatformIDs
returning-1001
which isCL_PLATFORM_NOT_FOUND_KHR
and john dies which is wrong/bad.hashcat on the same system detects the platform fine using literally the same function. The only conclusion I can come to is that hashcat is doing something correctly in their build, and john is not.
Steps to reproduce
john.exe --list=opencl-devices
with a card that's restricted to OCL 1.2 platform (this should work fine with 2.1/2.2 headers...)System configuration
windows enterprise 10.0.16299.19, 64-bit
root cause
cygOpenCL-1.dll
is really bad. JTR should never use that, and instead prefer OpenCL.dll in the loadlibrary path.cygOpenCL-1.dll
: https://hashcat.net/forum/thread-6187-post-32962.htmlalmost working after replacing the junk cygopencl DLL
POSIX shared memory objects require the existance of this directory. Create the directory '/dev/shm' and set the permissions to 01777. For instance on the command line: mkdir -m 01777 /dev/shm initUnicode(UNICODE, UTF-8/ISO-8859-1) UTF-8 -> UTF-8 -> UTF-8 Device 0@konata: GeForce GTX 970 Using default input encoding: UTF-8 Loaded 1 password hash (dmg-opencl, Apple DMG [PBKDF2-SHA1 OpenCL 3DES/AES]) Cost 1 (iteration count) is 270270 for all loaded hashes Will run 8 OpenMP threads Loaded 7 hashes with 7 different salts to test db from test vectors Options used: -I /run/kernels -cl-mad-enable -DSM_MAJOR=5 -DSM_MINOR=2 -cl-nv-verbose -DGPU -DDEVICE_INFO=262162 -DSIZEOF_SIZE_T=8 -DDEV_VER_MAJOR=391 -DDEV_VER_MINOR=1 -D_OPENCL_COMPILER -DHASH_LOOPS=753 -DOUTLEN=32 -DPLAINTEXT_LENGTH=64 -DV_WIDTH=1 $JOHN/kernels/pbkdf2_hmac_sha1_kernel.cl Build log::46:10: fatal error: 'opencl_device_info.h' file not found
include "opencl_device_info.h"
Error -11 building kernel $JOHN/kernels/pbkdf2_hmac_sha1_kernel.cl. DEVICE_INFO=262162 OpenCL CL_BUILD_PROGRAM_FAILURE (-11) error in common-opencl.c:1111 - clBuildProgram failed.