Cracking the Davinci Resolve Studio 18.5 and 19.0 license check by patching a single bit
NOTE: This blog was written for 18.5, but it also applies for 18.6 and 19.0 with some minor changes. See conclusions for patch scripts.
So I was trying out Davinci Resolve on Linux, and no matter how hard I tried to make it work, it wouldn’t display my OBS recorded videos.
After some searching, I found out that the DNxHD codec worked, but it requires about 2 GB/min of storage, so it wouldn’t work for me.
After some more searching, I found this Reddit post and this Davinci Resolve document. Turns out H264 and H265 don’t work specifically on Linux and specifically on the free version, AAC doesn’t work on Linux at all, and all of this is due to some licensing bullshit. I was pissed.
I tried to find a Linux crack, but the best that I’ve found was for 18.1 or something, so I decided to try and crack it myself.
Note that I’m using Arch Linux and the davinci-resolve-studio AUR package, but this should work for any Linux distro.
Searching for the offending file
After launching Davinci Resolve Studio, I’m presented with a license activation window. Trying out a random key doesn’t work, but it gives us a couple of strings and tells us that it probably uses a server to verify the key.
Let’s try searching for them
$ grep -R 'Activating license' /opt/resolve
grep: /opt/resolve/libs/Fusion/libfusionsystem.so: binary file matches
grep: /opt/resolve/bin/BlackmagicRawAPI: No such file or directory
grep: /opt/resolve/bin/resolve: binary file matches
$ grep -R 'The key entered does not appear to be valid' /opt/resolve
grep: /opt/resolve/libs/Fusion/libfusionsystem.so: binary file matches
grep: /opt/resolve/bin/BlackmagicRawAPI: No such file or directory
grep: /opt/resolve/bin/resolve: binary file matches
It looks like either libfusionsystem.so
or resolve
handle license checking. I’ll start with resolve
since it’s our entry binary.
Disassembling with Ghidra
I gave Ghidra this rather large (510 MiB) file for analysis and waited for a few hours…
And waited a few more hours…
Eventually, I gave up and stopped the analysis. It seems to have disassembled the functions, and I didn’t have the patience to wait an entire day for it to complete.
Search
-> For Strings...
, press Search
, filter for The key entered does not appear to be valid
Go to definition, change type to TerminatedCString
, go to XREF, open decompile
After going through a few DAT_xxxxxxxx
labels and changing their types to string, the function started to look a lot like a failure callback. I named it appropriately
The function had this string later on: Unable to connect to the server. Please check your internet connection.
This confirms that a server is used for key verification
After going through this function’s XREFs in a similar way, one function caught my eye
It calls our failure callback in one branch and has strings like Start DaVinci Resolve
and Has been successfully activated. %1
in the other.
Patching
I decided to try and patch param_2 != 0
to param_2 == 0
to see what happens.
I went into assembly view, found this jump instruction, pressed right click, Patch Instruction
, and changed JZ
(jump if zero) to JNZ
(jump if not zero)
After that, I tried to export the patched binary with Ghidra, but the resulting binary was too different. So I decided to change the instruction with a hex editor.
Don’t forget to subtract Ghidra’s base address from the instruction address!
Running
After saving changes from the hex editor and trying an invalid key again, to my surprise, the patch worked!
The program launched without issues, and I was able to use my H264 videos.
The AAC codec still doesn’t work, but this is a lot better than before.
Conclusions
This patch isn’t perfect because Davinci requires the key on each launch, but it is very easy. There is probably a way to hack this with mitmproxy or something similar, but I didn’t look into it.
I haven’t looked into libfusionsystem.so
at all, but everything seems to work okay. I’ll probably update this blog post if I notice something fishy.
Here is a small patch script using pattern searching if you don’t want to bother with reverse engineering
Update 2024-05-19: version 19.0b1 has changed some license related functions, so it needed a new pattern.
I also get some undefined symbol issues, so now I have to launch resolve like this:
LD_PRELOAD="/usr/lib/libgio-2.0.so /usr/lib/libgmodule-2.0.so /usr/lib/libglib-2.0.so" /opt/resolve/bin/resolve
Update 2024-07-07: version 19.0b4 changed the pattern again. Here is an updated patch script:
Also, if your screen is too small, you can use hax11 to remove the minimum size requirements. This will slightly break the UI, but it will make the program a lot more usable.
Please message me on Steam if you found this useful :)
And here is the pattern if you’re struggling with the script for some reason:
55 41 56 53 48 83 EC 20 49 89 FE 85 F6 0F 84 ?? ?? ?? ?? 81 FE 13 FC FF FF 0F 85
offset 14 bytes (0x0E)