Cracking the Davinci Resolve Studio 18.5 and 19.0 license check by patching a single bit

Published:
Last edit:

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.

Activating license The key entered does not appear to be valid

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

Activation failed callback

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

Activation callback

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)

Ghidra before patch Ghidra after patch

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.

ImHex patching

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!

Has been successfully activated

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

patch-resolve18.sh

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

patch-resolve19.sh

Update 2024-07-07: version 19.0b4 changed the pattern again. Here is an updated patch script:

patch-resolve19b4.sh

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)

ImHex pattern search